Wednesday, May 23, 2012

How to create Restful API in Zend Framework 2

Your ZF module just needs to provide Controller that speaks REST (for example RestfulController) and make sure that generated response will be formatted in JSON, in other words configure JSON rendering strategy. Below you can see an example controller. Note that it has convenient methods for to get all elements, single element, create/update and delete an element:
use Zend\Mvc\Controller\RestfulController;

class UserController extends RestfulController
 public function getList() {
  return array("users" => array());

 public function get($id) {
  return array("id" => $id);

 public function create($data) {
  return array("created" => "yes");

 public function update($id, $data) {
  return array("updated" => "yes");

 public function delete($id) {
  return array("deleted" => $i);

When associating this controller to route, make sure to NOT use 'action' parameter. Otherwise, your controller will look for '<action>Action' method, completely overlooking the above methods. Now let's configure JSON rendering strategy. Your Module.php should look like this after all:
class Module implements AutoloaderProvider
    public function init(Manager $moduleManager)
        $events       = $moduleManager->events();
        $sharedEvents = $events->getSharedManager();
        $sharedEvents->attach('bootstrap', 'bootstrap', array($this, 'bootstrap'), 100);
    public function bootstrap($e)
     $app = $e->getParam('application');
        $app->events()->attach('render', array($this, 'registerJsonStrategy'), 100);
    public function registerJsonStrategy($e)
        $app          = $e->getTarget();
        $locator      = $app->getLocator();
        $view         = $locator->get('Zend\View\View');
        $jsonStrategy = $locator->get('Zend\View\Strategy\JsonStrategy');

        // Attach strategy, which is a listener aggregate, at high priority
        $view->events()->attach($jsonStrategy, 100);
Finally, let's try the new API. Note that RestfulController responds only to requests with 'Accept: application/json' header, so trying it in browser may not work out of the box :-)
curl -H 'Accept: application/json' http://zf2sample:10088/user

curl -H 'Accept: application/json' http://zf2localhost:10088/user?id=1

curl -X DELETE -H 'Accept: application/json' http://zf2localhost:10088/user?id=1
{"content":{"deleted": "1"}}