我正在开发一个小型 ZF2 应用程序,它为客户端提供一些 API 端点。它通过 JSON 返回一些简单的数据。
它有一个
FooController
延伸 BaseRestController
和 AbstractRestfulController
:
FooController extends BaseRestController
{
// ....
public function getList()
{
$data = array('foo' => 'bar');
return $this->send($data);
}
}
和:
BaseRestController extends AbstractRestfulController
{
// ...
public function send($data)
{
return new JsonModel($data);
}
}
现在我想根据用户的选择通过 XML 返回相同的数据。我想我必须在
send()
中的 BaseRestController
方法中做这样的事情:
if ($format === 'json') {
return new JsonModel($data);
} else {
return new XmlModel($data);
}
我查看了内置的 JsonModel,它扩展了
Zend\View\Model\ViewModel
并添加了 serialize()
将变量序列化为 JSON 的方法。
我想我必须编写一个类似的XmlModel,但我不知道如何正确编写这个模型以及告诉我的控制器这个新模型的正确方法是什么。
需要哪些类/工厂/渲染器/策略来实现这一点?
我阅读了文档的创建和注册备用渲染和响应策略部分,但所有现有解决方案都会检查接受HTTP标头,我不需要与标头交互,客户端只需在我的应用程序中将所需的格式作为路由参数传递,如
/rest/foo?format=json
或 /rest/foo?format=xml
我还在 bitbucket 上找到了 Netglue 扩展,他们编写了 5 个不同的 Mvc 服务类加上 3 个其他模型/渲染器/策略总共 8 个类,这对我来说听起来有点大材小用了。
真正的问题是,真的需要编写八个不同的类来转换和返回 XML 格式的结构化数据吗?
应该还有其他选择,我想学习并了解实现此目标的正确方法是什么?
如果您只想在一个操作中使用它,则不需要 xmlModel。
只需将您的数据转换为正确的 XML,然后:
$response = new \Zend\Http\Response();
$response->getHeaders()->addHeaderLine('Content-Type', 'text/xml; charset=utf-8');
$response->setContent($xml);
return $response;
@alex-bernatskyi 找到了一个非常好的解决方案,如果您只需要一种方法,请在这里:
public function init()
{
$contextSwitch = $this->_helper->getHelper('contextSwitch');
$contextSwitch->addActionContext('xml', 'xml')->initContext('xml');
}
自 zf 2.0.4 起您可以处理内容协商,
参见PR:https://github.com/zendframework/zf2/pull/2615
class SomeController extends AbstractActionController
{
protected $acceptCriteria = array(
'Zend\View\Model\JsonModel' => array(
'application/json',
),
'Zend\View\Model\FeedModel' => array(
'application/rss+xml',
),
);
public function apiAction()
{
$model = $this->acceptableViewModelSelector($this->acceptCriteria);
// Potentially vary execution based on model returned
if ($model instanceof JsonModel) {
// ...
}
}
}
查看 Zend\View\Model\JsonModel 中的 JsonModel 。创建 ViewModel 的类扩展。在序列化方法中使用此代码
$test_array = array (
'bla' => 'blub',
'foo' => 'bar',
'another_array' => array (
'stack' => 'overflow',
),
);
$xml = new SimpleXMLElement('<root/>');
array_walk_recursive($test_array, array ($xml, 'addChild'));
print $xml->asXML();