Zend Framework 2 and a Restful Application

After speaking to a prospective employer in a job interview, I was interested to try out the ZendMvcControllerRestfulController. With Zend_Json_Server in ZF1 having, shall we say, a less than sterling reputation, it was very interesting for me to see how the strategy has been implemented in ZF2.

The starting point for this is simply a completely fresh clone of the ZF2 Skeleton Application. The aim is to simply allow the pre-created index controller to function as a Restful interface.

The first thing to do is to ensure that you have the ViewJsonStrategy added to your View Manager. This is pretty simple when you know how (cheers Rob Allen!). In your module config simply add to the view_manager section (under ‘strategies’ key:

    'view_manager' => array(
        'display_not_found_reason' => true,
        'display_exceptions' => true,
        'doctype' => 'HTML5',
        'not_found_template' => 'error/404',
        'exception_template' => 'error/index',
        'template_map' => array(
            'layout/layout' => __DIR__ . '/../view/layout/layout.phtml',
            'index/index' => __DIR__ . '/../view/index/index.phtml',
            'error/404' => __DIR__ . '/../view/error/404.phtml',
            'error/index' => __DIR__ . '/../view/error/index.phtml',
        ),
        'template_path_stack' => array(
            __DIR__ . '/../view',
        ),
        'strategies' => array(
            'ViewJsonStrategy',
        ),
    ),

Your module now knows not to use a view script for any JsonModels returned, but to simply render the output as JSON.

Next up, we need to ensure that the router is configured to handle the Restful style URLs. RestfulControllers don't have actions, but instead consist of a controller and optional formatter and id parameters. To setup your route to handle Restful requests, change the routing part of your module config to as follows:

    'router' => array(
        'routes' => array(
            'restful' => array(
                'type' => 'ZendMvcRouterHttpSegment',
                'options' => array(
                    'route' => '/:controller[.:formatter][/:id]',
                    'constraints' => array(
                        'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'formatter' => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'id' => '[a-zA-Z0-9_-]*'
                    ),
                ),
            ),
            'home' => array(
                'type' => 'ZendMvcRouterHttpLiteral',
                'options' => array(
                    'route' => '/',
                    'defaults' => array(
                        'controller' => 'index',
                        'action' => 'index',
                    ),
                ),
            ),
        ),
    ),

This allows /index to be interpreted as a Restful resource rather than a normal ActionController entry point.

Finally, it's just a case of changing IndexController so that instead of extending ActionController it extends RestfulController. We can also change the use statement to use the JsonModel instead of the ViewModel.

<?php

namespace ApplicationController;

use ZendMvcControllerRestfulController,
    ZendViewModelJsonModel;

class IndexController extends RestfulController
{

RestfulController is an interface that expects 5 function to be defined to handle the various Restful style http requests.

GET request without an id parameter calls the getList() function, and should return a relevant list of resources.
GET request with an id parameter calls the get() function with the parameter $id, and should return a single resource with the given id.
PUT request containing POSTed id and data parameters calls the update() function passing $id and $data. This is for editing the given resource.
POST request containing only POSTed data parameter calls the create() function, passing the $data parameter. This is for creating new a resource.
DELETE request should contain an id parameter, and calls the delete() function, passing this $id. You use this to delete the given resource.

If those functions return JsonModel objects (which can be created with an array of output values very easily), then the result is automatically output as JSON which is great for Restful APIs.

The clever thing about the RestfulController is that is determines the HTTP request type for you, and calls the correct function based on the combination of request type and parameters passed.

This information is correct as of beta4 of Zend Framework 2, but should not change much in future releases, once again, thanks to everyone in #ZFTalk.2, particularly mbn_18, matuszemi and Akrabat.

5 thoughts on “Zend Framework 2 and a Restful Application

  1. Pingback: Aus den Blogs: Zend Framework und Doctrine, Capistrano, CRUD, NetBeans, Magento, WordPress, Restful - Zend Framework Magazin
  2. Some extra notes that might help out others:

    1) Routes have a LIFO precedence so you may have to order your REST routes AFTER any generic or Controller/Action routes that might also “look” like a REST Route.

    2) The route name itself is does not carry meaning, so “restful” could have been called “restful-api-routes” — there is no magic behind the value of route names in the ‘router’ config

    3) You may need to add the controller definition to the ‘controllers’ section of you module config (actually this might be required but I’m not up to speed on zf2 so please correct me if I’m wrong).

  3. Pingback: Coupler Zend Framework avec CanJS pour des interfaces en MVC partie 1 | Netsyos
  4. Pingback: Coupler Zend Framework avec CanJS pour des interfaces en MVC partie 2 | Netsyos
  5. Pingback: Linkpool Nummer 31 | PHP Gangsta - Der PHP Blog mit Praxisbezug

Your Comments are Awesome, Please Leave Them!

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s