edigu
edigu

Reputation: 10099

What is the proper way to return XML response in a Zend Framework 2 app?

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

Answers (4)

Exlord
Exlord

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

bastien
bastien

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

Stephan Weinhold
Stephan Weinhold

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

Amin Arab
Amin Arab

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

Related Questions