thinkphp模型查询缓存需显式调用cache()且必须置于find()/select()之前;仅对这两方法生效,不加参数则永不过期;支持自定义键、过期时间及标签,但count等聚合查询和事务内查询不走缓存。

ThinkPHP 的模型查询缓存不是自动开启的,必须显式调用 cache() 方法,且默认只对 find() 和 select() 有效;不加参数时缓存永不过期,容易导致数据陈旧。
cache() 方法怎么写才生效
只有在模型查询链中调用 cache() 才会启用缓存,它必须出现在 find() 或 select() 之前。单独对模型实例调用 cache()(如 $model->cache())无效。
-
$user = User::where('id', 1)->cache()->find();✅ 生效 -
$user = User::cache()->where('id', 1)->find();✅ 生效(cache()是查询构造器方法,支持链式前置) -
$user = User::where('id', 1)->find()->cache();❌ 报错:返回的是数组/对象,没有cache()方法 -
User::cache(); User::where('id', 1)->find();❌ 不生效:静态调用未绑定到当前查询
缓存键名和过期时间怎么控制
默认缓存键由完整 SQL、绑定参数、数据库配置哈希生成,基本可避免冲突;但若需手动指定键或设置过期,得传参:
- 仅设过期时间:
->cache(3600)表示缓存 1 小时 - 自定义键 + 过期:
->cache('user_123', 3600) - 使用缓存标签(需缓存驱动支持,如 Redis):
->cache('user_123', 3600, ['user']) - 注意:
cache(false)可强制跳过缓存(用于调试或实时场景)
缓存键不含模型名称,纯靠 SQL 特征识别,所以 User::where('status', 1)->select() 和 User::where('status', 1)->order('id desc')->select() 是两个不同缓存项。
哪些查询不走 cache() 缓存
cache() 仅作用于最终执行读取的方法,以下情况完全绕过缓存机制:
-
count()、sum()、max()等聚合查询 —— 它们走的是query()底层,不触发缓存逻辑 -
value()、column()—— ThinkPHP 6.0+ 默认也不缓存,除非显式加cache()且驱动支持(部分版本需升级到 v6.0.13+) - 事务内查询 —— 即使写了
cache(),TP 也会自动禁用,防止脏读 - 使用了
lock(true)或useSoftDelete(false)等特殊选项的查询,可能破坏缓存一致性,框架主动跳过
缓存失效和手动清理怎么做
ThinkPHP 不提供自动缓存失效策略(比如“更新用户时自动删 user_* 缓存”),全靠手动管理:
- 单条清除:
Cache::delete('user_123') - 按标签批量清除(Redis):
Cache::tag('user')->clear() - 模型更新后建议顺手清缓存:
User::update($data); Cache::delete('user_'.$data['id']); - 注意:如果用了默认键(无自定义 key),清除困难 —— 此时应始终显式传 key,否则只能 flush 整个缓存池
缓存驱动选 Redis 比 file 更可靠,file 驱动在并发下存在缓存覆盖或读空风险,且无法支持标签功能。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











