Laravel. Валидация данных. Часть вторая из трех

20.09.2020

Теги: LaravelWeb-разработкаТеорияФормаФреймворкШаблонСайта

Валидация в отдельном классе

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

1. Создание класса валидатора

Создать такой класс можно с помощью artisan-команды:

> cd D:/work/localhost25/www
> php artisan make:request PostRequest

В результате будет создан файл app/Http/Requests/PostRequest.php, который будет проверять данные формы при создании нового поста блога.

<?php
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class PostRequest extends FormRequest {
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize() {
        return false;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules() {
        return [
            'title' => 'required|unique:posts|min:3|max:100',
            'excerpt' => 'required|min:100|max:200',
            'body' => 'required',
        ];
    }
}

Далее изменяем метод store() контроллера PostController, указывая тип параметра $request как PostRequest вместо Request.

<?php
namespace App\Http\Controllers;

use App\Post;
use Illuminate\Http\Request;
use App\Http\Requests\PostRequest;

class PostController extends Controller {
    /* ... */
    public function store(PostRequest $request) {
        $post = new Post();
        $post->title = $request->input('title');
        $post->excerpt = $request->input('excerpt');
        $post->body = $request->input('body');
        $post->save();
        return redirect()
            ->route('post.index')
            ->with('success', 'Новый пост успешно создан');
    }
    /* ... */
}

Входящий запрос перед вызовом метода контроллера store() будет проверяться на соответствие заданным правилам автоматически, что позволит не загромождать контроллер логикой валидации. Если проверка не пройдена, то при традиционном запросе ошибки записываются в сессию и будут доступны в шаблонах. Если был AJAX-запрос, пользователю будет возвращен HTTP-ответ с кодом 422, включая JSON с ошибками.

2. Доработка класса валидатора

Мы создали проверку данных при добавлении нового поста блога, но нужна еще проверка при редактировании существующего поста. Чтобы не создавать новый класс валидации — можно поступить так, как показано ниже.

<?php
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class PostRequest extends FormRequest {
    /**
     * Возвращает массив правил для проверки полей формы
     *
     * @return array
     */
    public function rules() {
        switch ($this->method()) {
            case 'POST': {
                return [
                    'title' => 'required|unique:posts|min:3|max:100',
                    'excerpt' => 'required|min:100|max:200',
                    'body' => 'required',
                ];
            }
            case 'PATCH': {
                return [
                    'id' => 'required|exists:posts,id',
                    'title' => 'required|min:3|max:100',
                    'excerpt' => 'required|min:100|max:200',
                    'body' => 'required'
                ];
            }
        }
    }
    /* ... */
}

3. Проверка прав в валидаторе

Класс FormRequest содержит в себе метод authorize(). В этом методе можно проверить, имеет ли аутентифицированный пользователь права на выполнение данного запроса. Например, можно проверить, есть ли у пользователя право для добавления комментариев в блог:

<?php
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class PostRequest extends FormRequest {
    /**
     * Определить, есть ли права у этого пользователя на этот запрос
     *
     * @return bool
     */
    public function authorize() {
        $comment = Comment::find($this->route('comment'));
        return $comment && $this->user()->can('update', $comment);
    }
    /* ... */
}

Так как FormRequest расширяет базовый класс Request, мы можем использовать метод user(), чтобы получить доступ к текущему пользователю.Так же обратите внимание на вызов метода route() — он предоставляет доступ к параметрам URI, определенным в роуте (в приведенном ниже примере это {comment}):

Route::post('comment/{comment}');

Если метод authorize() возвращает false, автоматически генерируется ответ с кодом 403 и метод контроллера не выполняется. Если логика авторизации организована в другом месте приложения, нужно просто вернуть true из метода authorize():

public function authorize() {
    return true;
}

4. Текст сообщений об ошибках

Метод messages() позволяет кастомизировать сообщения об ошибках. И должен возвращать массив атрибутов/правил и соответствующих им сообщений об ошибках:

<?php
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class PostRequest extends FormRequest {
    /**
     * Возвращает массив правил для проверки полей формы
     *
     * @return array
     */
    public function rules() {
        return [
            'title' => 'required|unique:posts|min:3|max:100',
            'excerpt' => 'required|min:100|max:200',
            'body' => 'required',
        ];
    }
    /**
     * Возвращает массив сообщений об ошибках для заданных правил
     *
     * @return array
     */
    public function messages() {
        return [
            'title.required' => 'Поле «Заголовок» обязательно для заполнения',
            'title.unique' => 'Такой заголовок уже существует, придумайте другой',
            'title.min' => 'Поле «Заголовок» должно быть не меньше :min символов',
            'title.max' => 'Поле «Заголовок» должно быть не больше :max символов',
            'excerpt.required'  => 'Поле «Анонс поста» обязательно для заполнения',
            'excerpt.min' => 'Поле «Анонс поста» должно быть не меньше :min символов',
            'excerpt.max' => 'Поле «Анонс поста» должно быть не больше :max символов',
            'body.required'  => 'Поле «Текст поста» обязательно для заполнения',
        ];
    }
    /* ... */
}
<?php
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class PostRequest extends FormRequest {
    /**
     * Возвращает массив правил для проверки полей формы
     *
     * @return array
     */
    public function rules() {
        return [
            'title' => 'required|unique:posts|min:3|max:100',
            'excerpt' => 'required|min:100|max:200',
            'body' => 'required',
        ];
    }
    /**
     * Возвращает массив сообщений об ошибках для заданных правил
     *
     * @return array
     */
    public function messages() {
        return [
            'required' => 'Поле «:attribute» обязательно для заполнения',
            'unique' => 'Такое значение поля «:attribute» уже используется',
            'min' => 'Поле «:attribute» должно быть не меньше :min символов',
            'max' => 'Поле «:attribute» должно быть не больше :max символов',
        ];
    }
    /**
     * Возвращает массив дружественных пользователю названий полей
     *
     * @return array
     */
    public function attributes() {
        return [
            'title' => 'Заголовок',
            'excerpt' => 'Анонс поста',
            'body' => 'Текст поста'
        ];
    }
}

5. Отображение ошибок

В случае ошибок пользователь будет перенаправлен на предыдущую страницу, а все ошибки валидации будут автоматически записаны во flash-переменные.

<!-- resources/views/post/create.blade.php -->

<h1>Создать пост</h1>

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
        @foreach ($errors->all() as $error)
            <li>{{ $error }}</li>
        @endforeach
        </ul>
    </div>
@endif

Дополнительно

Поиск: Laravel • Web-разработка • Теория • Форма • Фреймворк • Шаблон сайта • Валидация

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.