2014-11-25 55 views
2

说我有三个表:PHP /尔康 - 自动嵌套对象

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 
) 

而且我有一些可爱的尔康模型来表示这些。

现在,我想这样做是做到这一点:

$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" 
    }, 
    ... 
    ] 
}, 
.. 
] 
} 

有没有一种简单的方法与尔康做到这一点模型? :)

回答

2

要获取嵌套模型会自动使用此递归函数。

$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' 
     )); 
    } 
} 

UPDATE

使用下面的代码tead(把它放在你的基础模型里面)。这个新代码将允许您在新的(空的)模型上获取关系。

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); 
+0

我还没有测试过(所以没有被接受),但是谢谢 - 我认为这会非常有用! :) – 2015-06-03 13:23:09