我们想要的是能够仅为新记录设置任何默认的ActiveRecord属性值,使其在验证之前和验证期间可读,并且不会干扰用于搜索的派生类.
一旦我们实例化类,就需要设置和准备默认值,以便(new MyModel) – > attr返回默认的attr值.
以下是一些可能性和问题:
> A)在MyModel中覆盖init()方法并在isNewRecord为true时指定默认值,如下所示:
public function init() { if ($this->isNewRecord) { $this->attr = 'defaultValue'; } parent::init(); }
问题:搜索.除非我们在MySearchModel中显式取消设置我们的默认属性(因为它太容易忘记而非常容易出错),否则这也会在派生的MySearchModel类中调用search()之前设置值并干扰搜索(attr属性已经是设置所以搜索将返回不正确的结果).在Yii1.1中,这是通过在调用search()之前调用unsetAttributes()
来解决的,但是在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)在rules()中使用DefaultValidator
在验证期间设置默认属性值,如下所示:
public function rules() { return [ [ 'attr','default','value' => 'defaultValue','on' => 'insert',// instantiate model with this scenario ],// ... ]; }
问题:与B)和C)相同.在我们实际保存或验证记录之前,不会设置值.
我有Application和ApplicationSearch模型.在应用程序模型中,我添加init并检查当前实例.如果它的ApplicationSearch我跳过初始化.
public function init() { if(!$this instanceof ApplicationSearch) { $this->id = hash('sha256',123); } parent::init(); }
同样如@mae在下面评论你可以检查当前实例中是否存在搜索方法,假设你没有添加任何带有名称搜索的方法到非搜索基础模型,所以代码变为:
public function init() { // no search method is available in Gii generated Non search class if(!method_exists($this,'search')) { $this->id = hash('sha256',123); } parent::init(); }