«Домашка» по Yii2

от автора

Не так давно был написан хаб о «подводных камнях и ракушках» 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]; } 

Конечно же код не идеален (отсутствие php-doc), ну и многие задались сразу же вопросом — «а как быть с доп условиями (andWhere, orderBy, indexBy, …)»? Но я, к сожалению не буду затрагивать в данной статье этот вопрос, т.к. это всего лишь наброски мыслей.
Трейт решит проблему со статическим свойством — уникальным для класса модели.

Создание связей

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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *