CI页面缓存仅对$this->load->view()生效,数据库缓存需显式调用cache_on(),CI4缓存驱动可能因backupHandler降级失效,片段缓存需手动管理key且不支持嵌套视图自动识别。

页面缓存只对 $this->load->view() 生效
很多开发者写了 $this->output->cache(60) 却发现缓存文件始终不生成,根本原因是:CI 的页面缓存机制只拦截并保存 $this->load->view() 渲染后、经 $this->output 输出的完整 HTML 响应。以下情况会直接绕过缓存:
- 控制器中用
echo、print_r()或json_encode()直接输出内容 - 调用
return返回数据(比如 REST API 返回数组) - 使用了
$this->output->set_content_type()->set_output()手动设置输出 - 视图未被真正加载(例如条件分支跳过了
$this->load->view())
验证是否命中缓存最简单的方式是访问后立刻检查 application/cache/(CI3)或 writable/cache/(CI4)目录下是否有新增的多层哈希子目录和文件,且修改时间与请求时刻一致。
数据库缓存必须配合 $this->db->cache_on() 显式开启
CI 的数据库查询默认不缓存,哪怕你配置了 $db['default']['cachedir']。缓存开关由方法调用控制,且作用域仅限当前查询链:
-
$this->db->cache_on()后执行的get()、query()等才会写入缓存文件 -
$this->db->cache_off()之后的查询不再缓存,但不会自动清除之前缓存的内容 - 缓存键基于完整 SQL 语句 MD5 + 当前 URI 路径生成,相同 SQL + 相同路由才复用
- 缓存文件结构为
default+index/[md5_hash](CI3)或按 TTL 分片存储(CI4),不是明文可读
注意:带 WHERE user_id = ? 占位符的查询,若传入不同参数,会生成不同缓存文件;但若 SQL 字符串完全一样(比如硬编码 ID),则所有请求共用同一份缓存 —— 这极易导致数据陈旧。
CI4 的 cache 驱动切换常因 backupHandler 静默降级失败
在 CI4 中把 $handler 改成 'redis' 后仍看到缓存写到文件,大概率不是配置没生效,而是主驱动初始化失败后自动 fallback 到 $backupHandler。而默认 $backupHandler = 'dummy' 就等于不缓存,且无任何报错提示。
- 运行
php spark cache:info查看实际生效的 handler 和连接状态 - 确保
$backupHandler设为'file'而非'dummy',避免雪崩时彻底失能 - 检查 Redis 扩展是否启用:
extension=redis.so(Linux)或extension=php_redis.dll(Windows) -
$this->cache->save('key', $data)返回false时不抛异常,务必手动判断并记录日志
CI4 的缓存是「写失败即忽略」设计,生产环境必须主动校验返回值,否则你以为缓存着,其实每次都在穿透。
片段缓存需手动管理 key,且不支持嵌套 view 自动识别
CI 没有内置的「自动片段缓存」,所谓片段缓存本质是用 $this->load->view() 第三个参数传入缓存键名,再由底层判断是否从缓存读取。它不感知视图内部结构,也不递归处理 $this->load->view('partial') 子调用。
- 缓存键必须唯一且稳定,推荐组合业务标识,如
'product_list_'.$category_id.'_'.$page - 如果视图里又加载了其他子视图,那些子视图不会被自动缓存,除非你也给它们单独加 key
- 更新数据后,需调用
$this->db->cache_delete_all()或更精准的$this->db->cache_delete('controller','method'),否则缓存长期 stale - CI3 的片段缓存依赖文件系统,高并发下可能因文件锁导致阻塞;CI4 推荐统一走
$this->cache实例,支持原子操作
别指望一个 cache_key 覆盖整个区块的所有动态子内容 —— 缓存粒度是由你定义的 key 决定的,不是由 view 层级决定的。


















