Метод withWhereHas
Метод withWhereHas применяется к запросу Eloquent
и позволяет загрузить связанные модели, при этом
накладывая условия на выборку родительских записей.
Первым параметром передаётся имя отношения, вторым -
замыкание с условиями фильтрации. В результате запрос
вернёт только те записи, у которых есть связанные модели,
удовлетворяющие заданным условиям, и сразу загрузит
эти связи.
Синтаксис
<?php
Model::withWhereHas($relation, $callback);
?>
Пример
Давайте получим все статьи, у которых есть комментарии с текстом 'great':
<?php
use AppModelsArticle;
$articles = Article::withWhereHas('comments', function ($query) {
$query->where('text', 'great');
})->get();
foreach ($articles as $article) {
echo $article->title;
}
?>
Результат выполнения кода:
["article 1", "article 3"]
Пример
Давайте получим пользователей, у которых есть посты, созданные после определённой даты:
<?php
use AppModelsUser;
$users = User::withWhereHas('posts', function ($query) {
$query->where('created_at', '>', '2025-01-01');
})->get();
foreach ($users as $user) {
echo $user->name;
}
?>
Результат выполнения кода:
["user 1", "user 4"]
Пример
Давайте загрузим категории с продуктами, цена которых больше 1000:
<?php
use AppModelsCategory;
$categories = Category::withWhereHas('products', function ($query) {
$query->where('price', '>', 1000);
})->get();
foreach ($categories as $category) {
echo $category->name;
}
?>
Результат выполнения кода:
["category 2", "category 5"]
Пример
Давайте используем метод с несколькими условиями в замыкании:
<?php
use AppModelsOrder;
$orders = Order::withWhereHas('items', function ($query) {
$query->where('quantity', '>', 5)
->where('status', 'active');
})->get();
foreach ($orders as $order) {
echo $order->number;
}
?>
Результат выполнения кода:
["order 3", "order 7"]
Пример
Давайте сравним работу withWhereHas
и обычного whereHas:
<?php
use AppModelsArticle;
// withWhereHas - загружает связи
$articles1 = Article::withWhereHas('comments', function ($query) {
$query->where('text', 'great');
})->get();
// whereHas - не загружает связи
$articles2 = Article::whereHas('comments', function ($query) {
$query->where('text', 'great');
})->get();
// для второй выборки нужно дополнительно загружать связи
$articles2->load('comments');
?>
Результат выполнения кода:
["article 1", "article 3", "article 1", "article 3"]