首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

Yii 1.1 核心源碼深度剖析:從入口文件到控制器執行的完整生命週期

     編輯:PHP 相關知識

前言:為什麼要讀框架源碼?

Yii 1.1 雖已停止維護,但其清晰的架構設計、組件化思想、惰性載入機制,至今仍是學習 PHP 框架內核的優秀教材。本文以 demos/helloworld 為切入點,層層剝開從 index.php 到 SiteController::actionIndex() 的完整調用鏈,揭示框架如何將一個 HTTP 請求轉化為控制器動作執行。

階段一:應用實例化與初始化

1. 入口文件 (index.php)

require_once(dirname(__FILE__).'/../../framework/yii.php');
Yii::createWebApplication($config)->run();

2. YiiBase:框架基石

  • spl_autoload_register(['YiiBase','autoload']):註冊 PSR-0 風格自動載入
  • 定義核心常量(YII_PATH、YII_DEBUG 等)
  • Yii::createWebApplication() → createApplication('CWebApplication') → new CWebApplication($config)

3. CApplication 建構子:核心初始化流程

public function __construct($config=null) {
    Yii::setApplication($this);                    // 1. 設定全域應用實例
    $this->setBasePath($config['basePath'] ?? 'protected'); // 2. 基礎路徑
    Yii::setPathOfAlias('application', $this->getBasePath()); // 3. 路徑別名
    Yii::setPathOfAlias('webroot', dirname($_SERVER['SCRIPT_FILENAME']));
    $this->preinit();                              // 4. 預初始化(留給擴充)
    $this->initSystemHandlers();                   // 5. 註冊錯誤/異常處理器
    $this->registerCoreComponents();               // 6. 註冊核心組件(request, session, db...)
    $this->configure($config);                     // 7. 套用設定檔屬性
    $this->attachBehaviors($this->behaviors);      // 8. 綁定行為
    $this->preloadComponents();                    // 9. 預載入組件
    $this->init();                                 // 10. 子類初始化
}

階段二:請求處理流程

1. CApplication::run()

public function run() {
    $this->onBeginRequest(new CEvent($this));      // 觸發 onBeginRequest 事件
    register_shutdown_function([$this, 'end']);    // 註冊關閉函數
    $this->processRequest();                       // 核心:處理請求
    $this->onEndRequest(new CEvent($this));        // 觸發 onEndRequest 事件
}

2. CWebApplication::processRequest()

public function processRequest() {
    if ($this->catchAllRequest) {                  // 全域捕獲(維護模式)
        $route = $this->catchAllRequest[0];
        foreach (array_splice($this->catchAllRequest,1) as $k=>$v) $_GET[$k]=$v;
    } else {
        $route = $this->getUrlManager()->parseUrl($this->getRequest()); // 解析路由
    }
    $this->runController($route);                  // 執行控制器
}

3. 路由解析:CUrlManager::parseUrl()

  • 解析 PATH_INFO 或 GET 參數 r
  • 依據 rules 陣列進行雙向匹配(路由→URL、URL→路由)
  • 回傳標準路由格式:controllerID/actionID(如 site/index)

階段三:控制器建立與動作執行

1. CWebApplication::runController()

public function runController($route) {
    if (($ca = $this->createController($route)) !== null) {
        list($controller, $actionID) = $ca;
        $oldController = $this->_controller;
        $this->_controller = $controller;
        $controller->init();                       // 控制器初始化
        $controller->run($actionID);               // 執行動作
        $this->_controller = $oldController;
    } else {
        throw new CHttpException(404, ...);
    }
}

2. CController::createController() → CController::run()

  • createController():根據 controllerMap、模組、預設命名空間解析控制器類,實例化並回傳 [$controller, $actionID]
  • run($actionID):建立 CInlineAction → runActionWithFilters() → runAction()

3. 過濾器鏈:CFilterChain

public function runActionWithFilters($action, $filters) {
    if (empty($filters)) {
        $this->runAction($action);                 // 無過濾器直接執行
    } else {
        $this->_action = $action;
        CFilterChain::create($this, $action, $filters)->run(); // 串聯過濾器
        $this->_action = $priorAction;
    }
}

過濾器支援前置/後置邏輯(存取控制、效能分析、快取等),CFilterChain 透過遞迴實現洋蔥模型。

4. 動作執行核心:CInlineAction::runWithParams()

public function runWithParams($params) {
    $methodName = 'action' . $this->getId();       // actionIndex
    $controller = $this->getController();
    $method = new ReflectionMethod($controller, $methodName);
    
    if ($method->getNumberOfParameters() > 0) {
        return $this->runWithParamsInternal($controller, $method, $params); // 參數綁定
    } else {
        return $controller->$methodName();         // 無參數直接呼叫
    }
}

亮點:使用 ReflectionMethod 自動綁定 $_GET/$_POST 參數到動作方法簽名,實現參數自動注入。

階段四:視圖渲染與響應輸出

  • 動作方法執行 $this->render('view', $data)
  • CController::render() → renderPartial() → CBaseController::renderFile()
  • 視圖檔案實際為 PHP 腳本,透過 extract($data) 變數作用域隔離
  • 輸出緩衝區 (ob_start()) 捕獲內容,最終佈局檔案 main.php 包裝輸出

架構設計精華總結

設計模式Yii 實現位置核心價值
單一入口index.php集中式請求分發、安全控制
應用單例Yii::app() / CApplication全域資源存取、組件管理
惰性載入CModule::getComponent()按需實例化、效能優化
事件驅動CComponent::raiseEvent()解耦業務邏輯、擴充點
行為混入CModel::attachBehaviors()水平復用、動態擴充
過濾器鏈CFilterChainAOP 切面、請求預處理
反射參數綁定CInlineAction慣例優於配置、開發體驗

給現代開發者的啟示

Yii 1.1 的核心思想——組件化、惰性載入、事件驅動、慣例優於配置——在 Laravel、Symfony、Yii2 中均有傳承與發展。閱讀經典源碼,不僅能理解框架運作,更能養成「框架思維」:如何設計可擴充的核心、如何平衡靈活與效能、如何讓開發者用得爽。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved