2014-11-25 76 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