【问题标题】:Yii2. Adding attribute and rule dynamically to modelYii2.动态添加属性和规则到模型
【发布时间】:2016-11-16 08:06:23
【问题描述】:

我正在编写一个小部件,我想避免用户向他们的模型添加代码(我知道这会更容易,但用它来学习新东西)。

您知道是否可以将属性(不在您的数据库中,因此它将是虚拟的)添加到模型并为该属性添加规则?您无权更改该型号代码。

我知道规则是一个数组。过去,我使用 array_merge 合并了父类的规则。可以在外部完成吗? Yii2 有方法吗?

一个想法是在我的小部件内使用“模型”扩展用户提供的模型并在那里使用:

    public function init() {
      /*Since it is extended this not even would be necessary, 
      I could declare the attribute as usual*/

      $attribute = "categories";
      $this->{$attribute} = null; //To create attribute on the fly

      parent::init();
    }

    public function rules() {
      $rules = [...];

      //Then here merge parent rules with mine.
      return array_merge(parent::rules, $rules);
    }

但是如果我扩展它,当我在 ActiveForm 中使用该模型作为复选框时,它将使用我的“CustomModel”,所以我想避免这种情况。还有其他想法吗?如何在不扩展他们的模型的情况下做到这一点?

【问题讨论】:

    标签: php yii yii2


    【解决方案1】:

    为现有模型添加动态属性

    当您想在运行时向现有模型添加动态属性时。然后您需要一些自定义代码,您需要:一个模型类和一个扩展类,它将执行动态部分并具有保存动态信息的数组。这些数组将与模型类的返回数组合并到所需的函数中。

    这是一种样机,它没有完全发挥作用。但也许你知道你需要做什么:

    class MyDynamicModel extends MyNoneDynamicModel
    {
    
    private $dynamicFields = [];
    private $dynamicRules = [];
    
    public function setDynamicFields($aryDynamics) {
         $this->dynamicFields = $aryDynamics;
    }
    
    public function setDynamicRules($aryDynamics) {
         $this->dynamicRules = $aryDynamics;
    }
    
    public function __get($name)
    {
        if (isset($this->dynamicFields[$name])) {
            return $this->dynamicFields[$name];
        }
    
        return parent::__get($name);
    }
    
    public function __set($name, $value)
    {
    if (isset($this->dynamicFields[$name])) {
      return $this->dynamicFields[$name] = $value;
    }
    return parent::__set($name, $value);
    }
    
    public function rules() {
      return array_merge(parent::rules, $this->dynamicRules);
    }
    }
    

    全动态属性

    当所有属性都是动态的并且您不需要数据库时。然后使用 Yii2 新的DynamicModel。该文档还指出:

    DynamicModel 是一个模型类,主要用于支持即席数据验证。

    这里是来自 Yii2-Wiki 的完整 example with form integration,所以我在这里不做例子。

    虚拟属性

    当您想向模型添加属性时,该属性不在数据库中。然后只需在模型中声明一个公共变量:

    public $myVirtualAttribute;
    

    然后你可以像其他(数据库)属性一样在规则中使用它。

    要做Massive Assignment,别忘了在模型规则中添加安全规则:

    public function rules()
    {
        return [
            ...,
            [['myVirtualAttribute'], 'safe'],
            ...
        ];
    }
    

    这里很好地解释了这样做的原因: Yii2 non-DB (or virtual) attribute isn't populated during massive assignment?

    【讨论】:

    • 感谢您的回答。理想情况下,我想要实现的是从模型外部添加虚拟属性 $myVirtualAttribute 及其规则。扩展模型是我正在考虑的一个可能的解决方案:)
    • 啊,好吧。您的意思是动态属性。
    • 是的,完全正确。我将编辑我的问题以使用该名称
    • 我看到你已经更新了你的答案。我的模型是从 ActiveRecord 扩展的,但我想添加它的任何动态属性,可以实现吗?
    • 是的,我在 yii 中做到了,我正在更新我的答案。
    猜你喜欢
    • 2015-09-05
    • 1970-01-01
    • 2018-06-27
    • 2015-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多