Reputation: 10099
I'm working on a small ZF2 application which provides some API endpoints to clients. It returns some simple data via JSON.
It has a FooController
extending BaseRestController
and AbstractRestfulController
:
FooController extends BaseRestController
{
// ....
public function getList()
{
$data = array('foo' => 'bar');
return $this->send($data);
}
}
and:
BaseRestController extends AbstractRestfulController
{
// ...
public function send($data)
{
return new JsonModel($data);
}
}
Now I want to return the same data via XML based on the user's selection. I think I have to do something like this in my send()
method in BaseRestController
:
if ($format === 'json') {
return new JsonModel($data);
} else {
return new XmlModel($data);
}
I looked over built-in JsonModel, it extends Zend\View\Model\ViewModel
and adds serialize()
method which serializes variables to JSON.
I think i have to write a similar XmlModel but i can't figure out how to properly write this model and what is the correct way telling my controllers about this new model.
Which classes / factories / renderers / strategies are required to achieve this?
I read Creating and Registering Alternate Rendering and Response Strategies section of the documentation but all existing solutions inspects the Accept HTTP header, i don't need to interact with headers, client simply passes required format as route param in my application like /rest/foo?format=json
or /rest/foo?format=xml
I also found the Netglue extensions on bitbucket, they wrote 5 different Mvc Service classes plus 3 other Model/Renderer/Strategy total of 8 classes, which sounds like quite overkill for me.
The real question is, writing eight different classes to converting and returning structured data in XML format is really required?
There should be another options, i want to learn and understand what is the correct approach to achieve this?
Upvotes: 2
Views: 4401
Reputation: 5371
If you are going to use it in just one action there is no need for an xmlModel.
Just convert your data to proper XML and then :
$response = new \Zend\Http\Response();
$response->getHeaders()->addHeaderLine('Content-Type', 'text/xml; charset=utf-8');
$response->setContent($xml);
return $response;
Upvotes: 7
Reputation: 190
Since zf 2.0.4 you can deal with content negociation,
see 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) {
// ...
}
}
}
Upvotes: 1
Reputation: 1643
@alex-bernatskyi found a very nice solution for this here if you only need this in one method:
public function init()
{
$contextSwitch = $this->_helper->getHelper('contextSwitch');
$contextSwitch->addActionContext('xml', 'xml')->initContext('xml');
}
Upvotes: 1
Reputation: 530
look at JsonModel in Zend\View\Model\JsonModel . create a class extend of ViewModel . in serialize method use this code
$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
Upvotes: 0