Php 如何使用Zend Framework 2中带有映射器的Zend\Db\TableGateway处理具有(嵌套)列表的多维输出?
我正在开发一个基于RESTful ZF2的应用程序,并将TableGateway实现(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) {
<?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 ....
}