Множественные WHERE в Laravel Eloquent: от новичка до профи

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Как создавать запросы с множественными условиями WHERE в Laravel Eloquent

Вы когда-нибудь ловили себя на мысли: «Мне нужно отфильтровать записи по трём разным условиям, но синтаксис Eloquent какой-то запутанный»? Если да — вы не одиноки. Вопрос "How to Create Multiple Where Clause Query Using Laravel Eloquent?" на Stack Overflow собрал тысячи просмотров, и это неудивительно. Работа с базой данных — сердце любого PHP-приложения, а умение строить сложные запросы отличает новичка от профессионала.

В этой статье мы разберём все способы создания множественных WHERE-условий в Laravel Eloquent: от простейших цепочек до вложенных логических конструкций. Вы узнаете, как комбинировать AND и OR, использовать whereHas для связанных моделей и избегать типичных ошибок. Поехали!

Базовый синтаксис: цепочка WHERE

Самый очевидный способ добавить несколько условий — просто вызвать where() несколько раз подряд. По умолчанию все условия соединяются через AND.

// Получить всех пользователей, у которых status = 'active' И role = 'admin'
$users = User::where('status', 'active')
             ->where('role', 'admin')
             ->get();

// Эквивалентный SQL:
// SELECT * FROM users WHERE status = 'active' AND role = 'admin'

Можно передать массив условий:

$users = User::where([
    ['status', '=', 'active'],
    ['role', '=', 'admin'],
])->get();

Оба варианта рабочие, но первый читается легче, особенно когда условий становится много.

Условие OR: когда нужно «или»

А что если нам нужно найти пользователей, которые ИЛИ активны, ИЛИ являются администраторами? Тут в игру вступает orWhere().

// Пользователи, у которых status = 'active' ИЛИ role = 'admin'
$users = User::where('status', 'active')
             ->orWhere('role', 'admin')
             ->get();

// SQL: SELECT * FROM users WHERE status = 'active' OR role = 'admin'

⚠️ Важное предостережение: Если вы смешиваете where и orWhere, помните о приоритете операторов. Laravel обрабатывает их последовательно, поэтому результат может отличаться от ожидаемого.

Пример с подводным камнем

// Хотим: (status = 'active' AND role = 'admin') OR (plan = 'premium')
$users = User::where('status', 'active')
             ->where('role', 'admin')
             ->orWhere('plan', 'premium')
             ->get();

// SQL: WHERE status = 'active' AND role = 'admin' OR plan = 'premium'
// Это НЕ то же самое!

Чтобы получить правильный результат, используйте группировку с замыканием:

$users = User::where(function ($query) {
    $query->where('status', 'active')
          ->where('role', 'admin');
})->orWhere('plan', 'premium')
  ->get();

// SQL: WHERE (status = 'active' AND role = 'admin') OR plan = 'premium'

Вложенные WHERE: группировка условий

Когда логика становится сложнее, на помощь приходят вложенные замыкания. Это самый мощный инструмент для создания сложных условий.

// (age > 18 AND status = 'active') OR (age <= 18 AND parent_approved = 1)
$users = User::where(function ($query) {
    $query->where('age', '>', 18)
          ->where('status', 'active');
})->orWhere(function ($query) {
    $query->where('age', '<=', 18)
          ->where('parent_approved', 1);
})->get();

Код читается как книга: «найди пользователей, которые совершеннолетние и активные, ИЛИ несовершеннолетние с одобрением родителей».

Условия с операторами: WHERE IN, BETWEEN, NULL

Eloquent поддерживает все стандартные SQL-операторы. Вот несколько полезных:

whereIn — проверка вхождения в список

$users = User::whereIn('role', ['admin', 'editor', 'moderator'])->get();
// SQL: WHERE role IN ('admin', 'editor', 'moderator')

whereBetween — диапазон значений

$users = User::whereBetween('age', [18, 65])->get();
// SQL: WHERE age BETWEEN 18 AND 65

whereNull / whereNotNull — проверка на NULL

$users = User::whereNull('email_verified_at')->get();
// Все пользователи, не подтвердившие email

Работа со связями: whereHas и whereDoesntHave

Одна из сильнейших сторон Eloquent — фильтрация по связанным моделям. Допустим, у нас есть модель Post, которая belongsTo User. Как найти всех пользователей, у которых есть посты с определённым тегом?

$users = User::whereHas('posts', function ($query) {
    $query->where('tags', 'like', '%laravel%')
          ->where('published', true);
})->get();

А если нужно найти пользователей без постов?

$users = User::whereDoesntHave('posts')->get();

Методы orWhereHas и whereHas отлично комбинируются с обычными условиями:

$users = User::where('status', 'active')
             ->whereHas('posts', function ($q) {
                 $q->where('views', '>', 1000);
             })
             ->orWhereHas('comments', function ($q) {
                 $q->where('created_at', '>', now()->subDay());
             })
             ->get();

Динамические WHERE: whereColumn и whereDate

Иногда нужно сравнить два столбца между собой:

// Найти пользователей, у которых дата создания равна дате обновления
$users = User::whereColumn('created_at', 'updated_at')->get();

// Или с оператором:
$users = User::whereColumn('updated_at', '>', 'created_at')->get();

Для работы с датами есть удобный whereDate:

// Все пользователи, зарегистрированные сегодня
$users = User::whereDate('created_at', today())->get();

// За последнюю неделю
$users = User::whereDate('created_at', '>=', now()->subWeek())->get();

Практический пример: фильтр товаров в интернет-магазине

Давайте соберём всё вместе. Представьте, что вы разрабатываете каталог товаров с фильтрами:

  • Категория — обязательный параметр
  • Цена — от и до (необязательно)
  • Бренды —

Блоги

Рекомендаций по книгам