Yii2自定义GET类型REST动作为何无需在verbs()中声明?
问题原因:Yii2 REST的两层HTTP方法校验机制
这个现象是框架两层独立的请求校验逻辑职责不同导致的,和GET方法本身没有特殊关系。
1. 第一层校验:路由解析阶段的方法匹配
你在extraPatterns中配置的'GET test/{id}' => 'test'是带HTTP方法限定的路由规则,由yii\rest\UrlRule在路由解析阶段处理:
- 规则前缀的
GET明确声明:只有当请求方法为GET,且路径匹配test/{id}时,才会把请求路由到test动作 - 所有POST/PUT/DELETE等其他方法请求该路径时,根本不会命中这条自定义规则,会直接返回404,完全不会进入控制器流程
- 如果你在规则里省略HTTP方法前缀(比如写为
'test/{id}' => 'test'),路由层才会放行所有方法的请求到控制器。
2. 第二层校验:控制器动作执行前的VerbFilter校验
你重写的verbs()方法,返回的配置是给控制器自动挂载的yii\filters\VerbFilter过滤器使用的,这个过滤器的核心逻辑非常简单:
- 仅对显式出现在配置数组里的动作做HTTP方法校验,请求方法不在允许列表中就返回405错误
- 对于没有在配置数组里声明的动作,直接放行,不做任何方法限制
- 父类
ActiveController默认的verbs()配置,只覆盖框架内置的index/view/create/update/delete等核心动作,完全不会处理你自定义的test动作
为什么GET场景下不用配置verbs()
结合两层逻辑就能推导出来:
你已经在路由规则里限定了只有GET请求能命中test动作,能进到控制器的请求全是符合要求的GET请求;而test动作没有在VerbFilter的配置里声明,过滤器会直接放行,所以就算你注释掉整个verbs()重写代码,请求也能正常响应。
为什么POST/PUT等动作看起来必须配置verbs()
你测试时观察到的“POST/PUT必须配置才能访问”是配置不全导致的错觉:
- 如果你在
extraPatterns里显式配置了'POST test/{id}' => 'test'/'PUT test/{id}' => 'test'这类带方法前缀的规则,路由层会先把非对应方法的请求全部拦截,和GET场景完全一致,就算不在verbs()里声明,请求也能正常访问 - 如果你只在
verbs()里声明了允许POST/PUT,但没在路由规则里加对应方法前缀,要么POST/PUT请求匹配不到路由返回404,要么路由层放行了其他方法的请求被VerbFilter拦截返回405,才会让你误以为必须配置verbs()
实际开发提示:如果你已经在路由规则里明确写了HTTP方法前缀,再去
verbs()里重复配置自定义动作的允许方法属于冗余操作。verbs()更适合用在不想在路由层限定方法、需要统一在控制器层做方法校验,或者同一路由需要根据请求方法映射不同动作的场景。
内容的提问来源于stack exchange,提问作者trejder
相关产品推荐
相关产品推荐

