2

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?

Stephan Weinhold
  • 1,623
  • 1
  • 28
  • 37
edigu
  • 9,878
  • 5
  • 57
  • 80
  • Xml's only markup, can't you just return a regular view model with the xml in a template and no layout? – Crisp Mar 16 '14 at 00:08
  • Yes, json is too. But what about `Content-Type:application/json; charset=utf-8` header which added by AbstractRestfulController? Also should i create `` part manually in controller level? I also want to learn reason of existence of this `render()` method: https://github.com/zendframework/zf2/blob/master/library/Zend/View/Renderer/JsonRenderer.php#L127-L170 – edigu Mar 16 '14 at 00:21

4 Answers4

7

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;
Alex Tartan
  • 6,736
  • 10
  • 34
  • 45
Exlord
  • 5,009
  • 4
  • 31
  • 51
1

@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');
}
Community
  • 1
  • 1
Stephan Weinhold
  • 1,623
  • 1
  • 28
  • 37
1

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) {
        // ...
        }
    }
}
bastien
  • 190
  • 1
  • 9
0

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

Community
  • 1
  • 1
Amin Arab
  • 530
  • 4
  • 19
  • I added the example by @Exlord and included a XMLWriter example here: http://blog.webdevilopers.net/how-to-render-xml-response-in-zend-framework-2/ - hope this helps. – webDEVILopers Jul 08 '14 at 09:21