Ad

Laravel (5.7) Eloquent Many To Many With Query On Both Sides

Say I have a users, roles, and a pivot table. I have belongsToMany set up for both Role and User.

User Model:

<?php

namespace App;

...
use App\Models\Role;

class User extends Authenticatable
{
  ...
  public function roles()
  {
    return $this->belongsToMany(Role::class, "UserRoles", "userId", "roleId")
                ->withPivot("read", "write", "update", "delete")
                ->withTimestamps();
  }
}

Role Model:

<?php

namespace App\Models;

...
use App\User;

class Role extends Model
{
  ...
  public function users()
  {
    return $this->belongsToMany(User::class, "UserRoles", "roleId", "userId")
                ->withPivot("read", "write", "update", "delete")         
                ->withTimestamps();
  }

}

Table "Users":

userId username
1      admin
2      johndoe
3      menghour

Table "Roles":

roleId roleName
1      Admin
2      HR
3      Account

Pivot Table "UserRoles":

id     userId   roleId   read   write   update   delete
1      1        1        1      1       1        1
2      1        2        1      1       1        1
3      1        3        1      1       1        1
4      2        2        1      0       0        0
5      3        3        1      1       1        0

My question is how I can get filter in pivot table.

For example: I want to filter only userId or roleId or both userId and roleId

if I select user = admin in blade template, I want to get all roles that user have. expected result:

username    roleName

admin       Admin
admin       HR
admin       Account

if I select option role = HR in blade template,, I want to get all user that role have. expected result:

username    roleName

admin       HR
johndoe     HR

if I select option user = admin and role = HR, I want to get only specific user and role. expected result:

username    roleName

admin       HR

I've tired:

User::whereHas("roles", function ($query) use ($request) {
      if ($request->userId) {
        $query->where("userRoles.userId", "=", $request->userId);
      }
      if ($request->roleId) {
        $query->where("userRoles.roleId", "=", $request->roleId);
      }
    })->get();

note: I'm using Laravel 5.7

Ad

Answer

You could try this query to filter data as per your example.

The function whereHas is used to retrieve all the users with a given role. To get the roles of user you have to use with function.

$user = User::whereHas('roles', function ($query) use ($request) {
            if ($request->roleId) {
                $query->where("userRoles.roleId", "=", $request->roleId);
            }
        })
        // It will give you the user's role data.
        ->with('roles');

// It will check in users table if you have applied the filter by user.
if ($request->userId) {
    $user = $user->where("users.id", "=", $request->userId);
}

$user = $user->get();

You could also try this query to filter data as per your example. This query will give you the user with particular that role which has you given in roles object. For Example: if you select option role = HR in blade template.

$user = User::whereHas('roles', function ($query) use ($request) {
        if ($request->roleId) {
            $query->where("userRoles.roleId", "=", $request->roleId);
        }
    })
    // It will give you the user data with a particular given role which you has passed in the request.
    ->with(['roles' => function($query) use($request) {
        if ($request->roleId) {
            $query->where("roles.id", "=", $request->roleId);
        }
    }]);

// It will check in users table if you have applied the filter by user.
if ($request->userId) {
    $user = $user->where("users.id", "=", $request->userId);
}

$user = $user->get();
Ad
source: stackoverflow.com
Ad