Module类中获取子模块,注册子模块,实例化控制器,根据路由运行指定控制器方法的注释:

     /**
      * Retrieves the child module of the specified ID.
      * 取出指定模块的子模块
      * This method supports retrieving both child modules and grand child modules.
      * 该方法支持检索子模块和子模块的子模块
      * @param string $id module ID (case-sensitive). To retrieve grand child modules,
      * use ID path relative to this module (e.g. `admin/content`).
      * @param boolean $load whether to load the module if it is not yet loaded.
      * @return Module|null the module instance, null if the module does not exist.
      * @see hasModule()
      */
     public function getModule($id, $load = true)
     {
         if (($pos = strpos($id, '/')) !== false) {//判断模块id格式是否为 `admin/content`
             // sub-module
             $module = $this->getModule(substr($id, 0, $pos));//取子模块

             return $module === null ? null : $module->getModule(substr($id, $pos + 1), $load);//子模块不为空,返回子模块的子模块,否则返回空
         }

         if (isset($this->_modules[$id])) {
             if ($this->_modules[$id] instanceof Module) {
                 return $this->_modules[$id];//如果_modules数组中有该模块,直接返回该模块
             } elseif ($load) {//否则,$load为真,先实例化后返回
                 Yii::trace("Loading module: $id", __METHOD__);
                 /* @var $module Module */
                 $module = Yii::createObject($this->_modules[$id], [$id, $this]);
                 $module->setInstance($module);
                 return $this->_modules[$id] = $module;
             }
         }
         //不存在,返回空
         return null;
     }

     /**
      * Adds a sub-module to this module.
      * 为当前模块添加子模块
      * @param string $id module ID
      * @param Module|array|null $module the sub-module to be added to this module. This can
      * be one of the following:
      *
      * - a [[Module]] object
      *   一个模块对象
      * - a configuration array: when [[getModule()]] is called initially, the array
      *   will be used to instantiate the sub-module
      *   模块参数为配置数组,用于实例化模块
      * - null: the named sub-module will be removed from this module
      *   为空,则表示删除
      */
     public function setModule($id, $module)
     {
         if ($module === null) {
             unset($this->_modules[$id]);
         } else {
             $this->_modules[$id] = $module;
         }
     }

     /**
      * Returns the sub-modules in this module.
      * 返回该模块的子模块
      * @param boolean $loadedOnly whether to return the loaded sub-modules only. If this is set false,
      * then all sub-modules registered in this module will be returned, whether they are loaded or not.
      * Loaded modules will be returned as objects, while unloaded modules as configuration arrays.
      * @param boolean $loadedOnly 可选参数,定义是否只返回已加载的子模块
      * @return array the modules (indexed by their IDs)
      */
     public function getModules($loadedOnly = false)
     {
         if ($loadedOnly) {
             $modules = [];
             foreach ($this->_modules as $module) {
                 if ($module instanceof Module) {
                     $modules[] = $module;
                 }
             }

             return $modules;
         } else {
             return $this->_modules;
         }
     }

     /**
      * Registers sub-modules in the current module.
      * 注册子模块到当前模块
      *
      * Each sub-module should be specified as a name-value pair, where
      * name refers to the ID of the module and value the module or a configuration
      * array that can be used to create the module. In the latter case, [[Yii::createObject()]]
      * will be used to create the module.
      * 子模块以键值对的方式指定,键名为模块ID,键值为模块对象或者用于创建模块对象的配置数组
      *
      * If a new sub-module has the same ID as an existing one, the existing one will be overwritten silently.
      * 如果ID相同,后者会覆盖前置
      *
      * The following is an example for registering two sub-modules:
      *
      * ```php
      * [
      *     'comment' => [
      *         'class' => 'app\modules\comment\CommentModule',
      *         'db' => 'db',
      *     ],
      *     'booking' => ['class' => 'app\modules\booking\BookingModule'],
      * ]
      * ```
      *
      * @param array $modules modules (id => module configuration or instances)
      */
     public function setModules($modules)
     {
         foreach ($modules as $id => $module) {
             $this->_modules[$id] = $module;
         }
     }

     /**
      * Runs a controller action specified by a route.
      * 运行路由中指定的控制器方法
      * This method parses the specified route and creates the corresponding child module(s), controller and action
      * instances. It then calls [[Controller::runAction()]] to run the action with the given parameters.
      * If the route is empty, the method will use [[defaultRoute]].
      * 解析指定的路由,创建对应的子模块、控制器、方法实例,然后调用[[Controller::runAction()]]用给定的参数运行控制器中的方法
      * @param string $route the route that specifies the action.
      * @param array $params the parameters to be passed to the action
      * @return mixed the result of the action.
      * @throws InvalidRouteException if the requested route cannot be resolved into an action successfully
      */
     public function runAction($route, $params = [])
     {
         $parts = $this->createController($route);//根据路由创建控制器
         if (is_array($parts)) {
             /* @var $controller Controller */
             list($controller, $actionID) = $parts;//获得$actionId和$controller
             $oldController = Yii::$app->controller;
             Yii::$app->controller = $controller;
             $result = $controller->runAction($actionID, $params);//运行使用控制器加载 action方法
             Yii::$app->controller = $oldController;//将对象交给Yii::$app->controller 这里面起的作用应该是运行控制器,最后释放控制器的对象变量

             return $result;
         } else {
             $id = $this->getUniqueId();
             throw new InvalidRouteException('Unable to resolve the request "' . ($id === '' ? $route : $id . '/' . $route) . '".');
         }
     }

     /**
      * Creates a controller instance based on the given route.
      *
      * The route should be relative to this module. The method implements the following algorithm
      * to resolve the given route:
      *
      * 1. If the route is empty, use [[defaultRoute]];
      * 2. If the first segment of the route is a valid module ID as declared in [[modules]],
      *    call the module's `createController()` with the rest part of the route;
      * 3. If the first segment of the route is found in [[controllerMap]], create a controller
      *    based on the corresponding configuration found in [[controllerMap]];
      * 4. The given route is in the format of `abc/def/xyz`. Try either `abc\DefController`
      *    or `abc\def\XyzController` class within the [[controllerNamespace|controller namespace]].
      *
      * If any of the above steps resolves into a controller, it is returned together with the rest
      * part of the route which will be treated as the action ID. Otherwise, false will be returned.
      *
      * @param string $route the route consisting of module, controller and action IDs.
      * @return array|boolean If the controller is created successfully, it will be returned together
      * with the requested action ID. Otherwise false will be returned.
      * @throws InvalidConfigException if the controller class and its file do not match.
      */
     public function createController($route)
     {
         if ($route === '') {//路由为空,调用默认的路由
             $route = $this->defaultRoute;
         }

         // double slashes or leading/ending slashes may cause substr problem
         //双斜线或者开始/结束的斜线会引起函数问题,去掉两边的斜线,如果路径中包含双斜线,返回false
         $route = trim($route, '/');
         if (strpos($route, '//') !== false) {
             return false;
         }

         if (strpos($route, '/') !== false) {//路径中包含斜线
             list ($id, $route) = explode('/', $route, 2);//将路径按斜线分割为两个元素的数组,[0]为$id,[1]为$route
         } else {
             $id = $route;
             $route = '';
         }

         // module and controller map take precedence
         // 优先判断模块和控制器映射
         if (isset($this->controllerMap[$id])) {//如果$id是控制器ID,实例化控制器,返回控制器实例和后面的路径$route
             $controller = Yii::createObject($this->controllerMap[$id], [$id, $this]);
             return [$controller, $route];
         }
         $module = $this->getModule($id);//如果$id是模块ID,实例化控制器,返回控制器实例和后面的路径$route
         if ($module !== null) {
             return $module->createController($route);//调用自身实例化控制器,返回控制器实例和后面的路径$route
         }

         if (($pos = strrpos($route, '/')) !== false) {//上面两种情况都不是,则表示该模块还有子模块,构造子模块的id
             $id .= '/' . substr($route, 0, $pos);
             $route = substr($route, $pos + 1);
         }

         $controller = $this->createControllerByID($id);//调用createControllerByID()方法实例化控制器
         if ($controller === null && $route !== '') {
             $controller = $this->createControllerByID($id . '/' . $route);
             $route = '';
         }

         return $controller === null ? false : [$controller, $route];//实例化成功返回控制器实例和后面的路径$route,失败返回false
     }

Yii源码阅读笔记(二十四)的更多相关文章

  1. Yii源码阅读笔记(十四)

    Model类,集中整个应用的数据和业务逻辑——场景.属性和标签: /** * Returns a list of scenarios and the corresponding active attr ...

  2. Yii源码阅读笔记(十二)

    Action类,控制器中方法的基类: namespace yii\base; use Yii; /** * Action is the base class for all controller ac ...

  3. Yii源码阅读笔记(十八)

    View中的查找视图文件方法和渲染文件方法 /** * Finds the view file based on the given view name. * 通过view文件名查找view文件 * ...

  4. Yii源码阅读笔记(十五)

    Model类,集中整个应用的数据和业务逻辑——验证 /** * Returns the attribute labels. * 返回属性的标签 * * Attribute labels are mai ...

  5. Yii源码阅读笔记(十六)

    Model类,集中整个应用的数据和业务逻辑—— /** * Generates a user friendly attribute label based on the give attribute ...

  6. Yii源码阅读笔记(十)

    控制器类,所有控制器的基类,用于调用模型和布局,输出到视图 namespace yii\base; use Yii; /** * Controller is the base class for cl ...

  7. Yii源码阅读笔记(十九)

    View中渲染view视图文件的前置和后置方法,以及渲染动态内容的方法: /** * @return string|boolean the view file currently being rend ...

  8. Yii源码阅读笔记(二)

    接下来阅读BaseYii.php vendor/yiisoft/yii2/BaseYii.php—— namespace yii; use yii\base\InvalidConfigExceptio ...

  9. Yii源码阅读笔记(一)

    今天开始阅读yii2的源码,想深入了解一下yii框架的工作原理,同时学习一下优秀的编码规范和风格.在此记录一下阅读中的小心得. 每个框架都有一个入口文件,首先从入口文件开始,yii2的入口文件位于we ...

  10. werkzeug源码阅读笔记(二) 下

    wsgi.py----第二部分 pop_path_info()函数 先测试一下这个函数的作用: >>> from werkzeug.wsgi import pop_path_info ...

随机推荐

  1. 伪Acmer的推理(dfs/bfs)

    时间限制:1000MS  内存限制:65535K 提交次数:12 通过次数:9 收入:32 题型: 编程题   语言: C++;C Description 现在正是期末,在复习离散数学的Acmer遇到 ...

  2. 最火的.NET开源项目

    综合类 微软企业库 微软官方出品,是为了协助开发商解决企业级应用开发过程中所面临的一系列共性的问题, 如安全(Security).日志(Logging).数据访问(Data Access).配置管理( ...

  3. c#中ref和out 关键字

    问题:为什么c#中要有ref和out?(而java中没有)需求假设:现需要通过一个叫Swap的方法交换a,b两个变量的值.交换前a=1,b=2,断言:交换后a=2,b=1. 现编码如下: class ...

  4. 每天一个linux命令--locate

    linux下,不知道自己安装的程序放在哪里了,可以使用locate命令进行查找. [hongye@dev107 ~]$ locate activemq.xml /home/hongye/hongyeC ...

  5. xml基本操作和保存配置文件应用实例

    引言:在实际项目中遇到一些关于xml操作的问题,被逼到无路可退的时候终于决定好好研究xml一番.本文首先介绍了xml的基本操作,后面写了一个经常用到的xml保存配置文件的实例. xml常用方法: 定义 ...

  6. python 代码片段20

    #coding=utf-8 # 函数 def foo(x): print x foo(123) # import httplib def check_web_server(host,port,path ...

  7. (转)HBase工程师线上工作经验总结----HBase常见问题及分析

    阅读本文可以带着下面问题:1.HBase遇到问题,可以从几方面解决问题?2.HBase个别请求为什么很慢?你认为是什么原因?3.客户端读写请求为什么大量出错?该从哪方面来分析?4.大量服务端excep ...

  8. div+css定位position详解

    div+css定位position详解 1.div+css中的定位position 最主要的两个属性:属性 absolute(绝对定位) relative(相对定位),有他们才造就了div+css布局 ...

  9. ACM 精挑细选

    精 挑 细 选 时间限制:3000 ms  |  内存限制:65535 KB 难度:1   描述 小王是公司的仓库管理员,一天,他接到了这样一个任务:从仓库中找出一根钢管.这听起来不算什么,但是这根钢 ...

  10. 【BZOJ】2434: [Noi2011]阿狸的打字机

    题意 给你一些字符串.\(m\)次询问,每一次询问第\(x\)个字符串在\(y\)字符串中出现了多少次.(输入总长$ \le 10^5$, \(M \le 10^5\)) 分析 在ac自动机上,\(x ...