laravel-when-conditional-queries-tip.png
Шаблон кодуLaravel

Laravel when(): умовні запити без зайвих if

Як використовувати when() для умовних фільтрів, передавати значення в callback, додавати else через третій аргумент і не потрапляти в пастку з falsy значеннями.

when() дає змогу залишити optional filters усередині одного query chain замість того, щоб розривати побудову запиту окремими if.

Але його користь не закінчується простою заміною if. Callback може отримати саме значення умови, третій аргумент працює як else, а falsy значення на кшталт 0 потребують окремої уваги.

Базове використання when()

До
php
$query = User::query(); if ($status) {    $query->where('status', $status);} $users = $query->get();
Після
php
$users = User::query()    ->when(        $status,        fn ($query, $status) =>            $query->where('status', $status),    )    ->get();

У callback Laravel передає не тільки builder. Другим параметром callback можна отримати значення, передане першим аргументом у when(). Завдяки цьому не потрібен окремий use ($status).

PHP - Значення умови доступне в callback
User::query()    ->when(        $status,        fn ($query, $status) =>            $query->where('status', $status),    );

Третій аргумент when() - це else

Повна форма when($value, $callback, $default) має другий callback. Він виконується, коли перший аргумент має falsy значення. Це дозволяє виразити if / else без виходу з fluent chain.

PHP - when() з default callback
User::query()    ->when(        $sortByVotes,        fn ($query) => $query->orderBy('votes'),        fn ($query) => $query->orderBy('name'),    )    ->get();

Пастка: 0 та інші falsy значення

До
php
Product::query()    ->when(        $minPrice,        fn ($query, $minPrice) =>            $query->where('price', '>=', $minPrice),    );
Після
php
Product::query()    ->when(        $minPrice !== null,        fn ($query) =>            $query->where('price', '>=', $minPrice),    );
when() перевіряє truthiness першого аргументу. Якщо 0 є валідним значенням фільтра, передавайте явну boolean-умову на кшталт $minPrice !== null.

when() не обмежується where()

PHP - Кілька незалежних optional filters в одному chain
Product::query()    ->when(        $categoryId,        fn ($query, $categoryId) =>            $query->where('category_id', $categoryId),    )    ->when(        $onlyAvailable,        fn ($query) =>            $query->where('stock', '>', 0),    )    ->when(        $sortByPrice,        fn ($query) =>            $query->orderBy('price'),    )

when() зручний там, де умова модифікує той самий builder: можна умовно додавати where(), orderBy(), joins, selects та інші частини запиту.

Не потрібно замінювати ним кожен if. Якщо окрема умова читається простіше поза chain, звичайний if залишається нормальним рішенням. Для зворотної умови в Laravel також є unless().

#when #query-builder #eloquent #conditional-queries #laravel-12 #laravel-13 #php-8-4 #php-8-5

Схожі поради

laravel-withwherehas-avoid-duplicate-conditions-tip.pngПорада
Переглянути пораду
#eloquent #laravel-12 #laravel-13 #php-8-4 #php-8-5 #where-has #with-where-has #eager-loading #relationships
laravel-tap-side-effects-keep-original-value-tip.pngПорада
Переглянути пораду
#eloquent #laravel-12 #laravel-13 #php-8-4 #php-8-5 #tap #helpers #tappable
laravel-firstorcreate-replace-first-create-tip.pngПорада
Переглянути пораду
#eloquent #laravel-12 #laravel-13 #php-8-4 #php-8-5 #model-persistence #first-or-create #first-or-new
laravel-updateorcreate-replace-first-if-tip.pngПорада
Переглянути пораду
#eloquent #laravel-12 #laravel-13 #php-8-4 #php-8-5 #update-or-create #model-persistence #upsert