Laravel Many To Many Получить элемент, с которым у меня нет отношений

В laravel отношение «многие ко многим», как в примере с документацией Laravel. 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

В модели пользователей у меня есть

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

В модели ролей у меня есть

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

Как я могу получить все роли, к которым я не имею отношения.

Я пробовал что-то вроде

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

Но это дает мне всю роль, которой нет ни у одного пользователя.

Любой намек на это.

🤔 А знаете ли вы, что...
PHP поддерживает объектно-ориентированное программирование.


2
14
1

Ответ:

Решено

Если у вас уже есть экземпляр User (я предполагаю, что это и есть $this?), вы можете просто отфильтровать отношение:

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

Это должно вернуть все элементы Role, если только эта роль не связана с User ($this, $user, auth()->user() и т. д.; при необходимости отрегулируйте).

Альтернативный подход: отфильтровать роль на основе существующих ролей:

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

Этот подход получает roles.id для User экземпляра.

Вы можете взглянуть на эффективность запроса и использовать тот, который работает лучше всего, но любой подход должен работать нормально.

Примечание. Если $this не является экземпляром User, настройте:

$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();