关联模型中where()搭配with()与whereHas()的使用差异是什么?
区分 Eloquent 中
with()->where() 和 whereHas()->where() 的差异 核心差异一句话说清:
whereHas()是过滤主表数据:只保留存在符合条件关联记录的主表条目,关联数据默认加载全部(可额外加约束)。with()->where()是过滤关联数据:主表所有条目都会返回,但关联字段仅加载符合where条件的部分,主表本身不会被筛选。
1. whereHas() 的用法(过滤主表)
假设我们有 Post(帖子)和 Comment(评论)两个模型,关联关系为 Post hasMany Comment。
如果想只获取存在「已审核评论」的帖子,用 whereHas:
$posts = Post::whereHas('comments', function ($query) { $query->where('status', 'approved'); })->get();
- 结果:只有那些至少有1条已审核评论的帖子会被返回。
- 补充:如果想同时过滤关联数据(只加载已审核评论),需要结合
with一起用:
$posts = Post::whereHas('comments', function ($query) { $query->where('status', 'approved'); })->with('comments', function ($query) { $query->where('status', 'approved'); })->get();
这样既筛选出有审核评论的帖子,又只加载每个帖子的审核评论。
2. with()->where() 的用法(过滤关联数据)
如果想获取所有帖子,但每个帖子只加载已审核的评论,用 with 加闭包约束:
$posts = Post::with('comments', function ($query) { $query->where('status', 'approved'); })->get();
- 结果:所有帖子都会被返回,哪怕某个帖子没有任何已审核评论(此时该帖子的
comments字段是空数组)。 - 关键点:主表数据完全不受关联条件影响,只是关联数据被过滤了。
适用场景总结
- 当你需要筛选主表条目(只保留满足关联条件的主记录):用
whereHas() - 当你需要保留所有主表条目,但只加载符合条件的关联数据:用
with()->where()
内容的提问来源于stack exchange,提问作者Raj
相关产品推荐
相关产品推荐

