LARAVEL 5 ELOQUENT: ЧТО ЗНАЧИТ HAS, WITH, WHEREHAS

With

Применяется для жадной загрузки. То есть вместе с самой моделью Laravel загружает и связанные данные. Это полезно, если у вас есть коллекция моделей и для каждой вы хотите загрузить связанные данные. При жадной загрузке будет выполнен только один дополнительный запрос к базе данных.

Пример User > hasMany > Post:

$users = User::with(‘posts’)->get();

foreach($users as $user){

$users->posts; // посты уже загружены, нет запроса в каждой итерации цикла

}

Has

Применяется для фильтрации по связанным данным. Это очень похоже на обычно where-условие. Если вы используете has(‘relatiion’), то получите только те модели, у которых есть хотя бы одна связанная модель.

Пример User > hasMany > Post:

$users = User::has(‘posts’)->get();

// только пользователи с хотя бы одним постом

WhereHas

Работает как и has, но с возможностью указать дополнительные фильтры для связанной модели.

Пример User > hasMany > Post:

$users = User::whereHas(‘posts’, function($q){

$q->where(‘created_at’, ‘>=’, ‘2018-01-01 00:00:00’);

})->get();

// только пользователи с хотя бы одним постом 2018 года

Важно, что with добавляет связанные данные в коллекцию, а has и whereHas  — нет. Иногда может понадобиться применить with и has одновременно (или with и whereHas).

И есть еще такой вариант:

$books = Book::with([‘author’ => function($query) { $query->where(‘smth’, ‘val’); },

‘author.contacts’ => function($query) { $query->where(‘smth_else’, ‘one_more_val’); }])

->get();

Бывает и такое:

…->whereHas(‘university’, function($q) use($p) {

$q->whereHas(‘location’, function($q2) use($p) {

$q2->whereHas(‘city’,function($q3) use($p) {

$q3->where(‘region_id’, $p);

});

});

});