我正在编写一个小部件,我想避免用户将代码添加到他们的模型中(我知道它会更容易但是用它来学习新东西)。
您是否知道是否可以向模型添加属性(不在您的数据库中,因此它将是虚拟的)并为该属性添加规则?您无权更改该型号代码。
我知道规则是一个数组。在过去,我使用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”,所以我想避免这种情况。还有其他想法吗?没有扩展他们的模型怎么做?
答案 0 :(得分:6)
如果要在运行时将动态属性添加到现有模型中。然后你需要一些自定义代码,你需要:一个Model-Class和一个扩展类,它将执行动态部分并且具有保存动态信息的数组。这些数组将在所需函数中与Model-Class的返回数组合并。
这是一种模型,它没有完全正常工作。但也许你知道你需要做什么:
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?