PHP / Phalcon – Автоматически вложенные объекты

Скажем, у меня три таблицы:

CREATE TABLE divisions { idDivision INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR (40) NOT NULL } CREATE TABLE clubs { idClub INT NOT NULL AUTO_INCREMENT PRIMARY KEY, idDivision INT NOT NULL, name VARCHAR(40) NOT NULL } CREATE TABLE footballers ( idFootballer INT NOT NULL AUTO_INCREMENT PRIMARY KEY, idClub INT NOT NULL, name VARCHAR (40) NOT NULL ) 

И у меня есть некоторые прекрасные модели Phalcon, чтобы представить их.

Теперь я хотел бы сделать это:

 $divisions = new Divisions(); print json_encode($divisions::findFirst(), JSON_NUMERIC_CHECK); 

И это возвращает объект JSON примерно так:

 { idDivision: 1, name: "Welsh Premier League", clubs: [ { idClub: 1, idDivision: 1, name: "Airbus UK", players: [ { idPlayer: 1, idClub: 1, name: "Alf Jones" }, ... ] }, .. ] } 

Есть ли простой способ сделать это с помощью модели Phalcon? 🙂

Solutions Collecting From Web of "PHP / Phalcon – Автоматически вложенные объекты"

Чтобы получить вложенные модели, автоматически используйте эту рекурсивную функцию.

  $getRelations = function($model, $namespace, $alias = null, $instances = null) use (&$getRelations) { $modelsManager = $model->getModelsManager(); $relations = $modelsManager->getRelations($namespace); if (is_null($instances)) { $response = $model->toArray(); } if (count($relations)) { // loop relations foreach ($relations as $i => $relation) { $options = $relation->getOptions(); // get alias if (isset($options['alias'])) { $subAlias = $options['alias']; $modelName = $relation->getReferencedModel(); $subModel = new $modelName(); // get from model if (is_null($alias) && count($model->{$subAlias})) { $response[$subAlias] = $getRelations( $subModel, $modelName, $subAlias, $model->{$subAlias} ); // get from object instance } elseif (count($instances)) { foreach ($instances as $k => $instance) { $response[$k] = $instance->toArray(); $response[$k][$subAlias] = $getRelations( $subModel, $modelName, $subAlias, $instance->{$subAlias} ); } } } } } else { $response = $instances->toArray(); } return $response; }; 

Вы можете назвать это следующим образом:

 $model = new Division::findFirst($divisionId); $namespace = 'AppName\Models\Division'; $data = $getRelations($model, $namespace); $this->response->setJsonContent($data); 

Убедитесь, что вы определяете псевдоним для каждой вложенной модели следующим образом:

 class Division extends \Phalcon\Mvc\Model { public function initialize() { $this->hasMany('id', 'AppName\Models\Club', 'division_id', array( 'alias' => 'clubs' )); } } 

ОБНОВИТЬ

Используйте вместо этого код (поместите его в свою базовую модель). Этот новый код позволит вам получать отношения на новой (пустой) модели.

 public function getModelName() { return get_called_class(); } public function toArray($columns = null, $isRelated = false) { return !$isRelated ? parent::toArray($columns) : $this->_toArrayRelations(); } private function _toArrayRelations() { $getRelations = function($model, $instances = null) use (&$getRelations) { $hasInstances = count($instances); $modelsManager = $model->getModelsManager(); $relations = $modelsManager->getRelations($model->getModelName()); if (!$hasInstances) { $response = $model->toArray(); } if (count($relations)) { // loop relations foreach ($relations as $i => $relation) { $options = $relation->getOptions(); // get alias if (isset($options['alias'])) { $subAlias = $options['alias']; $modelName = $relation->getReferencedModel(); $subModel = new $modelName(); $subModelRelation = $model->{$subAlias}; // get from model if (!$hasInstances) { $response[$subAlias] = $getRelations( $subModel, $subModelRelation ); // get from object instance } else { foreach ($instances as $k => $instance) { $response[$k] = $instance->toArray(); $response[$k][$subAlias] = $getRelations( $subModel, $instance->{$subAlias} ); } } } } } elseif ($hasInstances) { foreach ($instances as $k => $instance) { $response[$k] = $instance->toArray(); } } return $response; }; return $getRelations($this); } 

С контроллера также легче позвонить.

 $model = new Division::findFirst($divisionId); $data = $model->toArray(null, 1); $this->response->setJsonContent($data);