Yii2:如何在ActiveRecord中设置默认属性值? [英] Yii2: How to set default attribute values in ActiveRecord?

查看:385
本文介绍了Yii2:如何在ActiveRecord中设置默认属性值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This may seem like a trivial question, however all of the obvious solutions that I can think of have their own flaws.

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

What we want is to be able to set any default ActiveRecord attribute value for new records only, in a way that makes it readable before and during validation and does not interfere with derived classes used for search.

实例化类后,需要立即设置值,以便(new MyModel)-> attr 返回默认的 attr 值。

The default values need to be set and ready as soon as we instantiate the class, so that (new MyModel)->attr returns the default attr value.

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

Here are some of the possibilities and the problems they have:


  • A) MyModel 中覆盖 init()方法并在 isNewRecord 为true时分配默认值,如下所示:

  • A) In MyModel override the init() method and assign default value when isNewRecord is true like so:

public function init() {
    if ($this->isNewRecord) {
        $this->attr = 'defaultValue';
    }
    parent::init();
}

问题:搜索。除非我们在 MySearchModel 中显式取消设置默认属性(容易出错,否则很容易出错),否则也会在调用之前设置该值。派生的 MySearchModel 类中的search()并干扰搜索( attr 属性将已经设置,因此搜索将返回不正确的结果)。在Yii1.1中,可以通过调用 unsetAttributes( ) ,然后调用 search(),但是Yii2中不存在这种方法。

Problem: Search. Unless we explicitly unset our default attribute in MySearchModel (very error-prone because it is too easy to forget), this will also set the value before calling search() in the derived MySearchModel class and interfere with searching (the attr attribute will already be set so search will be returning incorrect results). In Yii1.1 this was resolved by calling unsetAttributes() before calling search(), however no such method exists in Yii2.

B) MyModel 中覆盖 beforeSave() 方法如下:

B) In MyModel override the beforeSave() method like so:

public function beforeSave($insert) {
    if ($insert) {
        $this->attr = 'defaultValue';
    }
    return parent::beforeSave();
}

问题:未保存的记录中未设置属性。 (新MyModel)-> attr null 。更糟糕的是,即使其他依赖此值的验证规则也无法访问它,因为 beforeSave()在验证后称为

Problem: Attribute is not set in unsaved records. (new MyModel)->attr is null. Worse yet, even other validation rules that rely on this value will not be able to access it, because beforeSave() is called after validation.

C)为了确保该值在验证期间可用,我们可以改写 beforeValidate() 方法并在其中设置默认值,如下所示:

C) To ensure the value is available during validation we can instead override the beforeValidate() method and set the default values there like so:

public function beforeValidate() {
    if ($this->isNewRecord) {
        $this->attr = 'defaultValue';
    }
    return parent::beforeValidate();
}

问题:未保存的属性仍未设置(未验证)记录。如果要获取默认值,至少需要调用 $ model-> validate()

Problem: Attribute is still not set in unsaved (unvalidated) records. We need to at least call $model->validate() if we want to get the default value.

D)使用 <$ c rules()中的$ c> DefaultValidator 可以在验证期间设置默认属性值,例如:

D) Use DefaultValidator in rules() to set a default attribute value during validation like so:

public function rules() {
    return [
        [
            'attr', 'default',
            'value' => 'defaultValue',
            'on' => 'insert', // instantiate model with this scenario
        ],
        // ...
    ];
}

问题:与B)和C)相同。在我们实际保存或验证记录之前,不会设置值。

Problem: Same as B) and C). Value is not set until we actually save or validate the record.

那么设置默认属性值的正确方法?还有其他方法可以解决上面概述的问题吗?

So what is the right way to set default attribute values? Is there any other way without the outlined problems?

推荐答案

这与Yii肿的多功能ActiveRecords息息相关

This is a hangup with Yii's bloated multi-purpose ActiveRecords

在我看来,最好将表单模型,活动记录和搜索模型拆分为单独的类/子类

In my humble opinion the form models, active records, and search models would be better off split into separate classes/subclasses

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

Why not split your search models and form models?

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和switch

  • 您仍然可以在父类中保留通用代码以避免重复

  • 您可以对每个子类进行更改,而不必担心它将如何影响另一个子类

  • 各个班级不需要知道他们的兄弟姐妹/子女是否存在以正常运行

  • You can easily cater for different validation, set up and display cases without resorting to a bunch of ifs and switches
  • You can still keep common code in the parent class to avoid repetition
  • You can make changes to each subclass without worrying about how it will affect the other
  • The individual classes don't need to know about the existence of any of their siblings/children to function correctly

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

In fact, in our most recent project, we are using search models that don't extend from the related ActiveRecord at all

这篇关于Yii2:如何在ActiveRecord中设置默认属性值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆