Zend2路由请求流向控制器的机制及无Action路由疑问咨询
咱们先一步步拆解当你访问www.mysite.com/api2/testme/49时,代码是怎么流转到控制器的get($id)方法的:
1. 请求初始化与配置加载
当你在浏览器输入这个地址后,请求首先打到Zend2项目的入口文件public/index.php,这里会初始化整个应用实例,加载所有注册模块的配置——包括你在/module/Main/config/module.config.php里定义的路由规则。
2. 路由匹配阶段
应用会遍历所有注册的路由规则,你的Restful路由是Segment类型(支持动态参数的URL段路由),它的匹配规则应该是/api2/:controller[/:id](推测你配置里的/myapi是笔误,不然和访问地址的/api2对应不上)。
- 当请求URL是
/api2/testme/49时,路由会解析出:controller参数值为testmeid参数值为49- 加上配置里默认的
module为Main
3. 控制器实例化
Zend2会根据解析出的module和controller参数,自动定位到控制器类:Main\Controller\TestmeController(对应路径/module/Main/src/Main/Controller/TestmeController.php),并实例化这个控制器对象。
4. 方法自动映射(核心!)
这一步就是你疑惑的点——为什么路由没指定action却能走到get($id)方法:
你的控制器应该是继承了Zend\Mvc\Controller\AbstractRestfulController(RESTful风格的基础控制器),这个控制器已经封装了根据HTTP请求方法自动匹配对应方法的逻辑,不需要在路由里显式指定action参数:
- 如果是
GET请求且带id参数(比如你的请求/api2/testme/49),框架会自动调用控制器的get($id)方法; - 如果是
GET请求不带id(比如/api2/testme),会调用getList()方法; POST请求对应create()方法;PUT请求对应update($id)方法;DELETE请求对应delete($id)方法;
简单说,RESTful控制器把HTTP请求方法当作了“隐式的action”,路由只需要负责解析资源名称(controller)和资源ID(id),剩下的方法映射由框架自动完成。
补充验证
你可以检查下你的TestmeController类的头部,应该有类似这样的代码:
use Zend\Mvc\Controller\AbstractRestfulController; class TestmeController extends AbstractRestfulController { // ... 你的get($id)方法等 }
如果是继承普通的AbstractActionController,那必须在路由里指定action参数,否则会报错找不到默认action。
内容的提问来源于stack exchange,提问作者kenpeter

