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

Laravel关联查询问题:如何仅关联特定状态的Task并过滤结果

问题:Laravel中如何过滤预加载的关联Task模型

我有如下查询代码:

$projects = Project::with('tasks')
    ->select('projects.*')
    ->join('tasks', 'projects.id', '=', 'tasks.project_id')

我需要仅关联状态为特定值(例如done)的Task。目前尝试的写法如下:

$projects = Project::with('tasks', 'company')
    ->select('projects.*')
    ->join('tasks', 'projects.id', '=', 'tasks.project_id')
    ->where(function (Builder $query) use ($projectsListRequest){
        if (empty($projectsListRequest->taskStatus))
            return;
        $query->where('tasks.status', $projectsListRequest->taskStatus);
    })

但结果仍包含状态不符的Task。我猜测需要在join中添加额外条件,另外我觉得无论如何处理,tasks都会被预加载,因为模型中的tasks方法未添加过滤条件,但这只是我的猜测。


解决方案

你的猜测是对的:with('tasks')会直接加载模型关联方法定义的所有Task,主查询的where只会过滤出符合条件的Project,但不会影响预加载的关联数据。要解决这个问题,需要从过滤预加载关联和筛选目标Project两个层面处理:

1. 过滤预加载的Task关联

在with方法中传入闭包,专门对预加载的tasks进行过滤:

$projects = Project::with([
    'tasks' => function ($query) use ($projectsListRequest) {
        // 仅当有状态参数时,过滤task状态
        if (!empty($projectsListRequest->taskStatus)) {
            $query->where('status', $projectsListRequest->taskStatus);
        }
    },
    'company' // 保留原有的company关联
])

2. 筛选出包含符合条件Task的Project

如果你的需求是只获取至少有一个符合状态Task的Project,推荐用whereHas替代join,写法更简洁且避免重复数据:

->when(!empty($projectsListRequest->taskStatus), function ($query) use ($projectsListRequest) {
    $query->whereHas('tasks', function ($subQuery) use ($projectsListRequest) {
        $subQuery->where('status', $projectsListRequest->taskStatus);
    });
})

如果一定要用join,可以在join语句中添加条件,同时记得加distinct()避免Project重复:

->join('tasks', function ($join) use ($projectsListRequest) {
    $join->on('projects.id', '=', 'tasks.project_id');
    if (!empty($projectsListRequest->taskStatus)) {
        $join->where('tasks.status', $projectsListRequest->taskStatus);
    }
})
->distinct()

完整代码示例

$projects = Project::with([
    'tasks' => function ($query) use ($projectsListRequest) {
        if (!empty($projectsListRequest->taskStatus)) {
            $query->where('status', $projectsListRequest->taskStatus);
        }
    },
    'company'
])
->when(!empty($projectsListRequest->taskStatus), function ($query) use ($projectsListRequest) {
    $query->whereHas('tasks', function ($subQuery) use ($projectsListRequest) {
        $subQuery->where('status', $projectsListRequest->taskStatus);
    });
})
->select('projects.*')
->get();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 08:27:40