在Zend Framework 2应用程序中返回XML响应的正确方法是什么?

时间:2014-03-16 00:01:30

标签: xml api rest zend-framework2

我正在开发一个小型ZF2应用程序,它为客户端提供了一些API端点。它通过JSON返回一些简单的数据。

FooController延伸BaseRestControllerAbstractRestfulController

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 ,但我无法弄清楚如何正确编写这个模型以及告诉控制器这个新模型的正确方法。

要实现这一目标需要哪些类/工厂/渲染器/策略?

我阅读了文档的Creating and Registering Alternate Rendering and Response Strategies部分,但是所有现有的解决方案都检查了Accept HTTP标头,我不需要与标头交互,客户端只需将所需的格式作为路由参数传递给我的应用程序,如{{1} }或/rest/foo?format=json

我还在bitbucket上发现了Netglue扩展,他们写了5 different Mvc Service classes3 other Model/Renderer/Strategy总共 8个类,这听起来对我来说太过分了。

真正的问题是,真正需要编写八种不同的类来转换和返回XML格式的结构化数据吗?

应该有另一种选择,我想学习并了解实现这一目标的正确方法是什么?

4 个答案:

答案 0 :(得分:7)

如果您只想在一个动作中使用它,则不需要xmlModel 只需将您的数据转换为适当的XML,然后:

$response = new \Zend\Http\Response();
$response->getHeaders()->addHeaderLine('Content-Type', 'text/xml; charset=utf-8');
$response->setContent($xml);
return $response;

答案 1 :(得分:1)

@ alex-bernatskyi为这个here找到了一个非常好的解决方案,如果你只需要一个方法:

public function init()
{
    $contextSwitch = $this->_helper->getHelper('contextSwitch');
    $contextSwitch->addActionContext('xml', 'xml')->initContext('xml');
}

答案 2 :(得分:1)

从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) {
        // ...
        }
    }
}

答案 3 :(得分:0)

查看Zend \ View \ Model \ JsonModel中的JsonModel。创建ViewModel的类扩展。在serialize方法中使用此代码

$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();

How to convert array to SimpleXML