Laravel (whereHas, has, with)

Поговорим об Eloquent, связях и полезных методах для работы с ними.

В этой записи я хотел бы обратить внимание на три метода (whereHas, has, with), подробное описание которых можно найти в официальной документации.

Для того, чтобы использовать данные методы, нужно указать связь в модели. Например, возьмём модель user и укажем связь к его сообщениям так:

public function messages()
{
    return $this->belongsToMany(Message::class, 'message_users');
}

With

Используется для жадной загрузки данных модели. С помощью этого метода можно получить сообщения каждого пользователя:

$users = User::with('messages')->get();
foreach($users as $user){
    $users->messages;
}

Таким образом не происходит запроса для каждого пользователя. Система делает один дополнительный запрос и добавляет результат к каждой записи.

Has

Это фильтр, который позволяет фильтровать записи по определённой связи. Возьмём те же сообщения и получим только тех пользователей, у которых есть сообщения (есть связанные модели).

$users = User::has('messages')->get();

WhereHas

Этот метод похож на Has, но позволяет указать дополнительные условия фильтрации. К примеру, получим сообщения пользователя, которые уже были им просмотрены.

$users = User::whereHas('messages', function($q){
    $q->where('viewed', true);
})->get();

Эти методы можно комбинировать в одном запросе, если у вас продвинутые связи.