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

如何用Eloquent实现带OR运算符的BelongsToMany关联查询?

用Eloquent实现指定SQL查询及双向查询方案

已知User与Team模型为多对多(BelongsToMany)关联,要实现以下SQL的查询逻辑,同时支持从两个模型双向发起查询:

SELECT * FROM teams t WHERE
  owner_id = '{auth_id}'
  OR EXISTS (SELECT * FROM team_user WHERE team_id = t.id AND user_id = '{auth_id}')

前提假设

  • Team模型包含owner_id字段,关联到User模型的主键
  • User模型定义多对多关联方法:
    public function teams()
    {
        return $this->belongsToMany(Team::class);
    }
    
  • Team模型定义多对多关联方法:
    public function users()
    {
        return $this->belongsToMany(User::class);
    }
    

从Team模型发起查询

直接通过Team模型构造查询,完全匹配原SQL逻辑:

$authId = auth()->id();

$teams = Team::where('owner_id', $authId)
    ->orWhereHas('users', function ($query) use ($authId) {
        $query->where('user_id', $authId);
    })
    ->get();

where('owner_id', $authId)对应原SQL的所有者条件,orWhereHas会自动生成EXISTS子查询,匹配用户作为团队成员的条件,和原SQL子查询逻辑一致。


从User模型发起查询

从User模型出发,需获取该用户作为所有者的团队+作为成员的团队,有两种实现方式:

方式1:合并关联查询与所有者团队查询

$authUser = auth()->user();

// 获取用户作为成员的团队
$memberTeams = $authUser->teams;
// 获取用户作为所有者的团队
$ownerTeams = Team::where('owner_id', $authUser->id)->get();

// 合并结果并去重
$allTeams = $memberTeams->merge($ownerTeams)->unique('id');

方式2:单次数据库查询(推荐)

通过子查询一次性获取所有符合条件的团队,仅发起一次数据库请求:

$authId = auth()->id();

$teams = Team::where('owner_id', $authId)
    ->orWhereIn('id', function ($subQuery) use ($authId) {
        $subQuery->select('team_id')
            ->from('team_user')
            ->where('user_id', $authId);
    })
    ->get();

双向查询可行性

完全可以从User和Team两个模型双向发起该查询:

  • 从Team模型出发:直接通过模型查询构造器组合条件,逻辑最贴近原SQL
  • 从User模型出发:结合用户的关联团队与所有者团队,可通过结果合并或单次查询实现

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 03:35:17