Yii2. Adding attribute and rule dynamically to model

后端 未结 1 1740
感动是毒
感动是毒 2021-02-09 22:22

I am writing a widget and I want to avoid user adding code to their model (I know it would be easier but using it to learn something new).

Do you know if it is possible

1条回答
  •  攒了一身酷
    2021-02-09 23:00

    Add Dynamic Attributes to a existing Model

    When you want to add dynamic attributes during runtime to a existing model. Then you need some custom code, you need: A Model-Class, and a extended class, which will do the dynamic part and which have array to hold the dynamic information. These array will merged in the needed function with the return arrays of the Model-Class.

    Here is a kind of mockup, it's not fully working. But maybe you get an idea what you need to do:

    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);
    }
    }
    

    Full Dynamic Attributes

    When all attributes are dynamic and you don't need a database. Then use the new DynamicModel of Yii2. The doc states also:

    DynamicModel is a model class primarily used to support ad hoc data validation.

    Here is a full example with form integration from the Yii2-Wiki, so i don't make a example here.

    Virtual Attributes

    When you want to add a attribute to the model, which is not in the database. Then just declare a public variable in the model:

    public $myVirtualAttribute;
    

    Then you can just use it in the rules like the other (database-)attributes.

    To do Massive Assignment don't forget to add a safe rule to the model rules:

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

    The reason for this is very well explained here: Yii2 non-DB (or virtual) attribute isn't populated during massive assignment?

    0 讨论(0)
提交回复
热议问题