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

Laravel链式Scope查询中如何获取whereHas返回的用户ID执行后续查询

问题解决实现

修正后可直接运行的Scope代码

public function scopeLoadAvailableAgents($query)
{
    // Scope方法不要直接调用get(),保留链式调用能力,查询执行放在调用侧处理
    return $query->whereHas('roles', function ($q) {
            $q->where('name', 'agent');
        })
        ->whereNotIn('id', function ($q) {
            // 直接查询agent_to_manager表中所有已绑定的user_id集合即可
            $q->select('user_id')
                ->from(app(UserToManager::class)->getTable());
        });
}

逻辑说明

  • 第一层whereHas已经完成了「筛选拥有agent角色的用户」的逻辑,此时查询构造器已经限定了仅符合角色要求的用户范围
  • 第二层whereNotIn不需要单独获取前面的用户id,Laravel会自动将外层用户表的id字段和子查询返回的user_id集合做匹配,自动过滤掉存在于agent_to_manager表中的用户

更简洁的推荐写法

可以通过Laravel的whereDoesntHave关联查询方法简化代码,首先需要在User模型中提前定义和UserToManager的关联:

// app/Models/User.php 中添加关联定义
public function managerBinding()
{
    return $this->hasOne(UserToManager::class, 'user_id');
}

之后Scope可以简化为:

public function scopeLoadAvailableAgents($query)
{
    return $query->whereHas('roles', fn($q) => $q->where('name', 'agent'))
        ->whereDoesntHave('managerBinding');
}

调用示例

在需要查询的位置调用即可,支持后续拼接其他查询条件:

// 查询所有符合要求的用户
$availableAgents = User::loadAvailableAgents()->get();
// 也支持拼接分页等其他逻辑
$availableAgents = User::loadAvailableAgents()->paginate(10);

注意事项

  • 不要在Scope方法内部执行get()等最终查询操作,否则会破坏链式调用能力,无法后续拼接其他查询条件
  • 原写法的误区是误以为需要手动获取前面whereHas的查询结果传递给子查询,实际上whereNotIn会自动处理集合匹配逻辑,不需要手动传参绑定

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 10:36:08