【问题标题】:Triggering different actions on same route based on request type in Zend Framework 2在 Zend Framework 2 中根据请求类型在同一路由上触发不同的操作
【发布时间】:2014-11-13 10:57:29
【问题描述】:

我正在尝试让 ZF2 以 REST 方式响应不同的请求类型。

在我的 module.config.php 我有这个路由器配置。

'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',
                ),
            ),
        ),
    ),
),

在前端,我使用 Backbone 根据用户交互向服务器发送 GET、POST、DELETE 请求。 当用户触发删除 id 为 n 的学生的操作时,骨干网将使用 DELETE 请求发送 /somePath/student/n。 当用户触发操作以获取 id 为 n 的学生时,骨干网将使用 GET 请求发送 /somePath/student/n。

如果我希望当前设置正常工作,我必须更改 Backbone 请求并将 URL 从 student/n 更改为 student/delete/n,如果我想删除具有该 ID 的学生,对于 GET 也是如此。

这是我在客户端所做的,我想避免。

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);
        }
    });
});

在服务器端的控制器中,我想针对不同的请求类型运行不同的操作方法。

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

我不想更改默认主干行为(拦截和更改请求)。

有没有办法配置 ZF2 路由器使用相同的路由但根据请求方法类型触发不同的操作?

【问题讨论】:

    标签: javascript php backbone.js zend-framework2


    【解决方案1】:

    您可以使用Method 路由作为分段路由的子路由。 http://framework.zend.com/manual/2.3/en/modules/zend.mvc.routing.html

    有一个名为A complex example with child routes 的示例,其中blog 文字路由的作者创建了每个子路由,每个子路由都是不同的类型。

    您只需在学生路线中创建子路线,为您要使用的每种方法键入Method,然后仅更改此方法类型的操作。

    '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...
                ),
            ),
        ),
    ),
    

    【讨论】:

    • 虽然我最终使用了 Otto Sandström 建议的 AbstractRestulController,但我会接受你的回答,因为我询问了如何仅对路由器进行更改,而你提供了答案。
    【解决方案2】:

    您可以使用Zend\Mvc\Controller\AbstractRestfulController

    它会根据HTTP请求方法调用某些函数

    class StudentRest extends AbstractRestfulController {
    
        /** 
         * will be called with a GET request when it detects that route
         * matches paramater id has been set
         */
        public function get($id) {
            /*load studentdata*/
            return new JsonModel($data);
        }
    
        /**
         * Will be called on a POST request, and data should be sent with a $_POST
         * This should create a new object/row in db and return 201
         */
       public function Create($data) {
           /*create student*/
           $this->response->setStatusCode(201); // if new student was created.
           return JsonModel();
       }
    
        /**
         * Will be called on a PUT request. Data should be sent via $_POST
         * It also requires that the $id parameter is set in the route match
         */
       public function Update($id, $data) {}
    
        /**
         * Will be called on a DELETE request, It requires that the $id parameter is set in the route match
         */
       public function Delete($id) {}
    }
    

    这样你就可以通过路由链接到控制器了

    'student' => array(
            'type'    => 'segment',
            'options' => array(
                'route'    => '/student[/:id]',
                'constraints' => array(
                    'id'     => '[0-9]+',
                ),
                'defaults' => array(
                    'controller' => 'Student\Controller\StudentRest ',
                ),
            ),
        ),
    

    还有一些 getList 函数,当不在路由参数中提供 $id 时会调用它。 同样值得一提的是,所有函数的默认实现都会返回带有 ['content' => 'Method Not Allowed']

    的 405

    Documentation how to use it

    【讨论】:

      【解决方案3】:

      根据文档: http://framework.zend.com/manual/1.12/en/zend.controller.request.html

      确定请求方法

      getMethod() 允许您确定用于请求当前资源的 HTTP 请求方法。此外,还有多种方法可让您在询问是否已发出特定类型的请求时获得布尔响应:

      isGet()
      
      isPost()
      
      isPut()
      
      isDelete()
      
      isHead()
      
      isOptions()
      

      这些的主要用例是创建 RESTful MVC 架构。

      【讨论】:

        猜你喜欢
        • 2017-09-06
        • 2011-06-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-03
        • 1970-01-01
        相关资源
        最近更新 更多