Yii2:如何在 ActiveRecord 中设置默认属性值?

Yii2: How to set default attribute values in ActiveRecord?

这似乎是一个微不足道的问题,但我能想到的所有显而易见的解决方案都有其自身的缺陷。

我们想要的是能够仅为新记录设置任何默认的 ActiveRecord 属性值,以使其在验证之前和期间可读并且不干扰用于搜索的派生 classes 的方式.

一旦实例化 class,就需要设置默认值并准备好,以便 (new MyModel)->attr returns 默认 attr 值。

以下是一些可能性及其存在的问题:

那么设置默认属性值的正确方法是什么?有没有其他方法没有概述的问题?

你的问题我看了好几遍,觉得有些矛盾。
您希望默认值在验证之前和期间可读,然后您尝试 init()beforeSave()。因此,假设您只想在模型中设置默认值,以便它们可以在生命周期的一部分中尽可能长时间地存在并且不干扰派生 类,只需在初始化对象后设置它们。

您可以准备单独的方法,其中设置了所有默认值并显式调用它。

$model = new Model;
$model->setDefaultValues();

或者您可以创建静态方法来创建模型并设置所有默认值和return它的实例。

$model = Model::createNew();

或者您可以将默认值传递给构造函数。

$model = new Model([
    'attribute1' => 'value1',
    'attribute2' => 'value2',
]);

这与直接设置属性没有太大区别。

$model = new Model;
$model->attribute1 = 'value1';
$model->attribute2 = 'value2';

一切都取决于您希望模型对控制器的透明程度。

这种方式是为整个生命周期设置属性,直接初始化除外,它不会干扰派生搜索模型。

我知道有人回答了,但我会添加我的方法。 我有 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();
    }

有两种方法可以做到这一点。

$model => new Model();

现在 $model 具有数据库 table 中的所有默认属性。

或者在您的规则中您可以使用:

[['field_name'], 'default', 'value'=> $defaultValue],

现在 $model 将始终使用您指定的默认值创建。

您可以在此处查看核心验证器的完整列表 http://www.yiiframework.com/doc-2.0/guide-tutorial-core-validators.html

您可以准备单独的方法,其中设置了所有默认值并显式调用它。

$model = new Model;
if($model->isNewRecord())
    $model->setDefaultValues();

只需像这样重写模型中的 __construct() 方法:

class MyModel extends \yii\db\ActiveRecord {

    function __construct(array $config = [])
       {
           parent::__construct($config);
           $this->attr = 'defaultValue';
       }
    ...
}

这是 Yii 臃肿的多用途 ActiveRecords 的挂断

依我拙见,表单模型、活动记录和搜索模型最好拆分成单独的 classes/subclasses

为什么不拆分搜索模型和表单模型?

abstract class Creature extends ActiveRecord {
    ...
}

class CreatureForm extends Creature {

    public function init() {
        parent::init();
        if ($this->isNewRecord) {
            $this->number_of_legs = 4;
        }
    }
}

class CreatureSearch extends Creature {

    public function search() {
        ...
    }
}

这种方法的好处是

  • 您可以轻松满足不同的验证、设置和显示情况,而无需求助于一堆 ifs 和开关
  • 您仍然可以在父级中保留通用代码 class 以避免重复
  • 您可以对每个子项进行更改class,而不必担心它会如何影响另一个子项
  • 个人 class 不需要知道他们任何 siblings/children 的存在就可以正常工作

事实上,在我们最近的项目中,我们使用的搜索模型根本没有从相关的 ActiveRecord 扩展

如果你想从数据库加载默认值,你可以把这段代码放在你的模型中

 public function init()
 {
    parent::init(); 
    if(!method_exists($this,'search')) //for checking this code is on model search or not
    {
        $this->loadDefaultValues();
    }
 }