Yii2 源碼分析 入口文件執行流程

Yii2 源碼分析  入口文件執行流程

 

1. 入口文件:web/index.php,第12行。(new yii\web\Application($config)->run())

  入口文件主要做4件事:

  1. 設置環境
  2. 加載自動加載
  3. 引入Web需要的配置
  4. 運行應用Application

 1 <?php
 2 
 3 // comment out the following two lines when deployed to production
 4 defined('YII_DEBUG') or define('YII_DEBUG', true);
 5 defined('YII_ENV') or define('YII_ENV', 'dev');
 6 
 7 require __DIR__ . '/../vendor/autoload.php';
 8 require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php';
 9 
10 $config = require __DIR__ . '/../config/web.php';
11 
12 (new yii\web\Application($config))->run();

 

2. 接下來看運行應用Application做了哪些事情  

  1. 執行應用類的構造方法:__construct()

    a. 設置全局應用對象:Yii::$app
    b. 加載配置,檢查配置是否正常配置並設置全局配置參數:如,檢查應用id是否設置,檢查basePath是否設置,檢查緩存目錄...,並設置對應的應用屬性參數
    c. 註冊全局錯誤異常處理機制
    d. 設置配置中對應對象的屬性  

 189     /**
 190      * Constructor.
 191      * @param array $config name-value pairs that will be used to initialize the object properties.
 192      * Note that the configuration must contain both [[id]] and [[basePath]].
 193      * @throws InvalidConfigException if either [[id]] or [[basePath]] configuration is missing.
 194      */
 195     public function __construct($config = [])
 196     {
 197         Yii::$app = $this;
 198         static::setInstance($this);
 199 
 200         $this->state = self::STATE_BEGIN;
 201 
 202         $this->preInit($config);
 203 
 204         $this->registerErrorHandler($config);
 205 
 206         Component::__construct($config);
 207     }

  2. 執行init()方法,執行引導:bootstrap

    a. 註冊Yii擴展的組件,組件目錄位於:根目錄\vendor\yiisoft\extension/php
    b. 註冊用戶自定義配置文件main.php中屬性boostrap配置的容器配置

267     /**
268      * {@inheritdoc}
269      */
270     public function init()
271     {
272         $this->state = self::STATE_INIT;
273         $this->bootstrap();
274     }

  3. 執行run()方法,執行應用請求流程,Yii處理請求邏輯應用的方法入口,應用的生命週期及對應的行爲、事件處理函數等入口  

 374    /**
 375      * Runs the application.
 376      * This is the main entrance of an application.
 377      * @return int the exit status (0 means normal, non-zero values mean abnormal)
 378      */
 379     public function run()
 380     {
 381         try {
 382             $this->state = self::STATE_BEFORE_REQUEST;
 383             $this->trigger(self::EVENT_BEFORE_REQUEST);
 384 
 385             $this->state = self::STATE_HANDLING_REQUEST;
 386             $response = $this->handleRequest($this->getRequest());
 387 
 388             $this->state = self::STATE_AFTER_REQUEST;
 389             $this->trigger(self::EVENT_AFTER_REQUEST);
 390
 391             $this->state = self::STATE_SENDING_RESPONSE;
 392             $response->send();
 393 
 394             $this->state = self::STATE_END;
 395 
 396             return $response->exitStatus;
 397         } catch (ExitException $e) {
 398             $this->end($e->statusCode, isset($response) ? $response : null);
 399             return $e->statusCode;
 400         }
 401     }

 

解析Yii執行run()的生命週期,在這個方法中可以看到有一些$this->state變量設置,這個變量主要用來記載Yii應用請求處於每個階段的處理過程,例如上面的__construct(),init(),以及run()都相應的設置了Yii全局應用請求的狀態

其中有:STATE_BEGIN(應用實例化階段)、STATE_INIT(執行init方法初始化階段)、STATE_BEFORE_REQUEST(執行請求前階段)、STATE_HANDLING_REQUEST(處理請求中階段)、STATE_AFTER_REQUEST(執行請求後階段)、STATE_SENDING_RESPONSE(返回響應階段)、STATE_END(應用結束輸出階段)

這裏主要來分析run()方法中第385行:$response = $this->handleRequest($this->getRequest()); 處理請求中階段:

1. 獲取請求並傳遞給handRequest處理請求方法,handleRequest方法位於:\vendor\yiisoft\yii2\web\Application文件中
2. Application文件第80-99行,解析請求URL地址,獲取請求路徑,地址參數:82行 list($route, $params) = $request->resolve();
3. Application文件第100-116行,根據請求路徑及參數,創建路徑指向的路由控制器文件,執行方法並傳入參數:103行 $result = $this->runAction($route, $params);
  a. \vendor\yiisoft\yii2\base\Module::runAction($route, $params),找到路由文件地址:522行 $parts = $this->createController($route)
  b. 分析路由控制器,及請求方法:list($controller, $actionID) = $parts
  c. 設置全局控制器
  d. 執行控制器中的方法體並傳入參數:528行 $result = $controller->runAction($actionID, $params)
    I. \vendor\yiisoft\yii2\base\Controller::runAction($id, $params = []),第126-138行,方法體創建過程
      i. 創建方法體對象:創建方法體對象 第219行 createAction($id)
      ii. 正則匹配請求方法名是否符合規範
      iii. 方法名轉化,以'-'切割,轉換大小寫
      iiii. 爲方法名添加'action'前綴
      iiiii. 驗證該方法名是否存在該類中
      iiiiii. 檢查該方法是否屬於公共方法
      iiiiiii. 執行方法體前  
    II. 執行模塊前置行爲(全局行爲處理)
    III. 執行方法體前置行爲(這裏可驗證方法權限、參數、跨域等行爲)
    IIII. 執行方法體【業務邏輯,這裏就是我們編寫代碼邏輯controller::action】
    IIIII. 執行方法體後置行爲(這裏可對返回數據進行驗證處理)
    IIIIII. 執行模塊後置行爲(全局行爲處理)
    IIIIIII. 獲取以上執行方法體以及模塊行爲事件處理的最終結果並返回:第172行

 

這裏分析下Yii怎麼解析路由文件,執行路徑:web\Application::handleRequest->runAction()103行 => base\Module::runAction->createController()522行 =>base\Module::createController()562行:

1. 解析地址,以'/'切割,根據route路由地址解析出id模塊以及操作控制器路由地址route 第564-579行
2. 加載模塊id對應的模塊配置 第582-589行
3. 根據控制器路由地址,加載控制器文件 第591-602行,主要代碼:$controller = $this->createControllerByID($id . '/', $route) 598行
  a. 檢查類文件及類前綴路徑是否符合規範 vendor\yiisoft\base\Module::629行
  b. 加載模塊完,加載控制器,檢查類文件是否存在,控制器地址文件不存在則報錯404
  c. 加載容器的時候,自動給方法加上controller vendor\yiisoft\base\Module.php::635行
  d. 匹配正確的文件,實例化控制器 vendor\yiisoft\base\Module.php::642行
4. 返回對應的類實例化及操作方法到執行前創建控制器 vendor\yiisoft\yii2\base\Module::522行
5. 檢查返回是否符合數組(控制器實例及操作方法),否:頁面找不到
6. 設置App應用全局控制器 vendor\yiisoft\yii2\base\Module::527行
7. 傳遞參數到控制器並執行控制器方法 vendor\yiisoft\yii2\base\Module::528行

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章