📜 ⬆️ ⬇️

Domashka by Yii2

Not so long ago, a post about “pitfalls and shells ” was written, in which there was a “homework assignment” - an answer to which no one sent, but I think many wondered how to link models from different modules. I want to offer you a solution to this problem.

“Our gang” consisting of 3 people is trying to solve interesting problems on this framework, once again, in our free time - we sat down for coffee with cookies and began to check the “meaning” of the saying -
One head is good, but two is better.

As a result, we drew the following "concept for the development of dependent modules":
1. Register relays for models should modules;
2. Relays must be stored in the static property of the model;
3. The possibility of adding relays in both directions (on the modular model, and in the modular model - the reverse);



Adding and storing links


protected static $relations = []; public static function addRelation($name, $targetClass, $link, $multiple = false) { self::$relations[$name] = [$targetClass, $link, $multiple]; } 

...
Of course, the code is not perfect (the absence of php-doc), and many immediately asked themselves the question - “what about additional conditions (andWhere, orderBy, indexBy, ...)”? But I, unfortunately, will not touch upon this question in this article, since it's just an outline of thoughts.
Treit solves the problem with a static property - unique to the model class.

Making connections


 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; } 

see [[yii \ db \ BaseActiveRecord :: hasOne | hasMany]] for details
')

Announcement of links and their registration


in this code, we will consider an example from “homework” - the user has several bank accounts (we omit neimspaces to facilitate the perception of the content).
 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); } } } 


There could be a “conclusion” or “result”, but I think this hub doesn’t need it, I apologize for the low information content on how this works - I think everything is transparent here.
Waiting for critics, questions, suggestions.
An extension in public access will soon be created and published, this will be reported in this hub and in the Russian yii forum

ps parents will not go to school - you can not call

Source: https://habr.com/ru/post/256685/


All Articles