You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关联模型中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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 02:50:40