remember() 缓存的是终端方法(如get、first、count)执行后序列化得到的PHP值,包括数组、集合、标量或带关联数据的Eloquent对象,而非查询语句或构建过程。

remember() 只缓存终端方法执行后的结果,不缓存查询构建过程;它不是给模型“加缓存”,而是给一次 get()、first() 或 count() 的返回值贴个“快照”。
remember() 缓存的是什么数据
- 缓存内容是序列化后的 PHP 值:数组、集合、标量,或带关联数据的 Eloquent 对象(如用了
with('user')) - 不缓存查询语句本身,也不缓存中间状态(
where()、orderBy()等只是链式调用,没触发执行就不进缓存) -
remember(3600)->with('author')会把整条 SQL + 关联查出的数据一起缓存,下次命中直接反序列化返回,不重新走author()关系 - 如果闭包里写了
Log::info()或event(new SomethingHappened),这些副作用仍会每次执行——remember()只管“返回值”,不管“做了什么”
缓存键怎么生成的
- 默认键由完整 SQL 字符串 + 绑定参数值拼接后哈希生成,例如:
select * from `posts` where `status` = ? and `category_id` = ?
配合['published', 5]→ 键就是这个组合的 SHA256 - 所以
where('status', $status)中$status一变,就是新键,不会误 hit - 不是“SQL 模板”级缓存,不存在“同一 where 条件但不同值共用一个键”的问题
- 若想自定义键名,必须显式传参:
remember(3600, 'posts_active_list_v2'),否则调试时看到一堆哈希键,根本不知道来源
缓存失效必须手动处理
- Laravel 完全不监听模型变更,
Post::find(1)->update(['title' => 'new'])后,所有含该记录的remember()缓存依然有效 - 常见补救方式:
- 在模型的
saving/deleting事件中调用Cache::forget('your_custom_key') - 改用
Cache::tags(['posts'])->flush()(需 Redis/Memcached 驱动) - 把缓存键设计成可批量清除的形式,比如
"posts:{$status}:{$limit}",避免全库扫
- 在模型的
-
rememberForever()尤其危险:一旦写错逻辑或数据异常,只能靠人工清 Redis 或等服务重启(file 驱动下甚至可能永久残留)
和 Cache::remember() 混用容易翻车
-
Post::where(...)->remember(...)->get()底层就是调用Cache::remember(),再在外面套一层Cache::remember('key', ...)是冗余的 - 容易出现:
- 两层 TTL 冲突(外层 3600,内层 7200,实际谁生效?)
- 外层闭包返回空数组(因为内层缓存已存在但被清过,而外层没处理 miss 逻辑)
- 键名重复导致覆盖或未命中
- 真需要自定义逻辑(比如按用户角色分键、加版本号、压缩大对象),就别用模型上的
remember(),直接上Cache::remember("posts_{$role}_v3", ...)+ 手动构造查询
缓存键是否带业务语义、失效是否可控、驱动是否支持标签——这三个点,比“加不加 remember()”更能决定缓存到底有没有用。


















