codeigniter4页面缓存需显式配置cache.php的$handler(如'file'或'redis'),在控制器方法内输出前调用$this->cachepage($seconds),并合理设置$cachequerystring以确保缓存键准确。

CodeIgniter4 的页面缓存不是“开个开关就提速”,它依赖明确的缓存处理器配置和正确的调用时机;没配好 Cache.php 或误用 $this->cachePage(),反而会导致 500 错误或缓存完全不生效。
缓存必须先配 app/Config/Cache.php 才能用
很多人写完 $this->cachePage(60) 发现页面没缓存,根本原因是缓存后端没启用。CI4 默认不自动启用任何缓存处理器,$handler 必须显式设为 'file'、'redis' 等有效值,否则 cachePage() 会静默失败。
-
$handler设为'dummy'(默认值之一)→ 缓存写入直接丢弃,无报错但无效果 -
file处理器要求$file['storePath']目录可写,且权限正确(如0640),否则日志里出现failed to open stream: Permission denied - Redis/Memcached 需提前安装扩展并确保服务可达,
get()方法内部调用unserialize(),若缓存数据被污染可能触发反序列化漏洞(尤其 CI4 早期版本)
$this->cachePage($seconds) 只在控制器方法内有效
这个函数不是全局钩子,不能放在构造函数、__construct() 或中间件里——它只对当前响应体生效,且必须在输出生成前调用。常见错误包括:
- 放在
return view()之后 → 缓存逻辑被跳过 - 在重定向逻辑中调用(如
return redirect()->to(...))→ 实际返回的是 302 响应,缓存内容为空或损坏 - 在 AJAX 请求中使用 → 若前端未处理缓存头,可能拿到过期 HTML 而非 JSON
它实际作用是:标记当前请求响应需缓存,并设置 TTL(单位为秒),不是分钟。传 60 表示缓存 1 分钟,传 0 会禁用缓存(CI4.4+ 支持)。
缓存键由 URI + 查询字符串决定,$cacheQueryString 很关键
默认情况下,/products?category=shoes 和 /products?category=hats 会被视为同一个缓存键,因为 CI4 默认忽略查询参数。这容易导致内容错乱。
- 设
$cacheQueryString = true→ 完整包含 query string,适合列表页分页、筛选等场景 - 设
$cacheQueryString = ['page', 'sort'](数组)→ 仅取指定参数参与键生成,排除utm_source等干扰项 - 设
$cacheQueryString = false(默认)→ 所有查询参数被丢弃,/a?id=1和/a?id=2共享缓存,务必确认业务是否允许
注意:缓存键生成时会 clone 当前 $request->getUri(),所以中间件修改 URI 不影响原始键,但会影响后续请求匹配。
文件缓存路径和清理机制容易被忽略
CI4 的文件缓存写入 WRITEPATH . 'cache/'(通常是 writable/cache/),但这个目录不会自动清理过期文件——靠的是每次请求时读取缓存前检查 mtime。这意味着:
- 大量过期缓存文件长期堆积,占用磁盘空间,且扫描开销随文件数增长
- 手动删
writable/cache/是最彻底的清缓存方式,比改 TTL 更可靠 -
cachePage()不会自动清除旧缓存,新请求覆盖同名键,但旧文件仍残留 - CLI 场景下(如定时任务刷新首页),需主动调用
cache()->delete('key')或用php spark cache:clear命令
真正要稳住缓存行为,得盯住三件事:配置里的 $handler 和 $ttl 是否生效、控制器里 cachePage() 是否在正确位置调用、以及查询参数是否被合理纳入缓存键——漏掉任意一环,缓存就只是个幻觉。











