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

如何通过Laravel Eloquent实现带条件的INNER JOIN(不使用DB查询)

解决Laravel Eloquent带条件的INNER JOIN需求

直接用whereHas方法就能实现你要的效果,它是Eloquent专门用来基于关联模型条件过滤主模型的API,底层会生成INNER JOIN语句,正好符合你需要的「只保留满足关联任务条件的项目」的要求,完全不需要写原生SQL。

基础用法示例

假设你要筛选出至少有一个状态为已完成的任务的项目,同时预加载符合条件的任务(避免N+1查询),代码如下:

Project::whereHas('tasks', function ($query) {
    // 这里写任务表的过滤条件
    $query->where('status', 'completed');
})->with(['tasks' => function ($query) {
    // 如果需要同时过滤预加载的任务数据,重复条件即可
    $query->where('status', 'completed');
}])->get();

为什么这个方法可行?

  • whereHas会自动生成INNER JOIN关联表的SQL,只返回存在满足条件的关联任务的项目,完全是INNER JOIN的行为,不会出现tasks为null的项目。
  • 搭配with是为了预加载符合条件的任务数据,避免后续访问每个项目的tasks时触发额外查询。如果不需要预加载关联数据,只保留whereHas部分即可。

组合主表和关联表条件

如果需要同时对主表(projects)和关联表(tasks)加过滤条件,直接链式调用where和whereHas即可:

Project::where('is_active', true) // 主表条件
       ->whereHas('tasks', function ($query) {
           $query->where('status', 'completed') // 关联表条件
                 ->where('due_date', '>', now());
       })
       ->with(['tasks' => function ($query) {
           $query->where('status', 'completed')
                 ->where('due_date', '>', now());
       }])
       ->get();

多层级关联的扩展用法

如果你的关联是多层级的(比如项目下的任务有子任务),可以用嵌套whereHas实现深层关联的过滤:

Project::whereHas('tasks.subtasks', function ($query) {
    $query->where('priority', 'high');
})->get();

这个方法比事后遍历数组过滤高效得多,因为过滤逻辑在数据库层面完成,避免了加载不必要的数据到内存中。

内容的提问来源于stack exchange,提问作者vbulash

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 01:27:04