Search code examples
javascriptphpbackbone.jszend-framework2

Triggering different actions on same route based on request type in Zend Framework 2


I am trying to make ZF2 respond in REST way to different request type.

In my module.config.php I have this router config.

'router' => array(
    'routes' => array(
        'student' => array(
            'type'    => 'segment',
            'options' => array(

                'route'    => '/student[/:action][/:id]',
                'constraints' => array(
                    'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
                    'id'     => '[0-9]+',
                ),

                'defaults' => array(
                    'controller' => 'Student\Controller\Student',
                    'action'     => 'index',
                ),
            ),
        ),
    ),
),

On frontend I am using Backbone to send GET, POST, DELETE requests to server based on user interactions. When user trigger action to delete student with id of n, backbone will send /somePath/student/n using DELETE request. When user trigger action to get student with id of n, backbone will send /somePath/student/n using GET request.

If I want current setup to work I have to change Backbone request and change URL from student/n to student/delete/n if I want to delete student with that id and similarly for GET.

This is what I did on client side which I would like to avoid.

define(['backbone'], function(Backbone){
    return Backbone.Model.extend({
        defaults:{
            //set default model values
        },
        initialize: function(){
            //initialize
        },
        methodToURL: {
            'delete': '/student/delete'
        },
        sync: function(method, model, options) {
            options = options || {};
            var id = arguments[1]['id']
            options.url = model.methodToURL[method.toLowerCase()] + '/' + id;
            return Backbone.sync.apply(this, arguments);
        }
    });
});

In controller on server side I have different action methods I would like to run for different request types.

public function deleteAction()
{
        //some code
}
public function getAction()
{
        //some code
}

I don't want to change default backbone behaviour (intercepting and altering requests).

Is there a way to configure ZF2 router to use same route but trigger different actions based on request method type?


Solution

  • You can use Method route as child route of segment route. http://framework.zend.com/manual/2.3/en/modules/zend.mvc.routing.html

    There is a example named A complex example with child routes where author for blog literal route create child routes each of which is different type.

    Simply You can create child routes in your student route which will be type Method for each method You want to use and then change only action for this method types.

    'router' => array(
        'routes' => array(
            'student' => array(
                'type'    => 'segment',
                'options' => array(
    
                    'route'    => '/student[/:action][/:id]',
                    'constraints' => array(
                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'id'     => '[0-9]+',
                    ),
    
                    'defaults' => array(
                        'controller' => 'Student\Controller\Student',
                        'action'     => 'index',
                    ),
                ),
                'may_terminate' => true,
                'child_routes' => array(
                    'delete' => array(
                        'type' => 'method',
                        'options' => array(
                            'verb' => 'delete',
                            'defaults' => array(
                                'action' => 'delete'
                            ),
                        ),
                    ),
                    'put' => array(
                        'type' => 'method',
                        'options' => array(
                            'verb' => 'put',
                            'defaults' => array(
                                'action' => 'put'
                            ),
                        ),
                    ),//and so on...
                ),
            ),
        ),
    ),