Laravel 8 中关联模型缓存需将 with() 与 remember() 结合使用,确保预加载数据整体缓存、键名唯一可追踪,并在关联变更时主动清除;remember() 必须紧邻 get()/first()/paginate() 调用,分页、多级关系、动态预加载均适用对应策略。

在 Laravel 8 中对关联模型查询做缓存,核心是**把预加载(with)和缓存逻辑结合**,避免 N+1 同时防止重复查库。不能只缓存主模型,还要确保关联数据一并被缓存、键名可追踪、更新时能精准失效。
用 remember() 封装带 with() 的完整查询
Eloquent 的 remember() 支持链式调用,只要放在 get()、first() 或 paginate() 前即可,它会缓存整个查询结果(含预加载的关联数据)。
- 正确写法:
User::with('posts.comments')->where('active', true)->remember(3600, 'active_users_with_posts')->get() - 错误写法:
User::remember(3600)->with('posts')->get()——remember()必须紧邻终值方法,否则不生效 - 分页也适用:
Post::with('author', 'tags')->where('published', 1)->remember(7200, 'published_posts_paginated')->paginate(20)
为不同关联组合设计唯一缓存键
同一模型多次调用 with() 但关联不同(如 with('profile') vs with('orders')),必须用键名区分,否则缓存互相覆盖。
- 推荐拼接关系名:
'user_'.$id.'_with_profile'、'user_'.$id.'_with_orders' - 含多级关系时保留路径:
'post_'.$id.'_with_author_and_tags' - 避免空格、斜杠等非法字符;可用
md5()或sha1()哈希参数后拼接前缀,提升健壮性
关联变更时主动清除缓存
Laravel 不自动监听关联表变化。比如用户更新了头像(profile 表改了),但 User::with('profile')->remember(...)->first() 缓存不会失效。
- 在关联模型(如
Profile)中注册观察器,updating或updated时调用:Cache::forget('user_'.$profile->user_id.'_with_profile') - 若用标签(tags),需 Redis/Memcached 驱动支持:
Cache::tags(['user', 'profile'])->remember(...),然后Cache::tags(['profile'])->flush() - 批量更新(如
Profile::where(...)->update(...))不触发模型事件,得额外补清理逻辑
用 Cache::remember() 手动封装更灵活的场景
当关联逻辑复杂(如动态 with、条件预加载、跨模型聚合),直接用 Cache::remember() 更可控。
- 示例:
Cache::remember('user_'.$id.'_dashboard_data', 1800, fn() => User::with(['posts', 'notifications' => fn($q) => $q->where('read', false)])->find($id)) - 闭包内必须
return结果,且所有外部变量(如$id)要use ($id) - 不建议嵌套
->remember(),易导致键冲突或空缓存


















