vendor/yiisoft/yii2/base/Module.php(完)
/** * 创建一个控制器基于给定控制器ID. * * The controller ID is relative to this module. The controller class * should be namespaced under [[controllerNamespace]]. * * Note that this method does not check [[modules]] or [[controllerMap]]. * * @param string $id the controller ID * @return Controller the newly created controller instance, or null if the controller ID is invalid. * @throws InvalidConfigException if the controller class and its file name do not match. * This exception is only thrown when in debug mode. */ public function createControllerByID($id) { // $id是controller的ID,但它前面可能带有module的ID,而且可能是多层module ID // 取到最右边的斜线位置,可以分离出controller的名字 $pos = strrpos($id, '/'); if ($pos === false) { // 没有斜线,$id就是controller的名字 $prefix = ''; $className = $id; } else { // 有斜线,斜线前的是module的ID,斜线后是controller的名字 $prefix = substr($id, 0, $pos + 1); $className = substr($id, $pos + 1); } if (!preg_match('%^[a-z][a-z0-9\\-_]*$%', $className)) { // 如果controller的名字不符合命名的规范,就返回null // 以小写字母开头,可以包含数字/小写字母/右斜线/中划线/下划线 return null; } if ($prefix !== '' && !preg_match('%^[a-z0-9_/]+$%i', $prefix)) { // 如果module的ID不符合module的命名规范,就返回null // 可以包含数字/小写字母/左斜线/下划线 return null; } // 先将-替换为空格,再将每个单词的首字母大写,再将空格替换为空字符串,最后拼接上'Controller',就拿到了类名(不带namespace) $className = str_replace(' ', '', ucwords(str_replace('-', ' ', $className))) . 'Controller'; // 根据application和module中定义的controllerNamespace,拼出controller的类名,含namespace $className = ltrim($this->controllerNamespace . '\\' . str_replace('/', '\\', $prefix) . $className, '\\'); if (strpos($className, '-') !== false || !class_exists($className)) { // 如果存在中划线或者类不存在,即返回null return null; } // is_subclass_of — 如果此对象是该类的子类,则返回 TRUE // 判断是不是'yii\base\Controller'的子类,是的话,就创建相应类的实例 if (is_subclass_of($className, 'yii\base\Controller')) { return Yii::createObject($className, [$id, $this]); } elseif (YII_DEBUG) { throw new InvalidConfigException("Controller class must extend from \\yii\\base\\Controller."); } else { return null; } } /** * This method is invoked right before an action within this module is executed. * 这个方法被调用之前执行一个动作在这个模块 * The method will trigger the [[EVENT_BEFORE_ACTION]] event. The return value of the method * will determine whether the action should continue to run. * * If you override this method, your code should look like the following: * * ```php * public function beforeAction($action) * { * if (parent::beforeAction($action)) { * // your custom code here * return true; // or false if needed * } else { * return false; * } * } * ``` * * @param Action $action the action to be executed. * @return boolean whether the action should continue to be executed. */ public function beforeAction($action) { $event = new ActionEvent($action); //该方法将触发[[EVENT_BEFORE_ACTION]]事件 $this->trigger(self::EVENT_BEFORE_ACTION, $event); return $event->isValid; } /** * This method is invoked right after an action within this module is executed. *调用该方法之后执行一个动作在这个模块。 * The method will trigger the [[EVENT_AFTER_ACTION]] event. The return value of the method * will be used as the action return value. * * If you override this method, your code should look like the following: * * ```php * public function afterAction($action, $result) * { * $result = parent::afterAction($action, $result); * // your custom code here * return $result; * } * ``` * * @param Action $action the action just executed. * @param mixed $result the action return result. * @return mixed the processed action result. */ public function afterAction($action, $result) { //初始化 $event = new ActionEvent($action); //该事件触发后赋值给$result $event->result = $result; //该方法将触发[[EVENT_BEFORE_ACTION]]事件 $this->trigger(self::EVENT_AFTER_ACTION, $event); return $event->result; } }