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

Laravel嵌套关联查询仅返回子级User表数据忽略父级数据

Laravel 嵌套关联查询仅返回最子级User数据方案

现有场景说明

涉及表结构:

  • Team表:字段为id、name、manager_id
  • Manager表:字段为id、company_id、user_id
  • User表:存储最终需要的用户数据
    已定义模型关联:
  • Team模型定义manager() belongsTo关联到Manager模型
  • Manager模型定义user() belongsTo关联到User模型
    原有查询从Team模型预加载manager.user关联,返回结果包含Team、Manager表冗余字段,目标是仅获取匹配条件的User集合。

可用实现方案

方案1:从User模型发起关联查询(推荐,性能最优)

原有写法从Team模型出发查询,天然会返回Team主模型数据,直接切换到User作为查询起点,通过whereHas做嵌套关联过滤,返回结果就是纯User模型集合,无任何冗余字段。
首先补全两个反向关联(如果没定义的话):

// 在Manager模型中添加和Team的反向关联
public function teams()
{
    return $this->hasMany(Team::class);
}

// 在User模型中添加和Manager的反向关联
public function manager()
{
    return $this->hasOne(Manager::class);
}

控制器查询代码:

$managerUsers = User::whereHas('manager.teams', function ($query) use ($company) {
    // 过滤指定公司下的团队
    $query->where('company_id', $company->id);
})->get();

如果需要分页,直接在该查询后调用->paginate()即可,和普通查询用法完全一致

方案2:基于原有查询提取子级数据(无需修改模型关联)

如果不想新增模型关联,可以在原有查询结果上通过集合方法提取嵌套的User数据,同时做去重和空值过滤:

$managerUsers = Team::with('manager.user')
    ->where('company_id', $company->id)
    ->get()
    ->pluck('manager.user') // 提取嵌套层级中的user对象
    ->filter() // 移除无关联user的空值条目
    ->unique('id') // 按用户id去重,避免同一用户关联多个团队时重复返回
    ->values(); // 重置集合连续键名

该方案缺点是会先查询Team、Manager表的全量字段,数据库IO开销更高,仅适合数据量较小的场景使用,且不支持直接调用框架分页方法。

方案3:Join联表直查(大数据量性能优先选择)

数据量达到十万级以上时,可以直接用联表查询,只查询User表字段,性能最高:

$managerUsers = User::query()
    ->join('managers', 'managers.user_id', '=', 'users.id')
    ->join('teams', 'teams.manager_id', '=', 'managers.id')
    ->where('teams.company_id', $company->id)
    ->select('users.*') // 显式指定只查询user表字段
    ->distinct() // 联表可能产生重复数据,添加去重逻辑
    ->get();

该方案不依赖模型关联定义,查询效率最高,但会丢失模型关联的动态加载能力,适合纯列表查询场景。


避坑说明

with()预加载方法的设计逻辑是返回主模型+所有指定关联的模型数据,只要从Team模型作为主模型发起查询,就必然会返回Team表字段,不存在只返回子关联的配置,需要返回纯子级数据时必须切换查询主模型或者做结果集提取。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 22:48:21