Не так давно был написан хаб о «подводных камнях и ракушках» habrahabr.ru/post/254179 в котором было «домашнее задание» — ответ на которое так никто и не прислал, но думаю многие задавались вопросом — как все таки связывать модели из разных модулей. Хочу вам предложить вариант решения данной задачи.
«Наша банда», в составе 3 человек, пытается решать интересные задачки на данном фреймворке, в очередной раз, в свободное время — сели мы значит за кофе с печеньками и стали проверять «смысловую нагрузку» поговорки —
Одна голова — хорошо, но две лучше
В итоге у нас нарисовалась следующая «концепция по разработке зависимых модулей»:
1. Регистрировать релейшены для моделей должны модули;
2. Релейшены должны храниться в статическом свойстве модели;
3. Возможность добавления релейшенов в обе стороны (как на модульную модель, так и в модульной модели — обратная);
Добавление и хранение связей
protected static $relations = []; public static function addRelation($name, $targetClass, $link, $multiple = false) { self::$relations[$name] = [$targetClass, $link, $multiple]; }
Трейт решит проблему со статическим свойством — уникальным для класса модели.
Создание связей
public function getRelation($name, $throwException = true) { if (isset(self::$relations[$name])) { return $this->createRelation($name, $throwException); } return parent::getRelation($name, $throwException); } public function __get($name) { if (isset(self::$relations[$name]) && !$this->isRelationPopulated($name)) { $related = $this->getRelation($name)->findFor($name, $this); $this->populateRelation($name, $related); return $related; } return parent::__get($name); } protected function createRelation($name, $throwException = true) { $relation = self::$relations; if (!isset($relation[$name])) { if (!$throwException) { return null; } throw new InvalidCallException('Relation ' . $name . ' not find in class ' . get_class($this)); } $relation = $relation[$name]; $class = array_shift($relation); $query = $class::find(); $query->link = array_shift($relation); $query->multiple = array_shift($relation); $query->primaryModel = $this; return $query; }
подробнее смотрите [[yii\db\BaseActiveRecord::hasOne|hasMany]]
Объявление связей и их регистрация
в данном коде, рассмотрим пример из «домашки» — у пользователя несколько банковских аккаунтов (неймспейсы опустим для облегчения восприятия контента).
public $relations = [ 'User' => [ 'bankAccounts' => ['BankAccount', ['user_id' => 'id'], true] ], 'BankAccount' => [ 'user' => ['User', ['id' => 'user_id'], false] ], ]; protected static function registerRelations() { foreach ($this->relations as $owner => $relations) { foreach ($relations as $name => $relation) { list ($targetClass, $link, $multiple) = $relation; $owner::addRelation($name, $targetClass, $link, $multiple); } } }
Здесь мог быть «вывод» или «итог», но данный хаб думаю в этом не нуждается, прошу прощение за малую информативность о том, как это работает — думаю тут все прозрачно.
Жду критики, вопросов, предложений.
В скором времени будет создано и опубликовано расширение в публичном доступе, об этом будет сообщено в данном хабе и на русскоязычном yii форуме
п.с. родители в школу не пойдут — можете не вызывать
ссылка на оригинал статьи http://habrahabr.ru/post/256685/
Добавить комментарий