Не так давно был написан хаб о «подводных камнях и ракушках» habrahabr.ru/post/254179 в котором было «домашнее задание» — ответ на которое так никто и не прислал, но думаю многие задавались вопросом — как все таки связывать модели из разных модулей. Хочу вам предложить вариант решения данной задачи.
«Наша банда», в составе 3 человек, пытается решать интересные задачки на данном фреймворке, в очередной раз, в свободное время — сели мы значит закофе с печеньками и стали проверять «смысловую нагрузку» поговорки —
В итоге у нас нарисовалась следующая «концепция по разработке зависимых модулей»:
1. Регистрировать релейшены для моделей должны модули;
2. Релейшены должны храниться в статическом свойстве модели;
3. Возможность добавления релейшенов в обе стороны (как на модульную модель, так и в модульной модели — обратная);
подробнее смотрите [[yii\db\BaseActiveRecord::hasOne|hasMany]]
в данном коде, рассмотрим пример из «домашки» — у пользователя несколько банковских аккаунтов (неймспейсы опустим для облегчения восприятия контента).
Здесь мог быть «вывод» или «итог», но данный хаб думаю в этом не нуждается, прошу прощение за малую информативность о том, как это работает — думаю тут все прозрачно.
Жду критики, вопросов, предложений.
В скором времени будет создано и опубликовано расширение в публичном доступе, об этом будет сообщено в данном хабе и на русскоязычном yii форуме
п.с. родители в школу не пойдут — можете не вызывать
«Наша банда», в составе 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 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 форуме
п.с. родители в школу не пойдут — можете не вызывать