Скажем, у меня три таблицы:
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? 🙂
Чтобы получить вложенные модели, автоматически используйте эту рекурсивную функцию.
$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);