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

Laravel基于有向无环图递归关系的任务依赖层级查询实现

Laravel 按依赖层级查询任务实现方案

首先建议先优化原关联定义,直接通过多对多关联获取关联的任务实例,无需手动操作中间表:

// Task 模型中新增/调整关联
// 当前任务依赖的父任务
public function parentTasks()
{
    return $this->belongsToMany(Task::class, 'dependent_tasks', 'task_id', 'dependent_id');
}

// 依赖当前任务的子任务
public function childTasks()
{
    return $this->belongsToMany(Task::class, 'dependent_tasks', 'dependent_id', 'task_id');
}

方案1:固定层级查询(适合层级少的场景)

直接按层级逐层查询,符合你给出的3层查询需求:

// 第一层:ID为2、5的任务
$level1 = Task::whereIn('id', [2, 5])->get();
$level1Ids = $level1->pluck('id');

// 第二层:第一层任务的直接子任务
$level2 = Task::whereHas('parentTasks', function ($query) use ($level1Ids) {
    $query->whereIn('tasks.id', $level1Ids);
})->get();
$level2Ids = $level2->pluck('id');

// 第三层:第二层任务的直接子任务
$level3 = Task::whereHas('parentTasks', function ($query) use ($level2Ids) {
    $query->whereIn('tasks.id', $level2Ids);
})->get();

// 按层级返回结果
$tasksByLevel = [
    1 => $level1,
    2 => $level2,
    3 => $level3
];

方案2:递归CTE查询(适合层级不固定的场景)

如果后续层级可能变动,使用公共表表达式递归查询,支持任意层级的依赖查询(要求数据库支持CTE,如MySQL 8.0+、PostgreSQL等):

$tasksByLevel = Task::query()
    ->selectRaw('tasks.*, 1 as level')
    ->whereIn('id', [2, 5])
    ->unionAll(
        Task::query()
            ->selectRaw('tasks.*, cte.level + 1 as level')
            ->join('dependent_tasks as dt', 'dt.dependent_id', '=', 'tasks.id')
            ->join('cte', 'cte.id', '=', 'dt.task_id')
    )
    ->withRecursiveExpression('cte')
    ->orderBy('level')
    ->get()
    ->groupBy('level');

查询结果会自动按level字段分组,直接通过$tasksByLevel[1]、$tasksByLevel[2]即可拿到对应层级的任务集合。

注意事项

如果保留原有的中间表关联定义,只需把上述查询中关联部分替换为对dependents/depends_on中间表的ID筛选即可,逻辑完全一致。由于你已经确认关联为有向无环图结构,无需额外处理循环依赖问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 01:24:02