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

如何在Laravel中使用whereHas查询满足特定关联条件的Task记录

Laravel Eloquent 实现Task查询需求

需求回顾

数据库结构:

scripts (id, parent_id, name)
tasks (id, script_id, name)

需要查询满足以下任一条件的Task:

  • 关联的Script的parent_id为null
  • 存在Script记录,其parent_id等于该Task的script_id(即tasks.script_id = scripts.parent_id)

实现方案

方案一:直接使用whereExists构造子查询

无需额外定义关联,直接通过子查询匹配条件:

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;

$tasks = Task::query()
    ->where(function (Builder $query) {
        // 条件1:关联的script无父级
        $query->whereHas('script', fn (Builder $subQuery) => $subQuery->whereNull('parent_id'))
              // 条件2:当前script是其他script的父级
              ->orWhereExists(fn (Builder $subQuery) => $subQuery
                  ->select(DB::raw(1))
                  ->from('scripts')
                  ->whereColumn('scripts.parent_id', 'tasks.script_id')
              );
    })
    ->get();

方案二:利用Eloquent关联简化代码

如果你的Script模型已定义children关联(表示该script的子script),可以用更简洁的写法:

首先在Script.php中定义关联:

// app/Models/Script.php
public function children()
{
    return $this->hasMany(Script::class, 'parent_id');
}

然后编写查询代码:

use Illuminate\Database\Eloquent\Builder;

$tasks = Task::query()
    ->where(function (Builder $query) {
        $query->whereHas('script', fn (Builder $subQuery) => $subQuery->whereNull('parent_id'))
              ->orWhereHas('script.children');
    })
    ->get();

说明

  • 两种方案逻辑完全等价,均可满足查询需求
  • 方案一无需额外定义关联,适合临时查询场景;方案二代码更简洁,适合需要多次使用该关联的场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 17:09:46