Getting started with AbstractRestfulController

Zend Framework 2 introduced a new controller abstract class: AbstractRestfulController (more docs here). This is used to create restful services (which will communicate with javascript in the browser, for example).

Controllers implementing AbstractRestfulController, can expose normal actions in addition to the REST methods. Following the Zend convention, these the name of these methods must end in “Action”.

Example Rest Controller, with only the getList() method populated.

class TestRestController extends AbstractRestfulController
{
    public function indexAction()
    {
        return new ViewModel();
    }

    /**
     * Return list of resources
     *
     * @return mixed
     */
    public function getList()
    {
        return new JsonModel(array(
            array('name' => 'test'),
            array('name' => 'second')
        ));
    }

    /**
     * Return single resource
     *
     * @param  mixed $id
     * @return mixed
     */
    public function get($id)
    {
        //TODO: Implement Method
    }

    /**
     * Create a new resource
     *
     * @param  mixed $data
     * @return mixed
     */
    public function create($data)
    {
        //TODO: Implement Method
    }

    /**
     * Update an existing resource
     *
     * @param  mixed $id
     * @param  mixed $data
     * @return mixed
     */
    public function update($id, $data)
    {
        //TODO: Implement Method
    }

    /**
     * Delete an existing resource
     *
     * @param  mixed $id
     * @return mixed
     */
    public function delete($id)
    {
        //TODO: Implement Method
    }
}

I found the dispatch logic for AbstractRestfulController a little confusing.

If there is an available “action” value on the request object, the controller attempts to find the corresponding action method. If there is no action value, then it dispatches to the REST methods. This essentially means that we will have to setup custom routes to dispatch to AbstractRestfulControllers as the “action” value will typically have a default value of “index” if we are following the traditional route configuration.

If you are getting 404 Not Found errors, when you are expecting the REST methods to be executing, this is probably the problem.

Example route configuration (In module.config.php):

return array(
    'controllers' => array(
        'invokables' => array(
            'Application\Controller\TestRest' => 'Application\Controller\TestRestController',
        ),
    ),

    'router' => array(
        'routes' => array(
            'rest' => array(
                'type'    => 'Literal',
                'options' => array(
                    'route'    => '/rest',
                    'defaults' => array(
                        '__NAMESPACE__' => 'Application\Controller',
                    ),
                ),
                'may_terminate' => true,
                'child_routes' => array(
                    'default' => array(
                        'type'    => 'Segment',
                        'options' => array(
                            'route'    => '/:controller[/:id][/]',
                            'constraints' => array(
                                'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
                            ),
                            'defaults' => array(
                            ),
                        ),
                    ),
                ),
            ),
        ),
    ),

To get the controller to just render the JSON in the JsonModel returned by the getList method, we have to add a view manager strategy to the config:

return array(
    'view_manager' => array(
        'template_path_stack' => array(
            __DIR__ . '/../view',
        ),
        'strategies' => array(
            'ViewJsonStrategy',
        ),
    ),
);