Php 如何使用Zend Framework 2中带有映射器的Zend\Db\TableGateway处理具有(嵌套)列表的多维输出?

Php 如何使用Zend Framework 2中带有映射器的Zend\Db\TableGateway处理具有(嵌套)列表的多维输出?,php,mapping,zend-framework2,datamapper,Php,Mapping,Zend Framework2,Datamapper,我正在开发一个基于RESTful ZF2的应用程序,并将TableGateway实现(Zend\Db\TableGateway的子类)与模型的简单映射器结合使用,类似于 表格类 <?php namespace Courses\Model; use ... class CourseTable { protected $tableGateway; public function __construct(TableGateway $tableGateway) {

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

表格类

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

}
但现在我需要一个多维输出,其中包含嵌套列表,如下所示:

{
   "data":{
      "id":"123",
      "title":"test title",
      "details":"test details"
   }
}
{
    "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"
                            }
                        ]
                    ]
                }
            ]
        }
    }
}
{
“数据”:{
“id”:“123”,
“标题”:“测试标题”,
“细节”:“测试细节”,
“事件”:{
“计数”:“3”,

“事件列表”:[您试图完成的任务与
TableGateway
-模式无关。TableGateway模式用于访问一个指定表的数据。这就是为什么在ZF2中您不再具有
FindPendantRowsets()选项的原因之一
。这样做根本不是TableGateways的工作

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

1.联接查询 您可以编写一个连接所有相应表的大查询,然后手动将输出映射到所需的JSON格式

2.多重查询 性能稍差的方法(从SQL方面看),但“更容易”映射到JSON格式

为了提供一些见解,原则默认情况下会使用多查询方法。这主要是(我想!)为了提供能够在每个数据后端上工作的功能,而不仅仅是几个SQL版本

服务等级 既然您想知道json/数组的组装,我就这样设置它

'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 ....
}

谢谢你的回答,Sam!我想,也许我的问题还不够。1.对于TableGateway模式:我写道,我在这里使用它,只是为了描述上下文:由TableGateway实现组成的模型(Zend\Db\TableGateway的子类
)+mapper.2.两种解决方案:是的,实际上有两种获取数据的方法。但我想了解的是,如何/在哪里(在哪个类中)组装数据(已经通过一个fat或多个较小的查询获取)对于此结构,使用嵌套列表创建复杂结构。@automatix服务类或您的控制器。我认为,方法是让服务返回您需要的适当数组(如上面分类的嵌套版本)您的控制器将根据请求处理数组。在控制器中组装会使控制器非常胖。但是“服务类”是什么意思?一个特殊的“汇编程序”/“组合程序”类?如果是:此类必须与表类通信,对吗?因此,当前正在控制器中执行的代码(
$This->getCourseTable()->findOnceByID($id)->current();
)还有一些类似的调用来获取子列表的数据——这段代码将移到这个汇编器类中,而控制器将只执行类似于
$courseasembler->getCourse()的操作
?我只是想确认一下,我是否正确地理解了您的意思。@automatix听起来好像您是对的,我用一个服务示例编辑了答案,虽然我返回了一个数组,当然您的服务也可以返回相应的json。。。
'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 ....
}