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

Yii 資料庫快取實作完整指南:設定、基本操作與分頁列表實戰

     編輯:PHP 綜合知識

快取元件設定(config/main.php)

'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;

基本快取操作 API

操作方法說明
寫入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)分散式、需資料結構、發布訂閱豐富資料型別、持久化選項單執行緒、大值傳輸延遲

避坑指南

  1. 快取鍵衝突:加上模組/控制器/動作前綴,如 news_list_...。
  2. 快取雪崩:熱點資料過期瞬間大量請求打穿 DB,解法:隨機過期時間、互斥鎖重建、預熱。
  3. 快取穿透:查詢不存在資料每次都穿透 DB,解法:快取空結果(短 TTL)、布隆過濾器。
  4. 髒讀:寫入後未清除快取,讀到舊資料,解法:寫入後 delete() 對應鍵、或用相依性自動失效。
  5. 序列化問題:ActiveRecord 物件含資源連線不可直接快取,應先 toArray() 或只快取純資料陣列。

合理運用 Yii 快取機制,能大幅降低資料庫負載、提升回應速度,是高效能 Web 應用的關鍵技術之一。

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