这似乎是一个微不足道的问题,但是我能想到的所有明显的解决方案都有自己的缺陷。
我们想要的是能够为新记录设置任何默认的 ActiveRecord 属性值,以使其在验证之前和期间可读并且不干扰用于搜索的派生类的方式。
一旦我们实例化类,就需要设置默认值并准备好,以便(new MyModel)->attr
返回默认attr
值。
以下是一些可能性和他们遇到的问题:
A)在
MyModel
覆盖该方法并在为 trueinit()
时分配默认值,如下所示:isNewRecord
public function init() { if ($this->isNewRecord) { $this->attr = 'defaultValue'; } parent::init(); }
问题:搜索。除非我们明确地取消设置我们的默认属性
MySearchModel
(非常容易出错,因为它太容易忘记),否则这也会在调用search()
派生MySearchModel
类之前设置值并干扰搜索(attr
属性已经设置,因此搜索将返回结果不正确)。在 Yii1.1 中,这是通过在调用unsetAttributes()
之前调用来解决的search()
,但是在 Yii2 中不存在这样的方法。B)在
MyModel
覆盖这样的beforeSave()
方法:public function beforeSave($insert) { if ($insert) { $this->attr = 'defaultValue'; } return parent::beforeSave(); }
问题:未保存的记录中未设置属性。
(new MyModel)->attr
是null
。更糟糕的是,即使是其他依赖此值的验证规则也无法访问它,因为在验证后beforeSave()
调用。C)为了确保值在验证期间可用,我们可以重写该
beforeValidate()
方法并在那里设置默认值,如下所示:public function beforeValidate() { if ($this->isNewRecord) { $this->attr = 'defaultValue'; } return parent::beforeValidate(); }
问题:在未保存(未验证)的记录中仍未设置属性。
$model->validate()
如果我们想获得默认值,我们至少需要调用。D)在验证期间使用
DefaultValidator
inrules()
设置默认属性值,如下所示:public function rules() { return [ [ 'attr', 'default', 'value' => 'defaultValue', 'on' => 'insert', // instantiate model with this scenario ], // ... ]; }
问题:与 B) 和 C) 相同。在我们实际保存或验证记录之前,不会设置值。
那么设置默认属性值的正确方法是什么?有没有其他方法没有概述的问题?