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

Yii2 原始碼學習筆記(十九):View 類別剩餘核心方法解析

     編輯:PHP 相關知識

Yii2 原始碼學習筆記(十九):View 類別剩餘核心方法解析

接續上篇,本文分析 yii\web\View 剩餘關鍵方法:視圖檔案追蹤、前後置渲染事件、PHP 原生模板渲染、動態內容快取佔位符、區塊/內容裝飾/片段快取/頁面生命週期等輔助方法。

1. 視圖檔案堆疊追蹤

public function getViewFile() {
    return end($this->_viewFiles); // 回傳當前正在渲染的視圖檔路徑
}

_viewFiles 陣列在 renderFile() 進入時 array_push,結束時 array_pop,支援巢狀渲染追蹤。

2. 渲染前後事件

public function beforeRender($viewFile, $params) {
    $event = new ViewEvent(['viewFile' => $viewFile, 'params' => $params]);
    $this->trigger(self::EVENT_BEFORE_RENDER, $event);
    return $event->isValid; // false 可中止渲染
}

public function afterRender($viewFile, $params, &$output) {
    if ($this->hasEventHandlers(self::EVENT_AFTER_RENDER)) {
        $event = new ViewEvent(['viewFile' => $viewFile, 'params' => $params, 'output' => $output]);
        $this->trigger(self::EVENT_AFTER_RENDER, $event);
        $output = $event->output; // 允許事件修改輸出內容
    }
}

應用場景:EVENT_BEFORE_RENDER 可注入通用變數、權限檢查;EVENT_AFTER_RENDER 可進行 HTML 壓縮、關鍵字替換、CSP nonce 注入。

3. PHP 原生模板渲染核心

public function renderPhpFile($_file_, $_params_ = []) {
    ob_start();
    ob_implicit_flush(false);
    extract($_params_, EXTR_OVERWRITE); // 參數轉為區域變數
    require($_file_);                   // 直接執行 PHP 檔案
    return ob_get_clean();              // 取得輸出並關閉緩衝
}

這是 View 渲染的最底層實作,所有 render()/renderFile() 最終皆呼叫此方法。extract(EXTR_OVERWRITE) 確保同名變數以新值覆蓋。

4. 動態內容與快取佔位符

片段快取/頁面快取時,部分需即時更新的內容(如 CSRF token、用戶名、購物車數量)不應被快取。Yii2 採用佔位符替換策略:

public function renderDynamic($statements) {
    if (!empty($this->cacheStack)) { // 正在快取中
        $n = count($this->dynamicPlaceholders);
        $placeholder = "<![CDATA[YII-DYNAMIC-$n]]>";
        $this->addDynamicPlaceholder($placeholder, $statements);
        return $placeholder; // 回傳佔位符寫入快取
    }
    return $this->evaluateDynamicContent($statements); // 非快取模式直接執行
}

public function addDynamicPlaceholder($placeholder, $statements) {
    foreach ($this->cacheStack as $cache) {
        $cache->dynamicPlaceholders[$placeholder] = $statements; // 向外層所有快取登記
    }
    $this->dynamicPlaceholders[$placeholder] = $statements;
}

public function evaluateDynamicContent($statements) {
    return eval($statements); // 直接執行 PHP 代碼字串
}

流程:

  1. 開發者在視圖寫 。
  2. 若處於快取區塊內,回傳 <![CDATA[YII-DYNAMIC-0]]> 佔位符,並將 PHP 代碼登記到所有層級快取的 dynamicPlaceholders。
  3. 快取讀取時(FragmentCache::getCachedContent()),將快取內容中的佔位符替換為 eval() 執行結果。

5. 區塊、內容裝飾、片段快取、頁面生命週期輔助方法

方法用途對應 Widget
beginBlock($id, $renderInPlace)開始記錄具名區塊,稍後在佈局中輸出Block
endBlock()結束區塊記錄Block
beginContent($viewFile, $params)開始內容裝飾(巢狀佈局),$viewFile 為外層佈局ContentDecorator
endContent()結束內容裝飾ContentDecorator
beginCache($id, $properties)開始片段快取,回傳 false 表示命中快取無需重新生成FragmentCache
endCache()結束片段快取並儲存FragmentCache
beginPage()頁面開始,啟動輸出緩衝,觸發 EVENT_BEGIN_PAGE-
endPage()頁面結束,觸發 EVENT_END_PAGE,刷新輸出緩衝-

視圖中的使用範例

// 區塊

    <div class="sidebar">...</div>

// 佈局中:

// 內容裝飾(巢狀佈局)

    // 內容區內容


// 片段快取

    // 昂貴的選單生成邏輯
    


// 頁面生命週期(main.php 佈局)

<!DOCTYPE html>
<html>
<head>...</head>
<body>
    

</body>
</html>

原始碼設計重點

  1. 輸出緩衝控制:beginPage() ob_start(),endPage() ob_end_flush(),確保 EVENT_END_PAGE 事件可修改最終輸出(如注入腳本、壓縮 HTML)。
  2. 快取堆疊:cacheStack 陣列維護巢狀快取層級,動態內容佔位符需向所有外層快取登記,確保多層快取正確替換。
  3. 事件驅動擴充:beforeRender/afterRender、BEGIN_PAGE/END_PAGE 讓行為擴充與核心邏輯解耦。
  4. 安全性:eval() 僅用於開發者可控的動態內容代碼,不接受用戶輸入。

結語

View 類別是 Yii2 視圖層的核心協調者,除模板渲染外,還統一管理快取、動態內容、區塊、佈局裝飾、頁面生命週期。理解其內部機制,能更靈活地使用進階功能、排查渲染異常、編寫高效能視圖元件。

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