这似乎是一个微不足道的问题,但是我能想到的所有明显的解决方案都有自己的缺陷。
我们想要的是能够为新记录设置任何默认的 ActiveRecord 属性值,以使其在验证之前和期间可读并且不干扰用于搜索的派生类的方式。
一旦我们实例化类,就需要设置默认值并准备好,以便(new MyModel)->attr返回默认attr值。
以下是一些可能性和他们遇到的问题:
A)在
MyModel覆盖该方法并在为 trueinit()时分配默认值,如下所示:isNewRecordpublic 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)在验证期间使用
DefaultValidatorinrules()设置默认属性值,如下所示:public function rules() { return [ [ 'attr', 'default', 'value' => 'defaultValue', 'on' => 'insert', // instantiate model with this scenario ], // ... ]; }问题:与 B) 和 C) 相同。在我们实际保存或验证记录之前,不会设置值。
那么设置默认属性值的正确方法是什么?有没有其他方法没有概述的问题?