Laravel Many To Many Get element that I dont have a relationship with

In laravel Many to Many relationship like the one in the Laravel Documentation example.

    id - integer
    name - string

    id - integer
    name - string

    user_id - integer
    role_id - integer

In the Users model I have

public function roles()
    return $this->belongsToMany(Role::class);

In the Roles model I have

public function users()
    return $this->belongsToMany(User::class);

How can I get all Role that I don’t have a relationship to.

I tried thing like

$this->availableRoles = Role::doesntHave('users')->get();

But this give me all the Role that no user at all have

Any hint on this.

>Solution :

If you already have a User instance (I assume that is what $this is?), then you can simply filter the relationship:

$this->availableRoles = Role::whereDoesntHave('users', function ($subQuery) {
  return $subQuery->where('', $this->id);

This should return all Role elements, unless that Role has an association with the User ($this, $user, auth()->user(), etc.; adjust as required).

An alternative approach, filter out Role based on existing Roles:

$this->availableRoles = Role::whereNotIn('id', $this->roles->pluck('id'))->get();

This approach get’s the for the User instance.

You can take a look at query efficiency and use the one that works best, but either approach should work fine.

Note: If $this is not a User instance, adjust:

$user = User::find($userId); // or `auth()->user()`, etc.

$availableRoles = Role::whereDoesntHave('users', function ($subQuery) use ($user) {
  return $subQuery->where('', $user->id);

// OR

$availableRoles = Role::whereNotIn('id', $user->roles->pluck('id'))->get();

Leave a Reply