标签:
Module类中获取子模块,注册子模块,实例化控制器,根据路由运行指定控制器方法的注释:
1 /** 2 * Retrieves the child module of the specified ID. 3 * 取出指定模块的子模块 4 * This method supports retrieving both child modules and grand child modules. 5 * 该方法支持检索子模块和子模块的子模块 6 * @param string $id module ID (case-sensitive). To retrieve grand child modules, 7 * use ID path relative to this module (e.g. `admin/content`). 8 * @param boolean $load whether to load the module if it is not yet loaded. 9 * @return Module|null the module instance, null if the module does not exist. 10 * @see hasModule() 11 */ 12 public function getModule($id, $load = true) 13 { 14 if (($pos = strpos($id, ‘/‘)) !== false) {//判断模块id格式是否为 `admin/content` 15 // sub-module 16 $module = $this->getModule(substr($id, 0, $pos));//取子模块 17 18 return $module === null ? null : $module->getModule(substr($id, $pos + 1), $load);//子模块不为空,返回子模块的子模块,否则返回空 19 } 20 21 if (isset($this->_modules[$id])) { 22 if ($this->_modules[$id] instanceof Module) { 23 return $this->_modules[$id];//如果_modules数组中有该模块,直接返回该模块 24 } elseif ($load) {//否则,$load为真,先实例化后返回 25 Yii::trace("Loading module: $id", __METHOD__); 26 /* @var $module Module */ 27 $module = Yii::createObject($this->_modules[$id], [$id, $this]); 28 $module->setInstance($module); 29 return $this->_modules[$id] = $module; 30 } 31 } 32 //不存在,返回空 33 return null; 34 } 35 36 /** 37 * Adds a sub-module to this module. 38 * 为当前模块添加子模块 39 * @param string $id module ID 40 * @param Module|array|null $module the sub-module to be added to this module. This can 41 * be one of the following: 42 * 43 * - a [[Module]] object 44 * 一个模块对象 45 * - a configuration array: when [[getModule()]] is called initially, the array 46 * will be used to instantiate the sub-module 47 * 模块参数为配置数组,用于实例化模块 48 * - null: the named sub-module will be removed from this module 49 * 为空,则表示删除 50 */ 51 public function setModule($id, $module) 52 { 53 if ($module === null) { 54 unset($this->_modules[$id]); 55 } else { 56 $this->_modules[$id] = $module; 57 } 58 } 59 60 /** 61 * Returns the sub-modules in this module. 62 * 返回该模块的子模块 63 * @param boolean $loadedOnly whether to return the loaded sub-modules only. If this is set false, 64 * then all sub-modules registered in this module will be returned, whether they are loaded or not. 65 * Loaded modules will be returned as objects, while unloaded modules as configuration arrays. 66 * @param boolean $loadedOnly 可选参数,定义是否只返回已加载的子模块 67 * @return array the modules (indexed by their IDs) 68 */ 69 public function getModules($loadedOnly = false) 70 { 71 if ($loadedOnly) { 72 $modules = []; 73 foreach ($this->_modules as $module) { 74 if ($module instanceof Module) { 75 $modules[] = $module; 76 } 77 } 78 79 return $modules; 80 } else { 81 return $this->_modules; 82 } 83 } 84 85 /** 86 * Registers sub-modules in the current module. 87 * 注册子模块到当前模块 88 * 89 * Each sub-module should be specified as a name-value pair, where 90 * name refers to the ID of the module and value the module or a configuration 91 * array that can be used to create the module. In the latter case, [[Yii::createObject()]] 92 * will be used to create the module. 93 * 子模块以键值对的方式指定,键名为模块ID,键值为模块对象或者用于创建模块对象的配置数组 94 * 95 * If a new sub-module has the same ID as an existing one, the existing one will be overwritten silently. 96 * 如果ID相同,后者会覆盖前置 97 * 98 * The following is an example for registering two sub-modules: 99 * 100 * ```php 101 * [ 102 * ‘comment‘ => [ 103 * ‘class‘ => ‘app\modules\comment\CommentModule‘, 104 * ‘db‘ => ‘db‘, 105 * ], 106 * ‘booking‘ => [‘class‘ => ‘app\modules\booking\BookingModule‘], 107 * ] 108 * ``` 109 * 110 * @param array $modules modules (id => module configuration or instances) 111 */ 112 public function setModules($modules) 113 { 114 foreach ($modules as $id => $module) { 115 $this->_modules[$id] = $module; 116 } 117 } 118 119 /** 120 * Runs a controller action specified by a route. 121 * 运行路由中指定的控制器方法 122 * This method parses the specified route and creates the corresponding child module(s), controller and action 123 * instances. It then calls [[Controller::runAction()]] to run the action with the given parameters. 124 * If the route is empty, the method will use [[defaultRoute]]. 125 * 解析指定的路由,创建对应的子模块、控制器、方法实例,然后调用[[Controller::runAction()]]用给定的参数运行控制器中的方法 126 * @param string $route the route that specifies the action. 127 * @param array $params the parameters to be passed to the action 128 * @return mixed the result of the action. 129 * @throws InvalidRouteException if the requested route cannot be resolved into an action successfully 130 */ 131 public function runAction($route, $params = []) 132 { 133 $parts = $this->createController($route);//根据路由创建控制器 134 if (is_array($parts)) { 135 /* @var $controller Controller */ 136 list($controller, $actionID) = $parts;//获得$actionId和$controller 137 $oldController = Yii::$app->controller; 138 Yii::$app->controller = $controller; 139 $result = $controller->runAction($actionID, $params);//运行使用控制器加载 action方法 140 Yii::$app->controller = $oldController;//将对象交给Yii::$app->controller 这里面起的作用应该是运行控制器,最后释放控制器的对象变量 141 142 return $result; 143 } else { 144 $id = $this->getUniqueId(); 145 throw new InvalidRouteException(‘Unable to resolve the request "‘ . ($id === ‘‘ ? $route : $id . ‘/‘ . $route) . ‘".‘); 146 } 147 } 148 149 /** 150 * Creates a controller instance based on the given route. 151 * 152 * The route should be relative to this module. The method implements the following algorithm 153 * to resolve the given route: 154 * 155 * 1. If the route is empty, use [[defaultRoute]]; 156 * 2. If the first segment of the route is a valid module ID as declared in [[modules]], 157 * call the module‘s `createController()` with the rest part of the route; 158 * 3. If the first segment of the route is found in [[controllerMap]], create a controller 159 * based on the corresponding configuration found in [[controllerMap]]; 160 * 4. The given route is in the format of `abc/def/xyz`. Try either `abc\DefController` 161 * or `abc\def\XyzController` class within the [[controllerNamespace|controller namespace]]. 162 * 163 * If any of the above steps resolves into a controller, it is returned together with the rest 164 * part of the route which will be treated as the action ID. Otherwise, false will be returned. 165 * 166 * @param string $route the route consisting of module, controller and action IDs. 167 * @return array|boolean If the controller is created successfully, it will be returned together 168 * with the requested action ID. Otherwise false will be returned. 169 * @throws InvalidConfigException if the controller class and its file do not match. 170 */ 171 public function createController($route) 172 { 173 if ($route === ‘‘) {//路由为空,调用默认的路由 174 $route = $this->defaultRoute; 175 } 176 177 // double slashes or leading/ending slashes may cause substr problem 178 //双斜线或者开始/结束的斜线会引起函数问题,去掉两边的斜线,如果路径中包含双斜线,返回false 179 $route = trim($route, ‘/‘); 180 if (strpos($route, ‘//‘) !== false) { 181 return false; 182 } 183 184 if (strpos($route, ‘/‘) !== false) {//路径中包含斜线 185 list ($id, $route) = explode(‘/‘, $route, 2);//将路径按斜线分割为两个元素的数组,[0]为$id,[1]为$route 186 } else { 187 $id = $route; 188 $route = ‘‘; 189 } 190 191 // module and controller map take precedence 192 // 优先判断模块和控制器映射 193 if (isset($this->controllerMap[$id])) {//如果$id是控制器ID,实例化控制器,返回控制器实例和后面的路径$route 194 $controller = Yii::createObject($this->controllerMap[$id], [$id, $this]); 195 return [$controller, $route]; 196 } 197 $module = $this->getModule($id);//如果$id是模块ID,实例化控制器,返回控制器实例和后面的路径$route 198 if ($module !== null) { 199 return $module->createController($route);//调用自身实例化控制器,返回控制器实例和后面的路径$route 200 } 201 202 if (($pos = strrpos($route, ‘/‘)) !== false) {//上面两种情况都不是,则表示该模块还有子模块,构造子模块的id 203 $id .= ‘/‘ . substr($route, 0, $pos); 204 $route = substr($route, $pos + 1); 205 } 206 207 $controller = $this->createControllerByID($id);//调用createControllerByID()方法实例化控制器 208 if ($controller === null && $route !== ‘‘) { 209 $controller = $this->createControllerByID($id . ‘/‘ . $route); 210 $route = ‘‘; 211 } 212 213 return $controller === null ? false : [$controller, $route];//实例化成功返回控制器实例和后面的路径$route,失败返回false 214 }
标签:
原文地址:http://www.cnblogs.com/isleep/p/5463943.html