学习yii2.0框架阅读代码(十六)

yii\base\InlineAction

追踪一个命令行请求的过程

namespace yii\base;

use Yii;

/**
 * InlineAction表示一个动作被定义为一个控制器的方法.
 *
 * The name of the controller method is available via [[actionMethod]] which
 * is set by the [[controller]] who creates this action.
 *
 * @author Qiang Xue <[email protected]>
 * @since 2.0
 */
class InlineAction extends Action
{
    /**
     * @var string the controller method that this inline action is associated with
     */
    public $actionMethod;

    /**
     * @param string $id the ID of this action
     * @param Controller $controller the controller that owns this action
     * @param string $actionMethod the controller method that this inline action is associated with
     * @param array $config name-value pairs that will be used to initialize the object properties
     */
    public function __construct($id, $controller, $actionMethod, $config = [])
    {
        // 传入action的id,controller的实例,action方法的名称以及action的配置
        $this->actionMethod = $actionMethod;
        parent::__construct($id, $controller, $config);
    }

    /**
     * 这个动作用指定的参数运行.
     * 这种方法主要是由控制器调用.
     * @param array $params action parameters
     * @return mixed the result of the action
     */
    public function runWithParams($params)
    {
        // 获取action的参数,通过合并出入的参数和默认参数得出
        $args = $this->controller->bindActionParams($this, $params);
        Yii::trace(‘Running action: ‘ . get_class($this->controller) . ‘::‘ . $this->actionMethod . ‘()‘, __METHOD__);
        if (Yii::$app->requestedParams === null) {
            // 记录请求的参数
            Yii::$app->requestedParams = $args;
        }

        // 执行controller的这个action方法
        return call_user_func_array([$this->controller, $this->actionMethod], $args);
    }
}

控制器调用

 public function __construct($id, $module, $config = [])
     {
+        // 传入controller的id和所在的module的实例
         $this->id = $id;
         $this->module = $module;
         parent::__construct($config);
 @@ -117,6 +118,7 @@ public function actions()
      */
     public function runAction($id, $params = [])
     {
+        // 创建action的实例
         $action = $this->createAction($id);
         if ($action === null) {
             throw new InvalidRouteException(‘Unable to resolve the request: ‘ . $this->getUniqueId() . ‘/‘ . $id);
 @@ -125,6 +127,7 @@ public function runAction($id, $params = [])
         Yii::trace("Route to run: " . $action->getUniqueId(), __METHOD__);

         if (Yii::$app->requestedAction === null) {
+            // 记录当前的action为requestedAction
             Yii::$app->requestedAction = $action;
         }

 @@ -135,24 +138,31 @@ public function runAction($id, $params = [])
         $runAction = true;

         // call beforeAction on modules
+        // 从外到里一层层执行module的beforeAction
         foreach ($this->getModules() as $module) {
             if ($module->beforeAction($action)) {
+                // 将执行成功的module放入到$modules中,顺序会颠倒
                 array_unshift($modules, $module);
             } else {
+                // 执行失败,就标记一下,并跳出循环
                 $runAction = false;
                 break;
             }
         }

         $result = null;

+        // modules的beforeAction执行成功而且controller本身的beforeAction也执行成功
         if ($runAction && $this->beforeAction($action)) {
             // run the action
+            // 执行action
             $result = $action->runWithParams($params);

+            // 执行controller本身的afterAction
             $result = $this->afterAction($action, $result);

             // call afterAction on modules
+            // 从里到外一层层执行所有modules的beforeAction
             foreach ($modules as $module) {
                 /* @var $module Module */
                 $result = $module->afterAction($action, $result);
 @@ -211,17 +221,25 @@ public function bindActionParams($action, $params)
     public function createAction($id)
     {
         if ($id === ‘‘) {
+            // 如果action的id为空,就是用默认的action
             $id = $this->defaultAction;
         }

+        // 获取actions方法中的定义的actionMap
         $actionMap = $this->actions();
         if (isset($actionMap[$id])) {
+            // 如果action的id在actionMap中,就去创建这个action
             return Yii::createObject($actionMap[$id], [$id, $this]);
         } elseif (preg_match(‘/^[a-z0-9\\-_]+$/‘, $id) && strpos($id, ‘--‘) === false && trim($id, ‘-‘) === $id) {
+            // 如果id符合命名规范,并且不存在--,而且两边不存在-
+            // 必须是数字/小写字母/右斜线/中划线/下划线组成的的
+            // 用与拼接controller类名类似的方法拼接action方法的名称
             $methodName = ‘action‘ . str_replace(‘ ‘, ‘‘, ucwords(implode(‘ ‘, explode(‘-‘, $id))));
             if (method_exists($this, $methodName)) {
+                // 如果方法存在,就new一个ReflectionMethod实例
                 $method = new \ReflectionMethod($this, $methodName);
                 if ($method->isPublic() && $method->getName() === $methodName) {
+                    // 如果方法是public的,就new一个InlineAction返回
                     return new InlineAction($id, $this, $methodName);
                 }
             }
 @@ -297,9 +315,13 @@ public function afterAction($action, $result)
      */
     public function getModules()
     {
+        // 用当前controller的module组成modules的数组
         $modules = [$this->module];
         $module = $this->module;
+        // 遍历module的module,直到为空
         while ($module->module !== null) {
+            // array_unshift — 在数组开头插入一个或多个单元
+            // 将外面的module插入到modules数组的开头
             array_unshift($modules, $module->module);
             $module = $module->module;
         }
时间: 2024-10-29 19:10:03

学习yii2.0框架阅读代码(十六)的相关文章

学习yii2.0框架阅读代码(十五)

行为是 yii\base\Behavior 或其子类的实例.行为,也称为mixins,可以无须改变类继承关系即可增强一个已有的 yii\base\Component 类功能.当行为附加到组件后,它将“注入”它的方法和属性到组件,然后可以像访问组件内定义的方法和属性一样访问它们.此外,行为通过组件能响应被触发的事件,从而自定义或调整组件正常执行的代码. <?php namespace yii\base; /** * 行为是所有行为类的基类. * * 一个行为可以用来增强现有的功能组件,无需修改其代

学习yii2.0框架阅读代码(十九)

vendor/yiisoft/yii2/base/Module. php(续) /** * 检索指定的子模块ID. * 这种方法支持检索两个子模块和子模块. * @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 wheth

学习yii2.0框架阅读代码(十八)

vendor/yiisoft/yii2/base/Module. php /** * 返回一个ID,惟一标识此模块在所有模块在当前应用程序. * @return string the unique ID of the module. */ public function getUniqueId() { //如果该模块是一个应用程序,将返回一个空字符串. return $this->module ? ltrim($this->module->getUniqueId() . '/' . $t

学习yii2.0框架阅读代码(十)

vendor/yiisoft/yii2/base/Module. <?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace yii\base; use Yii; use yii\di\ServiceLocator; /** * 模块和应用程序类

学习yii2.0框架阅读代码(十二)

先把Object.Component.Module三个核心搞清楚了在写实例 下面介绍一下Object -- Yii最基础的类,大多数类都继承了该类.常用的12个公共方法,有点类似于ThinkPHP里面的魔术方法. <?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/

学习yii2.0框架阅读代码(十四)

组件(Component) 事件Event(温习) <?php namespace yii\base; //事件是所有事件类的基类.它封装了参数与事件相关联. //如果一个事件处理程序集[[进行]]是真的,其余的,uninvoked处理程序将不再被称为处理事件. //另外,添加一个事件处理程序时,额外的数据可能被传递和可以通过[[数据]]属性调用事件处理程序时. class Event extends Object { /** * @var string the event name. This

学习yii2.0框架阅读代码(六)

vendor/yiisoft/yii2/base/ArrayableTrait. <?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace yii\base; use Yii; use yii\helpers\ArrayHelper; use

学习yii2.0框架阅读代码(二十)

vendor/yiisoft/yii2/base/Module. php(续) /** * 新建一个控制器实例基于给定的路线. * * 路线应该是相对于这个模块.该方法实现了以下算法 * 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 [

学习yii2.0框架阅读代码(四)

阅读 BaseYii Yii的辅助类核心框架 别名相关(续) //用一个真实的路径注册一个别名 public static function setAlias($alias, $path) { if (strncmp($alias, '@', 1)) { // 如果不是以 @ 开头,就将 @ 拼到开头 $alias = '@' . $alias; } // 获取 / 在 $alias 中首次出现的位置 $pos = strpos($alias, '/'); // 如果 / 不存在,$root 就