3

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

表类

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

    ...

}

它适用于这样的浅输出:

{
   "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"
                            }
                        ]
                    ]
                }
            ]
        }
    }
}

我应该如何/在哪里将数据组装到这个结构中?直接在映射器中,让它包含整个数据?或者我应该用多个数据库请求处理这个并在控制器中组装结构?

4

1 回答 1

3

您要完成的工作与TableGateway-Pattern 无关。TableGateway-Pattern 用于访问一个指定表的数据。这就是在 ZF2 中您不再可以选择findDependantRowsets(). 这样做根本不是 TableGateways 工作。

为了实现您正在寻找的东西,您几乎有两种选择:

1. 加入查询

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

2.多个查询

一种性能稍差的方法(查看事物的 SQL 方面),但“更容易”“映射”到您的 JSON 格式。

为了提供一些见解,Doctrine 默认使用多查询方法。这主要是(我猜!)提供可以在每个可能的数据后端工作的功能,而不仅仅是几个 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 ....
}
于 2013-06-27T07:09:47.430 回答