ThinkPHP查询缓存怎么设_ThinkPHPRedis缓存加速介绍【教程】
ThinkPHP缓存配置:`config/cache.php`中`default`设为小写`'redis'`,`select`为整数,无密码时`password`写空字符串,PHP需装Redis扩展。`_cache()`参数为数组`[键,过期秒数,标签]`。模型缓存手动拼key防脏数据。`Cache::remember()`闭包需返回缓存值。
在开发中遇到 Cache::get() 返回 null,是件挺让人头疼的事。很多时候,问题根源并不复杂,就是缓存驱动根本没切换成功,你却浑然不知。
一个最直接的排查方法:执行下 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() 参数得是数组
_cache() 这个方法有点特殊。很多人误以为它是 Db 类的一个内置方法,其实不然。它是查询构造器的一个“钩子”,只在 select、find、value 这些执行方法前调用才有效。如果你写成 Db::table('user')->where()->_cache()->select(),大概率会直接报“方法未定义”的错误。
正确的姿势应该是这样:
Db::table('user')
->where('status', 1)
->_cache(['user_active_list', 1800, 'user'])
->select();
这里有三个关键点需要留意:
- 传给
_cache()的参数必须是数组,且顺序固定为:[缓存键, 过期秒数, 标签]。传个字符串或数字进去是无效的。 - 缓存键的命名是门学问。建议带上业务标识和查询条件的哈希值,比如
'user_list_' . md5($status . '_' . $type),这样能避免不同参数组合互相干扰。 - 第三个参数“标签”不是摆着好看的。它决定了你能不能优雅地进行批量清理,比如用
Cache::tag('user')->clear()一次性清除所有用户相关的缓存。
模型 cache(true) 不区分条件,手动拼 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),这种方式更可控,排查问题时也更直观。 - 千万别依赖
with('profile')这种关联预载入会自动加入缓存键,它不参与键的生成。查询with('profile')和with('posts')的结果可能会互相污染。
Cache::remember() 缓存失效,闭包里声明变量了吗?
Cache::remember('user_'.$id, 3600, function () use ($id) { return User::find($id); }) 这种写法是安全的。但如果你漏掉了 use ($id),写成 function () { return User::find($id); },问题就来了。ThinkPHP 6 会把整个闭包序列化后作为 key 的一部分,导致每次执行都生成一个不同的 key,结果就是“写进去了,但读不出来”。
还有个更隐蔽的坑是序列化失败。如果闭包里面用到了 $this、Request 或 Query 这样的对象,serialize() 会悄悄失败,缓存的值就变成了空。一个通用的解决方案是:写入前先用 json_encode() 处理,读取时再用 json_decode() 还原,这样可以绕过 PHP 序列化的那些限制。
最后,一个最容易被忽略的细节:缓存键里不要包含空格或中文,尤其在 file 驱动下,这会导致文件写入失败且没有任何报错。最稳妥的兜底方案,就是统一用 md5($key) 来处理,或者只保留字母、数字和下划线。


































