Я пишу виджет, и я хочу, чтобы пользователь не добавлял код в свою модель (я знаю, что было бы проще, но использовать его, чтобы узнать что-то новое).
Знаете ли вы, можно ли добавить в модель атрибут (который отсутствует в вашей базе данных, так что он будет виртуальным) и добавить правило для этого атрибута ?. У вас нет доступа к изменению этого кода модели.
Я знаю, что правила – это массив. В прошлом я объединил правила из родительского класса с помощью 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», поэтому я хочу этого избежать. Любые другие идеи? Как это сделать без расширения их модели?
Если вы хотите добавить динамические атрибуты во время выполнения к существующей модели. Затем вам нужен какой-то пользовательский код, вам нужны: 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 – это модельный класс, в основном используемый для поддержки проверки ad hoc.
Вот полный пример с интеграцией форм из Yii2-Wiki, поэтому я не приводил здесь пример.
Если вы хотите добавить атрибут к модели, которой нет в базе данных. Затем просто объявите общедоступную переменную в модели:
public $myVirtualAttribute;
Затем вы можете просто использовать его в правилах, как и другие атрибуты (database-).
Чтобы выполнить Massive Assignment , не забудьте добавить безопасное правило к правилам модели:
public function rules() { return [ ..., [['myVirtualAttribute'], 'safe'], ... ]; }
Причина этого очень хорошо объясняется здесь: Yii2 не-DB (или виртуальный) атрибут не заполняется во время массового присвоения?