頁面快取
頁面快取指的是快取整個頁面的內容。頁面快取可以發生在不同的地方。例如,通過選擇適當的頁面頭,客戶端的瀏覽器可能會快取網頁瀏覽有限時間。 Web 應用程式程式本身也可以在快取中儲存網頁內容。
頁面快取可以被看作是 片段快取 一個特殊情況 。 由於網頁內容是往往通過應用程式佈局來產生,如果我們只是簡單的在佈局中調用 beginCache() 和 endCache(),將無法正常工作。 這是因為佈局在 CController::render() 方法裡的加載是在頁面內容產生之後。
如果想要快取整個頁面,我們應該跳過產生網頁內容的動作執行。我們可以使用 COutputCache 作為動作 篩選器來完成這一任務。下面的程式碼展示如何配置快取篩選器:
public function filters() { return array( array( 'COutputCache', 'duration'=>100, 'varyByParam'=>array('id'), ), ); }
上述篩選器配置會使篩選器適用於控制器中的所有行動。 我們可能會限制它在一個或幾個行動透過使用插件操作器。 更多的細節可以看篩選器。
Tip: 我們可以使用 COutputCache 作為一個篩選器,因為它從 CFilterWidget 繼承過來, 這意味著它是一個工具(widget)和一個篩選器。事實上,小工具的工作方式和篩選器非常相似: 小工具 (篩選器) 是在動作裡的內容執行前執行,在執行後結束。
HTTP 快取
除了簡單快取動作的輸出,Yii 在版本 1.1.11 介紹了 CHttpCacheFilter。這個篩選器協助了前面所提到的,使用標頭來提示客戶端頁面的內容,自上一次請求後就沒有改變,所以伺服器不需要重新傳送內容。CHttpCacheFilter 可以像 COutputCache 一樣設置:
public function filters() { return array( array( 'CHttpCacheFilter + index', 'lastModified'=>Yii::app()->db->createCommand("SELECT MAX(`update_time`) FROM {{post}}")->queryScalar(), ), ); }
上述的程式碼會設定 Last-Modified
標頭成上一次文章被更新的日期。你也可以使用 CHttpCacheFilter::lastModifiedExpression 藉由 PHP 表達式來設定 Last-Modified
標頭。
提示: CHttpCacheFilter::lastModifiedExpression 和 CHttpCacheFilter::lastModified 都可以使用 Unix 時間戳記或是人類可讀的字串來表示。後者可以被 strtotime() 解析,不需要額外的轉換。
這個 "Entity Tag"(或 ETag
)標頭可以分別藉由像是 CHttpCacheFilter::etagSeed 和 CHttpCacheFilter::etagSeedExpression 的方法來設定。兩個都會被序列化(所以可以使用單一值或是一整個陣列),並且被用來產生一個被標記的、base64-encoded SHA1 編碼的內容來給 ETag
標投當作內容。這跟 Apache Webserver 的方法不同,各家的伺服器也產生自己的 ETags。然而,非常符合 RFC,而且也成為一個框架中的主流的用法。
注意: 為了遵守 RFC 2616,第 13.3.4 章節, CHttpCacheFilter 會送出
ETag
和Last-Modified
標頭,如果他們可以同時被產生。所以,兩者都會被客戶端用來做快取驗證。
當時體標籤被編碼,他們允許比 Last-Modified
標頭更複雜且/或更精確的快取策略。例如,一個 ETag 可能是無效的,當網站切換成另外一個主題。
提示: 昂貴的表達式給 CHttpCacheFilter::etagSeedExpression 可以會違背 CHttpCacheFilter 的目的和產生不需要的負擔,因為每次的請求都要重新被評估。試著找出一個簡單的表達式,可以檢驗快取是否頁面的 內容 已經被修改了。
搜尋引擎優化的影響
搜尋引擎機器很看重快取標頭。當一些網路爬蟲有限制每個網域下,在某一個時間區間有多少頁面可以被處理,使用快取標投可以幫助索引你的網站,因為可以減少需要處理的頁面數量。