YII 提供統一的緩存組件抽象層,支援 10+ 後端存儲驅動,並實現數據級、片段級、頁面級、動態內容四大緩存模式。本文系統梳理驅動選型、配置、API 使用與進階模式實戰。
框架內建驅動(framework/caching/):
| 驅動類 | 底層依賴 | 適用場景 | 特點 |
|---|---|---|---|
| CMemCache | PHP memcache/memcached 擴展 | 分散式高併發緩存 | 多伺服器權重、一致性哈希、高性能 |
| CApcCache | PHP APC 擴展 | 單機 opcode + 用戶緩存 | 無網絡開銷、共享內存、需 APC 支援 |
| CXCache | PHP XCache 擴展 | 單機高性能緩存 | 類 APC、支援 1.0.1+ |
| CEAcceleratorCache | PHP EAccelerator 擴展 | 單機緩存 | 早期方案、逐漸淘汰 |
| CDbCache | 數據庫表(默認 SQLite3) | 無額外擴展環境 | 持久化、可指定 connectionID 使用業務庫 |
| CZendDataCache | Zend Server Data Cache | Zend Server 環境 | 企業級、支援 1.0.4+ |
| CFileCache | 文件系統 | 大對象、頁面緩存 | 支援 1.0.6+、適合大塊數據 |
| CDummyCache | 無操作 | 開發/測試/無緩存環境 | 接口兼容、無實際緩存、支援 1.0.5+ |
| CWinCache | PHP WinCache 擴展 | Windows IIS 環境 | 微軟生態整合 |
核心優勢: 所有驅動繼承 CCache,業務代碼**零修改**即可切換後端。
'components' => array(
'cache' => array(
'class' => 'system.caching.CApcCache',
),
),
'cache' => array(
'class' => 'CMemCache',
'servers' => array(
array('host' => 'server1', 'port' => 11211, 'weight' => 60),
array('host' => 'server2', 'port' => 11211, 'weight' => 40),
),
'keyPrefix' => 'myapp_', // 避免鍵衝突
),
$cache = Yii::app()->cache;
// 基礎操作
$cache->set($id, $value, $expire=0, $dependency=null); // 存儲
$cache->get($id); // 讀取
$cache->add($id, $value, $expire, $dependency); // 僅不存在時存儲
$cache->delete($id); // 刪除
$cache->flush(); // 清空所有
// 陣列式訪問(實現 ArrayAccess)
$cache['key'] = $value; // 等同 set()
$value = $cache['key']; // 等同 get()
// 批量讀取(支援驅動原生 mget)
$values = $cache->mget(array('key1', 'key2', 'key3'));
除過期時間外,支援依賴條件變更觸發失效:
| 依賴類 | 觸發條件 |
|---|---|
| CFileCacheDependency | 文件修改時間變化 |
| CDirectoryCacheDependency | 目錄及子目錄文件變化 |
| CDbCacheDependency | SQL 查詢結果變化 |
| CGlobalStateCacheDependency | 全局狀態變化(跨請求/會話) |
| CChainedCacheDependency | 鏈中任一依賴變化 |
| CExpressionDependency | PHP 表達式結果變化(1.0.4+) |
// 依賴文件變化
$dependency = new CFileCacheDependency('/path/to/config.ini');
Yii::app()->cache->set('config', $data, 3600, $dependency);
// 依賴數據庫最大更新時間
$dependency = new CDbCacheDependency('SELECT MAX(updated_at) FROM post');
Yii::app()->cache->set('post_list', $data, 0, $dependency);
$key = 'user_profile_' . $userId;
if (($profile = Yii::app()->cache->get($key)) === false) {
$profile = User::model()->findByPk($userId);
Yii::app()->cache->set($key, $profile, 3600);
}
視圖中緩存頁面局部:
<?php if ($this->beginCache('sidebar', array('duration'=>3600, 'dependency'=>...))) { ?>
<!-- 昂貴的側邊欄渲染邏輯 -->
<?php $this->endCache(); ?>
<?php } ?>
進階選項:
duration:有效秒數(默認 60)dependency:依賴對象/配置varyByRoute:按路由變化(不同 Controller/Action 獨立緩存)varyBySession:按 Session ID 變化(用戶個性化)varyByParam:按 GET 參數變化(如 array('id'))varyByExpression:按 PHP 表達式結果變化requestTypes:限制請求類型(如 array('GET') 僅緩存 GET)作為 Action 過濾器,跳過整個視圖渲染:
public function filters() {
return array(
array(
'COutputCache',
'duration' => 100,
'varyByParam' => array('id'),
),
);
}
COutputCache 繼承 CFilterWidget,兼具 Widget 與 Filter 雙重身份。
頁面/片段緩存中嵌入實時生成內容(如用戶名、購物車數量):
<?php if ($this->beginCache('page', array('duration'=>3600))) { ?>
<!-- 靜態內容 -->
<?php echo $this->renderDynamic(array($this, 'renderUserPanel')); ?>
<!-- 靜態內容 -->
<?php $this->endCache(); ?>
<?php } ?>
renderDynamic($callback) 回調可為控制器方法、全局函數或類方法,每次請求實時執行並插入結果。
片段緩存支援嵌套,內層過期不影響外層有效數據;外層過期將重新生成包含內層的完整內容。合理設置不同 duration 實現多級緩存失效策略。
模塊:實體:動作:標識 格式(如 user:profile:view:123),配合 keyPrefix 隔離環境