如何用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
相关产品推荐
相关产品推荐

