如何在Zend Framework 2中使用带有映射器的Zend \ Db \ TableGateway处理带有(嵌套)列表的多维输出? [英] How to handle multidimensional output with (nested) lists using the Zend\Db\TableGateway with a mapper in Zend Framework 2?

查看:80
本文介绍了如何在Zend Framework 2中使用带有映射器的Zend \ Db \ TableGateway处理带有(嵌套)列表的多维输出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发基于RESTful ZF2的应用程序,并将TableGateway实现(Zend\Db\TableGateway的子类)与模型的简单映射器结合使用,类似于

I'm developing a RESTful ZF2 based application and using a TableGateway implementation (subclass of the Zend\Db\TableGateway) in combination with a simple mapper for the model, similar to the Album example of the ZF2 manual.

表类

<?php
namespace Courses\Model;

use ...

class CourseTable {

    protected $tableGateway;

    public function __construct(TableGateway $tableGateway) {
        $this->tableGateway = $tableGateway;
    }

    public function findOnceByID($id) {
        $select = new Select();
        $where = new Where();
        $select->columns(array(
            'id',
            'title',
            'details',
        ));
        $select->from($this->tableGateway->getTable());
        $select->where($where, Predicate::OP_AND);
        $resultSet = $this->tableGateway->selectWith($select);
        return $resultSet;
    }

}

映射器类

<?php
namespace Courses\Model;

use ...

class CourseDetails implements ArraySerializableInterface {

    public $id;
    public $title;
    public $details;

    public function exchangeArray(array $data) {
        $this->id      = (isset($data['id'])) ? $data['id'] : null;
        $this->title   = (isset($data['title'])) ? $data['title'] : null;
        $this->details = (isset($data['details'])) ? $data['details'] : null;
    }

    public function getArrayCopy() {
        return get_object_vars($this);
    }

}

控制器

<?php
namespace Courses\Controller;

use ...

class CoursesController extends RestfulController // extends AbstractRestfulController
{
    protected $acceptCriteria = array(
        'Zend\View\Model\JsonModel' => array(
            'application/json',
        ),
        'Zend\View\Model\FeedModel' => array(
            'application/rss+xml',
        ),
    );

    private $courseTable;

    public function get($id)
    {
        $course = $this->getCourseTable()->findOnceByID($id)->current();
        $viewModel = $this->acceptableViewModelSelector($this->acceptCriteria);
        $viewModel->setVariables(array('data' => array(
            'id' => $courseDetails->id,
            'title' => $courseDetails->title,
            'details' => $courseDetails->details
        )));
        return $viewModel;
    }

    ...

}

它适用于像这样的浅输出:

It's working for a shallow output like this:

{
   "data":{
      "id":"123",
      "title":"test title",
      "details":"test details"
   }
}

但是现在我需要一个带有嵌套列表的多维输出:

But now I need a multidimensional output with nested lists like this:

{
    "data":{
        "id":"123",
        "title":"test title",
        "details":"test details",
        "events":{
            "count":"3",
            "events_list":[ <- main list
                {
                    "id":"987",
                    "date":"2013-07-20",
                    "place":"Berlin",
                    "trainers":{
                        "count":"1",
                        "trainers_teamid":"14",
                        "trainers_teamname":"Trainers Team Foo",
                        "trainers_list":[ <- nested list
                            {
                                "id":"135",
                                "name":"Tom"
                            }
                        ]
                    }
                },
                {
                    "id":"876",
                    "date":"2013-07-21",
                    "place":"New York",
                    "trainers":{
                        "count":"3",
                        "trainers_teamid":"25",
                        "trainers_teamname":"Trainers Team Bar",
                        "trainers_list":[ <- nested list
                            {
                                "id":"357",
                                "name":"Susan"
                            },
                            {
                                "id":"468",
                                "name":"Brian"
                            },
                            {
                                "id":"579",
                                "name":"Barbara"
                            }
                        ]
                    }
                },
                {
                    "id":"756",
                    "date":"2013-07-29",
                    "place":"Madrid",
                    "trainers":{
                        "count":"1",
                        "trainers_teamid":"36",
                        "trainers_teamname":"Trainers Team Baz",
                        "trainers_list":[ <- nested list
                            {
                                "id":"135",
                                "name":"Sandra"
                            }
                        ]
                    ]
                }
            ]
        }
    }
}

如何/应该在哪里将数据组装到此结构?直接在映射器中,以便包含整个数据吗?还是我应该通过多个数据库请求来处理这个问题,并且将控制器中的结构设置为如此?

How / where should I assemble the data to this structure? Directly in the mapper, so that it contains the whole data? Or should I handle this with multiple database requests anb assemple the structure in the controller?

推荐答案

您要完成的工作与TableGateway-模式无关.通过TableGateway-Pattern可以访问一个指定表的数据.这是为什么在ZF2中不再选择findDependantRowsets()的原因之一.这样做根本不是TableGateways的工作.

What you are trying to accomplish has nothing to do with the TableGateway-Pattern. The TableGateway-Pattern is there to gain access to the Data of one specified Table. This is one of the reasons why in ZF2 you no longer have the option to findDependantRowsets(). It's simply not the TableGateways Job to do so.

要实现您想要的目标,您有两种选择:

To achieve what you are looking for you have pretty much two options:

您可以编写一个大查询来连接所有各自的表,然后将输出手动映射为所需的JSON格式.

You could write a big query that joins all respective tables and then you'd manually map the output into your desired JSON Format.

性能稍差的方法(从SQL的角度看),但是更容易"将其映射"到您的JSON格式.

A little less performant approach (looking at the SQL side of things) but "easier" to "map" into your JSON Format.

为了提供一些见识,Doctrine默认情况下会使用多重查询方法. (我猜!)主要是为了提供可以在每个数据后端上可用的功能,而不仅仅是几个SQL版本...

To give some insight, Doctrine would go with the multiple query approach by default. This is mostly (i guess!) done to provide features that would work on every data backend possible rather than just a couple of SQL Versions...

由于您想知道json/数组的组装方式,因此我会像这样设置

Since you're wondering about the assembling of the json / array, i would set it up like this

'service_manager' => array(
    'factories' => array(
        'MyEntityService' => 'Mynamespace\Service\Factory\MyEntityServiceFactory'
    )
)

// MyEntityServiceFactory.php
// assuming you only need one dependency! more lines for more dependencies ;)
class MyEntityServiceFactory implements FactoryInterface {
    public function createService(ServiceLocatorInterface $serviceLocator) {
        return new MyEntityService($serviceLocator->get('YourTableGateway'));
    }
}

// Your SERVICE Class
class MyEntityService {
    // do constructor and stuff to handle dependency

    public function someBigQueryAsArray() {
        // Query your Gateway here and create the ARRAY that you want to return,
        // basically this array should match your json output, but have it as array
        // to be used for other stuff, too
    }
}

// lastly your controller
public function someAction() {
    $service = $this->getServiceLocator()->get('MyEntityService');
    $data = $service->someBigQueryAsArray();

    // do that viewmodel selector stuff

    // ASSUMING $data is a array of more than one baseObject
    // i did this in my app to produce the desired valid json output, there may be better ways...
    if ($viewModel instanceof JsonModel) {
        foreach($data as $key => $value) {
            $viewModel->setVariable($key, \Zend\Json\Json::encode($value));
        }
        return $viewModel;
    }

    // Handle other ViewModels ....
}

这篇关于如何在Zend Framework 2中使用带有映射器的Zend \ Db \ TableGateway处理带有(嵌套)列表的多维输出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆