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

19.09.2020

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

Laravel предоставляет несколько способов для валидации входящих данных. По умолчанию базовый контроллер использует трейт ValidatesRequests, который обеспечивает удобный способ валидации HTTP-запросов c большим количеством правил валидации.

Простая валидация в контроллере

Давайте рассмотрим простой пример валидации формы и вывод сообщений об ошибках для пользователя.

  1. Определение роутов
  2. Создание контроллера
  3. Правила валидации
  4. Отображение ошибок

1. Определение роутов

Во-первых, представим что мы имеем следующие роуты в файле routes/web.php:

Route::get('post/create', 'PostController@create');
Route::post('post', 'PostController@store');

Маршрут GET отображает форму для создания нового поста в блоге, в то время как POST будет сохранять новую запись в базе данных.

2. Создание контроллера

Во-вторых, создадим простой контроллер, который обрабатывает эти роуты. Реализуем метод create(), а метод store() пока оставим пустым.

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class PostController extends Controller {
    /**
     * Показать форму для создания новой записи блога
     *
     * @return Response
     */
    public function create() {
        return view('post.create');
    }

    /**
     * Сохранить в базу данных новую запись блога
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request) {
        // .....
    }
}

3. Правила валидации

Если посмотреть исходный код базового контроллера (App\Http\Controllers\Controller), то можно увидеть, что он включает в себя трейт ValidatesRequests, который обеспечивает все контроллеры методом validate(). Метод принимает два параметра — экземпляр HTTP-запроса и правила валидации.

Если все правила валидации пройдены успешно — код выполняется дальше. Иначе будет выброшено исключение и сообщение об ошибке будет отправлено обратно пользователю. Ответ будет направлен обратно с заполненными flash-переменными, а на AJAX-запрос будет отправлен JSON.

/**
 * Сохранить в базу данных новую запись блога
 *
 * @param  Request  $request
 * @return Response
 */
public function store(Request $request) {
    $this->validate($request, [
        'title' => 'required|unique:posts|max:100',
        'body' => 'required',
    ]);
    // проверка пройдена, можно записывать в БД
}

Чтобы остановить выполнение остальных правил после первой неудачной проверки, нужно добавить bail в начало списка всех правил:

$this->validate($request, [
    'title' => 'bail|required|unique:posts|max:100',
    'body' => 'required',
]);

Если правило unique для атрибута title не выполняется, правило max не проверяется.

Если данные HTTP-запроса содержат вложенные параметры, можно указать их, используя синтаксис с точкой:

$this->validate($request, [
    'title' => 'required|unique:posts|max:100',
    'author.name' => 'required',
    'body' => 'required',
]);

Начиная с версии Laravel 5.5 можно для валидации данных использовать метод validate() объекта Illuminate\Http\Request:

/**
 * Сохранить в базу данных новую запись блога
 *
 * @param  Request  $request
 * @return Response
 */
public function store(Request $request) {
    $request->validate([
        'title' => 'required|unique:posts|max:100',
        'body' => 'required',
    ]);
    // проверка пройдена, можно записывать в БД
}

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

Мы уже знаем, что в случае ошибок пользователь будет перенаправлен на предыдущую страницу. Кроме того, все ошибки валидации будут автоматически записаны во flash-переменные. Нам не нужно явно передавать сообщения об ошибках в шаблоне роута GET. Потому что Laravel будет проверять наличие ошибок в текущем сеансе и автоматически привязывать их к шаблону, если они доступны.

В нашем случае пользователь будет перенаправлен в метод create() контроллера и можно отобразить сообщения об ошибках в шаблоне:

<!-- 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

С помощью директивы @error можно быстро проверить, существуют ли сообщения об ошибках для данного атрибута. Внутри директивы @error можно использовать переменную $message, чтобы показать текст ошибки.

<input type="text" name="title" class="@error('title') is-invalid @enderror">

@error('title')
    <div class="alert alert-danger">{{ $message }}</div>
@enderror

По умолчанию в Laravel включены глобальные посредники TrimStrings и ConvertEmptyStringsToNull. Они перечислены в свойстве $middleware класса App\Http\Kernel. Из-за этого нужно часто помечать дополнительные поля как nullable, если не нужно, чтобы валидатор считал не действительным значение null.

$this->validate($request, [
    'title' => 'required|unique:posts|max:100',
    'body' => 'required',
    'publish_at' => 'nullable|date',
]);

В этом примере мы указываем что поле publish_at может быть null или должно содержать дату. Если модификатор nullable отсутствует, значение null будет считаться недопустимым.

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

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

Каталог оборудования
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.