Создание валидации, которой можно гордиться, в Laravel

Сегодня я хотел бы затронуть тему валидации в бэкенде с помощью Laravel. Для меня это часть того, что делает этот фреймворк таким элегантным и беглым. Несмотря на то, что он позволяет вам проверять ваши входные данные, используя несколько подходов, он дает вам защитные рельсы, чтобы гарантировать, что это будет работать хорошо и останется организованным по мере роста вашего приложения.

Давайте перейдем к коду. Я создал начальный проект, который вы можете использовать, чтобы следовать за ним. Просто клонируйте репозиторий отсюда. Это простой CRUD-проект с Rest API для показа, хранения, обновления и удаления наблюдений за птицами из приложения. В настоящее время в нем нет никакой валидации. Все, что он получает от клиентов, он будет пытаться сохранить или обновить в базе данных, что может быть очень плохо, даже если у вас есть валидация в клиентском коде. Давайте начнем исправлять это с помощью Form Requests.

Запросы форм

Честно говоря, если у вас есть только пара правил, вам может не понадобиться запрос формы, вы можете просто проверить запрос внутри метода контроллера, например:

// app/Http/Controllers/BurdSightingController.php

public function create(Request $request)
{
    $request->validate([
        'common_name' => 'required|string|max:255',
    ]);

    $sighting = BirdSighting::create($request->validated());
    return response()->json($sighting, 201);
}

Войти в полноэкранный режим Выйти из полноэкранного режима

Но если вам нужен более чистый интерфейс с контроллером и специальное место, где происходит валидация, то вы можете создать FormRequest с помощью команды artisan:

php artisan make:request CreateBirdSightingRequest

Войти в полноэкранный режим Выйти из полноэкранного режима

Это создаст следующий файл:

// app/Http/Requests/CreateBirdSightingRequest.php

class CreateBirdSightingRequest extends FormRequest
{
    public function authorize()
    {
        return false;
    }

    public function rules()
    {
        return [
            //
        ];
    }
}

Войти в полноэкранный режим Выйти из полноэкранного режима

Метод authorize может быть использован для определения того, имеет ли текущий пользователь право на выполнение данной операции, поэтому вы можете, например, использовать Врата и Политики или даже более простые правила, например, если у пользователя есть определенное свойство. Убедитесь, что этот метод возвращает булево значение: true означает, что пользователь авторизован, а false означает, что пользователь не авторизован и ответит HTTP-статусом 403.

Метод rules — это место, где находятся фактические правила валидации. В Laravel есть десятки встроенных правил валидации, которые можно добавить сюда. Итак, в нашем случае мы хотим проверить поля, чтобы создать наблюдение за птицами:

    public function rules()
    {
        return [
            'common_name' => 'required|string|max:255',
            'species' => 'required|string|max:255',
            'sighted_at' => 'required|date',
            'quantity' => 'nullable|integer|min:1',
            'latitude' => 'required|numeric',
                        'longitude' => ['required', 'numeric'],
        ];
    }

Войти в полноэкранный режим Выйти из полноэкранного режима

Вы заметите, что для longitude я использовал другой синтаксис. Laravel поддерживает как строки с правилами, разделенными |, так и массивы с правилами, разделенными запятыми. Насколько я знаю, строковый синтаксис можно использовать только со встроенными правилами. Если вы создаете пользовательское правило валидации (и я покажу вам, как это сделать), то вам придется использовать синтаксис массива.

Пользовательские сообщения валидации

Form Requests также позволяет вам добавлять пользовательские сообщения валидации для каждого поля и правила. Для этого вам нужно переопределить метод messages в созданном вами запросе формы, например:

    public function messages()
    {
        return [
            'common_name.required' => 'A common name for the bird you saw is required',
            'sighted_at.required' => 'An approximate date and time for the sighting is required',
        ];
    }

Войти в полноэкранный режим Выйти из полноэкранного режима

Эти сообщения переопределят стандартное сообщение валидации для правила required, которое вы можете найти в resources/lang/validation.php.

Наконец, вы должны использовать этот запрос формы в своем методе, поэтому вернитесь в контроллер и замените Request $request на CreateBirdSightingRequest $request.

    public function create(CreateBirdSightingRequest $request)
    {
        $sighting = BirdSighting::create($request->validated());
        return response()->json($sighting, 201);
    }

Вход в полноэкранный режим Выйти из полноэкранного режима

Вы также заметите, что мы заменили $request->all() на $request->validated() для получения подтвержденных полей из запроса.

Теперь, если вы отправите данные в эту конечную точку, и они не будут соответствовать правилам, которые вы добавили, вы получите ответ со статусом 422 HTTP с сообщениями об ошибках для каждого поля.

Организация правил

Теперь вам понадобится другой запрос формы для метода update, который может иметь другой набор правил, и, говоря о наборе правил, когда приложение начинает расти и правила начинают слишком «разбрасываться» в запросе формы, мы можем создать классы правил, которые сделают эти наборы многократно используемыми и более понятными. Мне нравится создавать каталог Rules внутри app/ и создавать класс, который будет предоставлять нужные мне правила:

// app/BirdSightingRules.php

class BirdSightingRules
{
    public static function birdRules()
    {
        return [
            'common_name' => 'required|string|max:255',
            'species' => 'required|string|max:255',
            'quantity' => 'nullable|integer|min:1',
        ];
    }

    public static function locationRules()
    {
        return [
            'sighted_at' => 'required|date',
            'latitude' => 'required|numeric',
            'longitude' => ['required', 'numeric'],
        ];
    }

    public static function updateRules()
    {
        return [
            // 
        ];
    }
}

Войти в полноэкранный режим Выйти из полноэкранного режима

Затем вернемся к запросу формы:

    public function rules()
    {
        return array_merge(
            BirdSightingRules::birdRules(),
            BirdSightingRules::locationRules()
        );
    }

Войти в полноэкранный режим Выйти из полноэкранного режима

Пользовательские правила

В Laravel так много встроенных правил, что вам может понадобиться некоторое время, чтобы создать пользовательское правило, но иногда ваше приложение может иметь специфическую особенность, которая требует пользовательского правила валидации. В этом случае artisan поможет вам:

php artisan make:rule SightedInMarch

Вход в полноэкранный режим Выйти из полноэкранного режима

Будет создан файл в каталоге app/Rules, который содержит пользовательское правило со следующими методами:

// app/Rules/SightedInMarch.php

class SightedInMarch implements Rule
{
    public function passes($attribute, $value)
    {
        //
    }

    public function message()
    {
        return 'The validation error message.';
    }
}

Войти в полноэкранный режим Выйти из полноэкранного режима

Внутри метода passes вы можете создать свое пользовательское правило, которое должно возвращать булево значение, а внутри message вам просто нужно вернуть строку с объяснением того, почему оно не прошло проверку:

    public function passes($attribute, $value)
    {
        return preg_match('/^[0-9]{4}-03-[0-9]{2}/', $value);
    }

    public function message()
    {
        return 'Why are you watching birds in March?';
    }

Войти в полноэкранный режим Выход из полноэкранного режима

Затем вернитесь к набору правил и используйте это пользовательское правило с атрибутом sighted_at:

// app/Rules/BirdSightingRules.php

    public static function locationRules()
    {
        return [
            'sighted_at' => ['required', 'date', new SightedInMarch],
            'latitude' => 'required|numeric',
            'longitude' => ['required', 'numeric'],
        ];
    }

Войти в полноэкранный режим Выйти из полноэкранного режима

Теперь все запросы формы, использующие locationRules, будут автоматически проверять атрибут sighted_at, используя это новое правило. На этом мы завершаем очередную статью. До встречи в следующей!

Оцените статью
Procodings.ru
Добавить комментарий