Yii源码阅读笔记(二十四)
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源码阅读笔记(二十四)的更多相关文章
- Yii源码阅读笔记(十四)
Model类,集中整个应用的数据和业务逻辑——场景.属性和标签: /** * Returns a list of scenarios and the corresponding active attr ...
- Yii源码阅读笔记(十二)
Action类,控制器中方法的基类: namespace yii\base; use Yii; /** * Action is the base class for all controller ac ...
- Yii源码阅读笔记(十八)
View中的查找视图文件方法和渲染文件方法 /** * Finds the view file based on the given view name. * 通过view文件名查找view文件 * ...
- Yii源码阅读笔记(十五)
Model类,集中整个应用的数据和业务逻辑——验证 /** * Returns the attribute labels. * 返回属性的标签 * * Attribute labels are mai ...
- Yii源码阅读笔记(十六)
Model类,集中整个应用的数据和业务逻辑—— /** * Generates a user friendly attribute label based on the give attribute ...
- Yii源码阅读笔记(十)
控制器类,所有控制器的基类,用于调用模型和布局,输出到视图 namespace yii\base; use Yii; /** * Controller is the base class for cl ...
- Yii源码阅读笔记(十九)
View中渲染view视图文件的前置和后置方法,以及渲染动态内容的方法: /** * @return string|boolean the view file currently being rend ...
- Yii源码阅读笔记(二)
接下来阅读BaseYii.php vendor/yiisoft/yii2/BaseYii.php—— namespace yii; use yii\base\InvalidConfigExceptio ...
- Yii源码阅读笔记(一)
今天开始阅读yii2的源码,想深入了解一下yii框架的工作原理,同时学习一下优秀的编码规范和风格.在此记录一下阅读中的小心得. 每个框架都有一个入口文件,首先从入口文件开始,yii2的入口文件位于we ...
- werkzeug源码阅读笔记(二) 下
wsgi.py----第二部分 pop_path_info()函数 先测试一下这个函数的作用: >>> from werkzeug.wsgi import pop_path_info ...
随机推荐
- windows安装python问题
在安装python过程中,直接下一步,安装好了,配置环境变量的时候如果找不到安装路径在哪,打开开始菜单,在左边的程序栏找到: 这样就找到了,然后在系统变量中加入即可.如果找不到的话,以联想电脑为例一般 ...
- ashx 文件 与js文件数据交互
//js代码 //城市下拉列表 $("#selPro").change(function() { var option = ...
- OA
OA(政府) http://zw.wuzhitong.com/oa_wuzhitong/index.asp http://www.wuzhitong.com/Information_ZW.html O ...
- linux 安装程序
tar文件打开 tar -xvf myfile.tar bz2文件打开
- HDU 2851 (最短路)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2851 题目大意:给出N条路径,M个终点(是路径的编号) .重合的路径才算连通的,且路径是单向的.每条路 ...
- ACM: HDU 2563 统计问题-DFS+打表
HDU 2563 统计问题 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u HDU 2 ...
- TC SRM 591
表示第一次在div1,我要记录一下... 木有挂0,第一题不怎么难的,读题读了20分钟,又想了20分钟,时间有点长,然后各种小心,然后得了140分.... 后两个题,根本木有看,貌似做出来的也不多.. ...
- Crystal Reports 2008(水晶报表) 第一个报表
学习Craystal Reports 2008的时候,光看说明文档,很多东西看了就忘了. 我在看文档的时候,是跟着文档上面来做的. 这样边看边做,效果还不错哈 下面就是我的第一个demo 先看看效果: ...
- Linux 获取设备树源文件(DTS)里描述的资源
Linux 获取设备树源文件(DTS)里的资源 韩大卫@吉林师范大学 在linux使用platform_driver_register() 注册 platform_driver 时, 需要在 plat ...
- java中instanceof和getClass()的区别分析
class A { } class B extends A { } Object o1 = new A(); Object o2 = new B(); o1 instanceof A => t ...