本文介绍了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模型来代表这些模型.

And I have some lovely Phalcon models to represent those.

现在,我想做的是:

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

这将返回类似于以下内容的JSON对象:

And that return a JSON object something like:

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

是否有使用Phalcon模型执行此操作的简单方法? :)

Is there an easy way to do this with a Phalcon model? :)

推荐答案

要自动获取嵌套模型,请使用此递归函数.

To get the nested models automatically use this recursive function.

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

确保为每个嵌套模型定义别名,如下所示:

Make sure you define an alias for each nested model like so:

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

更新

请改用以下代码(将其放入基本模型中).此新代码将允许您获取新(空)模型上的关系.

Use the code below instead (put it inside your base model). This new code will allow you to fetch relations on a new (empty) model.

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

从控制器中调用也更容易.

It's also easier to call from the controller.

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

这篇关于PHP/Phalcon-自动嵌套对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-21 01:20