cache::get()总返回null,大概率仍是file驱动未切换成功;需确认config/cache.php中default为小写'redis'、stores.redis配置完整、php已加载redis扩展,并验证缓存是否真实写入redis。

Cache::get() 总是返回 null,先确认驱动真切过去了
不是配置写了 default => 'redis' 就算数——Cache::get() 返回 null 的最大概率,是你还在用 file 驱动,只是没察觉。运行 php -r "var_dump(cache('test', 'ok', 10)); var_dump(cache('test'));",如果第二次输出 bool(false),说明缓存根本没通。
检查三处硬性条件:
-
config/cache.php中default必须是小写'redis'(不是'Redis'或'REDIS') -
stores.redis配置块必须存在,且select是整数(写成"0"会静默失败),password即使为空也得显式写'' - PHP 环境里必须已加载
redis扩展:php -m | grep redis有输出,或phpinfo()里能看到 Redis 模块
Db 查询加缓存,_cache() 必须放在 select 前且参数是数组
_cache() 不是 Db 类方法,是查询构造器临时注入的钩子,只对 select、find、value 这类最终执行方法生效,且必须紧挨在它们前面调用。写成 Db::table('user')->where()->_cache()->select() 会直接报 Call to undefined method。
正确写法是:
Db::table('user')
->where('status', 1)
->_cache(['user_active_list', 1800, 'user'])
->select();
注意三点:
- 参数必须是数组,顺序固定:[缓存键, 过期秒数, 标签];传字符串或单独数字会失效
- 缓存键建议含业务标识和条件哈希,比如
'user_list_' . md5($status . '_' . $type),避免不同参数组合命中同一缓存 - 标签(第三个参数)不是可选装饰——它决定了你后续能不能用
Cache::tag('user')->clear()批量清理
模型 cache(true) 不区分 where 条件,手动拼 key 才靠谱
UserModel::where('status', $status)->cache(true)->select() 看似开了缓存,实际生成的键只含类名和方法名(如 think:UserModel:select),所有 $status 值都共用一个缓存,必然脏数据。
要真正按条件隔离,必须手动构造唯一键:
- 用数组方式:
cache(['user_list', $status, $type], 300),ThinkPHP 会自动序列化为稳定字符串 - 用字符串拼接:
cache('user_list_' . md5($status . '_' . $type), 300),更可控,也方便 debug - 别依赖
with('profile')自动进缓存键——它不参与键生成,查with('profile')和with('posts')可能互相污染
Cache::remember() 缓存失效,大概率是闭包里用了未声明变量
Cache::remember('user_'.$id, 3600, function () use ($id) { return User::find($id); }) 是安全的;但如果你写成 function () { return User::find($id); }(漏了 use ($id)),TP6 会把整个闭包对象序列化进 key,每次执行都生成新 key,导致“写进去读不出”。
更隐蔽的问题是序列化失败:
- 闭包里用了
$this、Request或Query对象,serialize()会静默失败,缓存值变空 - 解决方案:一律先
json_encode()再缓存,读取时json_decode(),绕过 PHP 序列化限制 - 验证是否真存进去了:用
redis-cli get 'cache:user_123'直接查 Redis,看是空、乱码还是正常 JSON
最易被忽略的是缓存键里的非法字符——file 驱动下,键含空格或中文会导致文件写入失败却无报错;统一用 md5($key) 或只保留字母数字下划线,是最简单有效的兜底方案。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











