yii::$app->cache需显式配置组件,键名须带版本和业务上下文,失效应结合依赖机制而非仅靠过期时间,读取时须用===false判断未命中。

直接用 Yii::$app->cache 就能读写缓存,但多数人卡在「缓存不生效」「数据没更新」「本地开发和线上行为不一致」这三类问题上——根本原因不是不会调用 API,而是没理清缓存组件配置、键名设计、失效逻辑这三层依赖关系。
缓存组件必须在 config/web.php 里显式声明
很多人以为 Yii 自带默认缓存,其实没有。不配 'cache' 组件,Yii::$app->cache 会返回 DummyCache(空实现),所有 set()/get() 都静默失败。
- 文件缓存(开发/低流量):
'class' => 'yii\caching\FileCache',注意确认runtime/cache目录可写 - Redis 缓存(生产推荐):
'class' => 'yii\redis\Cache',需提前安装php-redis扩展,并确保redis组件已配置 - 别漏掉
'redis' => ['hostname' => 'localhost', 'port' => 6379]这层嵌套,否则报Invalid Configuration – yii\base\InvalidConfigException
缓存键名要带业务上下文,不能只用数字或简单字符串
$cache->set('user_123', $data) 看似没问题,但一旦模型结构变更、序列化方式升级,旧缓存就变成脏数据,且无法批量清理。
- 建议加版本前缀:
'v2:user:123',升级时改v3即可自然淘汰旧数据 - 涉及多条件查询时,把参数拼进 key:
'article:list:status=1&limit=10',避免 key 冲突 - 不要用
serialize($obj)后的长字符串做 key —— Redis 对 key 长度有限制,且不易排查
缓存失效不能只靠过期时间,得配合依赖机制
设了 3600 秒过期,但用户刚编辑完文章,页面还显示旧内容,这就是典型的「被动等待过期」陷阱。
- 数据库变动触发失效:
new \yii\caching\DbDependency(['sql' => 'SELECT MAX(updated_at) FROM post']) - 文件变动监听:
new \yii\caching\FileDependency(['fileName' => '@app/config/params.php']) - 手动清除相关缓存:
Yii::$app->cache->delete('v2:post:456')或按前缀批量删(需缓存驱动支持,如 Redis 可用keys v2:post:*+del)
数据缓存必须检查 false 返回值,不能用 empty() 或 == null 判断
$data = $cache->get('key'); 命中缓存但值本身是 null、0、false 或空数组时,if (!$data) 会误判为未命中,导致重复查库。
- 必须严格用全等判断:
if ($data === false) - 如果业务允许缓存
false值,就改用标记包装:$cache->set('key', ['value' => $realData, 'exists' => true]) - 调试时加日志:
Yii::debug("Cache miss for key: 'v2:user:123'", __METHOD__);
最常被忽略的是缓存组件初始化时机和作用域——比如在 console 应用里用了 web 的 cache 配置,或在事件回调中访问了尚未 bootstrapped 的 Yii::$app->cache,这时返回的可能是未配置的默认实例,而不是你预期的那个 Redis 实例。











