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

Laravel关联中间表查询:使用whereIn过滤后仍返回全部Status数据如何修正

问题描述

我有一个Status class,它和roles之间通过中间表建立了关联关系,关联定义如下:

public function roles(): 
{
   return $this->belongsToMany(Role::class, 'status_role', 'status_id', 'role_id');
}

Status数据库表结构如下:

idtitle
1status1
2status2
3status3

对应的关联中间表结构如下:

status_idrole_id
12
22

现在我需要编写query查询所有关联role_id=2的status记录,预期返回结果为status1、status2,不包含status3。
我目前的实现代码如下:

$statuses = Status::query()
            ->leftJoin('status_role', function ($join) {
                $join->on('statuses.id', '=', 'status_role.status_id')
                    ->whereIn('status_role.role_id',[2]);
            })
            ->get();

但当前写法会返回全部3条status记录,不符合需求,请问应该如何修改查询语句?


解决方案

你当前写法返回全部记录的核心原因是使用了leftJoin左连接:左连接会保留左表(statuses表)的所有记录,即使右表没有匹配项也会返回,因此无关联的status3也会被查询出来。

方案1:使用Eloquent关联查询whereHas(推荐)

你已经定义了roles关联,直接使用whereHas方法即可,无需手动编写join逻辑,代码更简洁易维护:

$statuses = Status::whereHas('roles', function ($query) {
    $query->where('role_id', 2);
})->get();

whereHas的作用就是仅返回满足关联条件的模型记录,完全匹配你的需求。

方案2:修改join类型为内连接

如果你需要保留手动写join的写法,把leftJoin改为join(Laravel中join默认是内连接),内连接仅返回两表都有匹配的记录,额外加distinct避免同一status关联多个符合条件的role时返回重复数据:

$statuses = Status::query()
            ->join('status_role', function ($join) {
                $join->on('statuses.id', '=', 'status_role.status_id')
                    ->where('status_role.role_id', 2);
            })
            ->distinct()
            ->get();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 21:06:02