首页 > 解决方案 > 使用 whereIn 从数据透视表返回数据

问题描述

所以我有Status class它与数据透视表的关系roles

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

这是Statusdb 表的外观:

id  title
1   status1
2   status2
3   status3

然后我的数据透视表如下所示:

status_id   role_id
1           2
2           2

现在我想queryrole_id=2.
基本上它应该返回这样的数据: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();

但现在它返回所有状态(status1、status2、status3)它应该只是(status1 和 status2)。我需要如何改变它?

标签: phplaravel

解决方案


此查询将返回所有附加到 id 为 2 的角色的状态:

Status::query()->whereHas('roles', function($q){
   $q->where('id', 2);
})->get();

它使用whereHas在您需要查询关系时可能有用的方法。

它可以做得更多,您应该查看有关此主题的文档:https ://laravel.com/docs/8.x/eloquent-relationships#querying-relationship-existence


快速说明:whereHas是做你想要实现的目标的“Laravel 首选方式”。

但是,您应该也可以使用此查询来执行此操作,它更接近您当前的代码:

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

// I replaced the leftJoin by join, which will exclude all results without roles (e.g. status id 3)

// or even simpler:

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

推荐阅读