Yii缓存需显式配置组件并挂载为'cache'键,支持FileCache和RedisCache等类型,后者要求redis扩展及服务可用;$cache->get()返回false多因存储不可用或key不匹配;PageCache需在behaviors中声明且满足响应条件;FragmentCache需注意key唯一性和上下文隔离;缓存更新需手动清理或用tag机制。

Yii 框架缓存不是“开个开关就生效”,必须显式配置组件、显式调用方法,且不同缓存类型对环境和依赖有硬性要求——比如 yii\redis\Cache 要求 PHP 安装 redis 扩展且 Redis 服务可连,yii\caching\FileCache 则依赖 runtime/cache/ 目录可写。
如何在 config/web.php 中正确注册 cache 组件
缓存组件必须挂载在 'components' 数组下,且键名固定为 'cache'(框架内部硬编码查找)。类名决定行为,不能拼错:
-
'cache' => ['class' => 'yii\caching\FileCache']:最轻量,适合开发或单机小流量,缓存文件落在@runtime/cache/下,注意该目录需有写权限 -
'cache' => ['class' => 'yii\redis\Cache', 'redis' => ['hostname' => 'localhost', 'port' => 6379, 'database' => 0]]:必须确保redis扩展已启用,且连接参数与实际 Redis 实例一致;database值超出范围会静默失败(如 Redis 配置只允许 db 0–15,却设为 16) - 集群模式要换用
'class' => 'yii\redis\Cache'+'clusters'配置项,不能复用单点的'redis'键,否则报Invalid Configuration – yii\base\InvalidConfigException
为什么 $cache->get() 总是返回 false
这不是代码写错了,大概率是底层存储不可用或 key 不匹配。常见原因包括:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 缓存组件未成功初始化:检查
Yii::$app->cache是否为 null,或抛出InvalidConfigException异常(常因扩展缺失或连接超时) - key 被自动加了前缀但你没意识到:
yii\redis\Cache默认不加前缀,但若配置了'keyPrefix' => 'myapp_',那么$cache->get('user_list')实际查的是myapp_user_list,而你可能用 redis-cli 直接 set 的是裸 key - 序列化失败:缓存值含闭包、资源句柄或未定义类实例时,
set()会静默失败(FileCache 尤其明显),建议先var_dump(serialize($data))确认可序列化
页面缓存(PageCache)为什么没生效
PageCache 是控制器级过滤器,它绕过整个 action 执行,所以必须满足三个条件才起作用:
- 过滤器必须在
behaviors()中声明,且'class'值为'yii\filters\PageCache'(注意不是yii\caching\PageCache,后者不存在) -
'only'指定的动作必须是当前请求匹配的,比如配了['index']却访问/site/about,自然不触发 - 响应必须是 200 状态且 Content-Type 为 text/html;如果 action 内部调用了
Yii::$app->response->statusCode = 404或输出了 JSON,PageCache 会自动跳过 - 默认不缓存带 GET 参数的请求(如
?id=123),需显式配置'variations' => ['GET']或指定具体参数名
片段缓存(Fragment Cache)中 begin()/end() 的坑
片段缓存写在视图里,看着简单,但容易忽略上下文隔离问题:
-
beginCache()的第一个参数是 cache key,**必须唯一且稳定**;如果 key 含动态变量(如'user_'.$id.'_profile')但$id在某些场景下未定义,会导致 key 变成user__profile,和其他用户混用缓存 - 缓存内容包含 PHP 输出(如
echo $model->name)没问题,但**不能包含 exit/die 或修改全局状态的代码**(如Yii::$app->user->login()),因为缓存命中时这些代码根本不执行 - 嵌套使用时,外层缓存时间不能短于内层,否则可能出现外层已过期重建,但内层仍返回旧数据的情况
缓存最麻烦的从来不是配置语法,而是“什么时候该清”和“谁负责清”。比如用户资料更新后,User::updateAll() 不会自动删掉 user_list 缓存,得手动 Yii::$app->cache->delete('user_list') 或用 tag 机制批量管理——这点文档提得少,但线上事故多源于此。

















