Студия разработки сайтов и приложений

Netspark.ru

Скрипт для типографики

Typofilter.js

Макрос getOrFail в Laravel

В Ларавеле есть удобный хелпер-метод: firstOrFail(), позволяющий получить по заданному запросу из БД первую найденную модель, либо вывалиться в 404, если моделей не найдено. Удобство в том, что использование хелпера позволяет избавиться от необходимости отдельно проверять наличие результата.

$page = ContentPage::where('slug', $slug)->firstOrFail();

вместо

$page = ContentPage::where('slug', $slug)->take(1)->get();

if ($page->isEmpty()) abort(404);

Очевидно, первый вариант лаконичнее и читабельнее.

Так вот, хотелось бы, чтобы то же самое можно было делать, когда мы хотим загрузить несколько моделей, или уйти в 404, если не нашли ни одной. То есть чтобы был хелпер-метод getOrFail(), который делает то же, что и firstOrFail, но возвращает несколько моделей.

Для этого можно написать макрос. В Laravel есть такой трейт, Macroable, и классы, которые его используют, можно расширять своими макро-методами. Расширим класс Illuminate\Database\Eloquent\Builder. Добавим в AppServiceProvider:

public function boot(): void
{
    // ...

    Builder::macro('getOrFail', function () {
        return tap(
            $this->get(), 
            fn ($results) => abort_unless($results->count(), 404)
        );
    });
}

теперь мы можем писать, например, так:

$contentPages = ContentPage::where('slug', $slug)->getOrFail();

и получим либо коллекцию моделей ContentPage, либо ошибку 404, без необходимости отдельно проверять, что коллекция не пустая.

P.S. Да, slug в данном примере не уникальный, может быть несколько моделей с одинаковым slug. Вместо этого у меня есть уникальный ключ ['slug', 'language'].

Обсуждение

Чтобы обсудить заметку, написать комментарий, или просто связаться, заходите в Телеграм-канал. У нас весело и всем рады!

Также меня можно найти в Хвиттере, VC.ru, Дзене, или Тенчате.