In laravel Many to Many relationship like the one in the Laravel Documentation example. https://laravel.com/docs/9.x/eloquent-relationships#many-to-many
users
id - integer
name - string
roles
id - integer
name - string
role_user
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.
CodePudding user response:
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('users.id', $this->id);
})->get();
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 roles.id
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('users.id', $user->id);
})->get();
// OR
$availableRoles = Role::whereNotIn('id', $user->roles->pluck('id'))->get();