CodeIgniter (CI) 內建兩層快取機制:**資料庫查詢快取** 減少 DB 負載,**頁面輸出快取** 達到近靜態頁速度。本文詳細說明設定、使用、清除策略與常見坑點。
一、資料庫快取 (Query Caching)
啟用三步驟
- 建立可寫入目錄:`mkdir -p application/cache/db && chmod 777 application/cache/db`
- 設定 `application/config/database.php`:
$db['default']['cachedir'] = APPPATH . 'cache/db/';
$db['default']['cache_on'] = TRUE; // 全域開啟
- 或程式碼動態控制:`$this->db->cache_on()` / `$this->db->cache_off()`
運作原理
- 僅快取 **SELECT** 查詢 (產生結果集)。INSERT/UPDATE/DELETE 不快取。
- 首次載入頁面:查詢結果序列化存檔 (`application/cache/db/{controller}+{method}/*.cache`)。
- 後續請求:直接讀取快取檔,**完全繞過資料庫**,DB 使用率降為 0。
- 快取檔**永不過期**,需手動刪除。
手動控制範例
<?php
$this->db->cache_on();
$query = $this->db->query("SELECT * FROM articles"); // 被快取
$this->db->cache_off();
$query = $this->db->query("SELECT * FROM user_session WHERE id = $uid"); // 不快取 (動態)
$this->db->cache_on();
$query = $this->db->query("SELECT * FROM categories"); // 再次快取
?>
清除快取
<?php
// 清除特定頁面 (依 URI 前兩段)
$this->db->cache_delete('blog', 'comments'); // 刪除 application/cache/db/blog+comments/
// 清除所有快取
$this->db->cache_delete_all();
// 注意:實測 cache_delete() 有時失效 (可能版本 Bug),cache_delete_all() 穩定。
?>
二、頁面快取 (Page Caching / Output Caching)
啟用方式
在**控制器方法內**任意位置呼叫:
$this->output->cache($minutes);
- `$minutes`:快取分鐘數,支援小數 (如 `1/60` = 1 秒)。
- 快取檔存放:`application/cache/{MD5_URI}.html`。
- **僅快取 View 輸出** (經 `$this->load->view()` 或 `echo` 送至輸出緩衝區的內容)。
- 需確保 `application/cache/` 可寫入。
運作流程
- 請求進入 → 檢查快取檔是否存在且未過期。
- **命中**:直接讀取檔案輸出,**不執行控制器邏輯**,極快。
- **未命中/過期**:執行控制器 → 捕獲輸出緩衝區 → 存檔 → 輸出。
停用與清除
- 移除 `$this->output->cache()` 程式碼 → 新請求不再產生快取,舊檔自然過期刪除。
- 立即清除:手動刪除 `application/cache/` 對應檔案。
三、常見問題與最佳實踐
| 問題 | 解決方案 |
| 快取不生效 | 檢查 `cachedir` 權限、`cache_on=TRUE`、是否為 SELECT 查詢 |
| 動態內容被快取 (如使用者名稱) | 用 `cache_off()` 包裹動態查詢,或改用片段快取 (第三方庫) |
| 集群環境檔案快取不同步 | 改用 Redis/Memcached 驅動 (CI3 需第三方庫,CI4 內建) |
| 快取檔案過多導致 inode 耗盡 | 定期 `cache_delete_all()`、調整目錄結構、改用記憶體快取 |
| 開發模式干擾 | 設定 `$config['cache_query_string'] = FALSE` 避免查詢字串產生多份快取 |
四、進階:片段快取與第三方擴充
CI 原生不支援區塊級快取 (如側邊欄、導航列)。建議:
- **CI3**:使用 `MatthiasMullie/Scrapbook`、`stensi/ci-cache` 或自寫 Helper 封裝 Redis/Memcached。
- **CI4**:內建 `CacheInterface` 支援 File/Redis/Memcached/RedisCluster,支援 `save()`/`get()`/`delete()` 任意鍵值,天然支援片段快取。
總結建議
- **資料庫快取**:適合靜態/半靜態報表、列表頁,配合 `cache_delete()` 於資料異動時清除。
- **頁面快取**:適合極高流量、內容變動極低的頁面 (首頁、靜態文章)。**避免**用於有使用者狀態、表單、動態推薦的頁面。
- **生產環境**:強烈建議將快取後端改為 **Redis/Memcached**,解決多伺服器同步、效能、inode 等問題。