'components' => [
'cache' => [
'class' => 'system.caching.CDbCache', // 資料庫快取
'connectionID' => 'db', // 使用的 DB 連線元件 ID
'cacheTableName' => 'yii_cache', // 快取資料表名稱
'autoCreateCacheTable' => true, // 自動建立快取表
],
// 或使用檔案快取(較簡單,單機適用)
// 'cache' => ['class' => 'system.caching.CFileCache'],
],
// 記得在 db 元件中啟用 schemaCachingDuration 以快取資料表結構
'db' => [
'class' => 'CDbConnection',
'schemaCachingDuration' => 3600,
// ...
],
CREATE TABLE `yii_cache` (
`id` char(128) NOT NULL,
`expire` int(11) NOT NULL,
`data` blob NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
| 操作 | 方法 | 說明 |
|---|---|---|
| 寫入 | Yii::app()->cache->set($key, $value, $expire) | $expire 秒數,0=永不過期 |
| 讀取 | Yii::app()->cache->get($key) | 不存在或過期回傳 false |
| 刪除 | Yii::app()->cache->delete($key) | |
| 清空 | Yii::app()->cache->flush() | 刪除所有快取項目 |
列表頁 URL 範例:/news/list/gid/2/nid/3/page/1.html,快取鍵需包含所有分頁參數以確保唯一性。
public function actionList() {
// 1. 取得分頁參數
$gid = isset($_GET['gid']) ? intval($_GET['gid']) : 1;
$nid = isset($_GET['nid']) ? intval($_GET['nid']) : 0;
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// 注意:避免使用 $page 變數名,可能與分頁元件衝突,建議用 $currentPage
// 2. 組合唯一快取鍵
$cacheKey = "newsList_gid{$gid}_nid{$nid}_page{$page}";
// 3. 嘗試讀取快取
$cachedData = Yii::app()->cache->get($cacheKey);
if ($cachedData !== false) {
return $this->render('list', $cachedData); // 直接渲染快取資料
}
// 4. 快取未命中:查詢資料庫
$criteria = new CDbCriteria();
$criteria->condition = 'status=1';
if ($gid) $criteria->addCondition("gid=$gid");
if ($nid) $criteria->addCondition("nid=$nid");
$count = News::model()->count($criteria);
$pages = new CPagination($count);
$pages->pageSize = 20;
$pages->applyLimit($criteria);
$list = News::model()->findAll($criteria);
// 5. 組裝視圖資料
$viewData = [
'list' => $list,
'pages' => $pages,
'gid' => $gid,
'nid' => $nid,
];
// 6. 寫入快取(有效期 1 小時)
Yii::app()->cache->set($cacheKey, $viewData, 3600);
// 7. 渲染
$this->render('list', $viewData);
}
使用 CDbCacheDependency 監控資料表變更:
$dependency = new CDbCacheDependency('SELECT COUNT(*) FROM {{news}} WHERE status=1');
Yii::app()->cache->set($cacheKey, $viewData, 3600, $dependency);
當 news 表筆數變化(新增/刪除/狀態變更),快取自動失效,下次請求重新查詢。
// 視圖檔案中
if ($this->beginCache('sidebar_hot_news', [
'duration' => 3600,
'dependency' => [
'class' => 'system.caching.CDbCacheDependency',
'sql' => 'SELECT MAX(updated_at) FROM {{news}} WHERE status=1',
],
])) {
// 此區塊無快取時執行,有快取時跳過
$hotNews = News::model()->findAll(['condition'=>'status=1', 'order'=>'view_count DESC', 'limit'=>10]);
$this->renderPartial('_hotNews', ['news' => $hotNews]);
$this->endCache();
}
| 策略 | 適用場景 | 優點 | 缺點 |
|---|---|---|---|
| 資料庫快取 (CDbCache) | 單機、已有 DB、資料量中等 | 持久化、支援查詢相依性 | DB 成瓶頸時快取也慢 |
| 檔案快取 (CFileCache) | 單機、小型專案 | 零設定、效能不錯 | 不支援分散式、inode 耗盡風險 |
| Memcached (CMemCache) | 分散式、高併發、多伺服器 | 記憶體級速度、水平擴展 | 資料非持久、需額外維運 |
| Redis (CRedisCache) | 分散式、需資料結構、發布訂閱 | 豐富資料型別、持久化選項 | 單執行緒、大值傳輸延遲 |
news_list_...。delete() 對應鍵、或用相依性自動失效。toArray() 或只快取純資料陣列。合理運用 Yii 快取機制,能大幅降低資料庫負載、提升回應速度,是高效能 Web 應用的關鍵技術之一。