先说一下Yii中的控制器是做什么用的,以及在什么地方使用.
在Yii中,当请求一个Url的时候,首先在application中获取request信息,然后由request通过urlManager解析出route,再在Module中根据route来创建controller并处理request。
如:http://www.yii2.com/index.php?r=site/login。会使用SiteController里面的actionLogin动作来处理这个请求。
Yii中总共有三种控制器类
我们按照这些函数的调用顺序来一一说明
执行路由:public function run($route, $params = [])
执行动作:public function runAction($id, $params = [])
在Yii中,当请求一个Url的时候,首先在application中获取request信息,然后由request通过urlManager解析出route,再在Module中根据route来创建controller并处理request。
如:http://www.yii2.com/index.php?r=site/login。会使用SiteController里面的actionLogin动作来处理这个请求。
Yii中总共有三种控制器类
- base\Controller.php 这个是下面两个的基类,即这里讲的控制器
- console\Controller.php 这个是控制台控制器
- web\Controller.php 这个是web控制器
- 和action相关的功能
- 和render相关的功能
- 其它功能
我们按照这些函数的调用顺序来一一说明
执行路由:public function run($route, $params = [])
- /*
- * route值即可以为当前controller中的action id,
- *
- * 也可为module id/controller id/action id/这种格式
- * 如果以“/”开头,将用application来处理,否则,用控制器所属模块来处理
- */
- public function run($route, $params = [])
- {
- //先判断route中有没有“/”
- $pos = strpos($route, '/');
- if ($pos === false) {
- //如果没有“/”,则为action id,直接调用runAction来执行这个action。如:index
- return $this->runAction($route, $params);
- } elseif ($pos > 0) {
- //如果“/”在中间,由当前的模块来处理这个route。如:test/index
- return $this->module->runAction($route, $params);
- } else {
- //如果以“/”开头,则用当前的应用程序来处理这个route。如:/test/index;
- return Yii::$app->runAction(ltrim($route, '/'), $params);
- }
- }
- /*
- * $id 为action的id,如定义的actionIndex,那么id就为Index。
- *
- */
- public function runAction($id, $params = [])
- {
- //创建action
- $action = $this->createAction($id);
- if ($action === null) {
- throw new InvalidRouteException('Unable to resolve the request: ' . $this->getUniqueId() . '/' . $id);
- }
- Yii::trace("Route to run: " . $action->getUniqueId(), __METHOD__);
- if (Yii::$app->requestedAction === null) {
- Yii::$app->requestedAction = $action;
- }
- $oldAction = $this->action;
- $this->action = $action;
- //用来保存当前控制器的所有父模块,顺序为由子模块到父模块
- $modules = [];
- $runAction = true;
- /*
- * 获取当前控制器的所属模块,并执行每个模块的beforeAction来检查当前的action是否可以执行,
- * 注意:getModules返回的数组顺序为:从父模块到子模块,
- * 所以在执行beforeAction的时候,先检查最外层的父模块,然后检查子模块。
- *
- * 然而在执行afterAction的时候,顺序就反过来了,先执行子模块,最后执行父模块。
- *
- */
- foreac