Валидация форм в классе
Для сложных случаев валидации, лучше создать отдельный класс, который будет проверять данные формы.
Создать такой класс можно с помощью artisan-команды:
php artisan make:request PostRequest
В результате будет создан файл app/Http/Requests/PostRequest.php
, который будет проверять данные формы при создании нового поста блога:
app/Http/Requests/PostRequest.php<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class PostRequest extends FormRequest {
// Определение, авторизован ли пользователь для выполнения этого запроса @return bool
public function authorize() {
return false;
}
// Получите правила проверки, которые применяются к запросу @return array
public function rules() {
return [
//
];
}
}
Далее изменяем метод store()
контроллера PostController
, указывая тип параметра $request
как PostRequest
вместо Request
:
app/Http/Controllers/PostController.php<?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 с ошибками.
Класс FormRequest
содержит в себе метод authorize()
. В этом методе можно проверить, имеет ли аутентифицированный пользователь права на выполнение данного запроса. Например, можно проверить, есть ли у пользователя право для добавления комментариев в блог:
app/Http/Requests/PostRequest.php<?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);
}
// Получите правила проверки, которые применяются к запросу @return array
public function rules() {
return [
//
];
}
}
Так как FormRequest
расширяет базовый класс Request
, мы можем использовать метод user()
, чтобы получить доступ к текущему пользователю.Так же обратите внимание на вызов метода route()
— он предоставляет доступ к параметрам URI, определенным в роуте (в приведенном ниже примере это {comment}
).
Если метод authorize()
возвращает false
, автоматически генерируется ответ с кодом 403 и метод контроллера не выполняется. Если логика авторизации организована в другом месте приложения, нужно просто вернуть true
из метода authorize()
:
public function authorize() {
return true;
}
Правила валидации задаются в методе rules()
:
app/Http/Requests/PostRequest.php<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class PostRequest extends FormRequest {
// Определение, авторизован ли пользователь для выполнения этого запроса @return bool
public function authorize() {
return true;
}
// Получите правила проверки, которые применяются к запросу @return array
public function rules() {
return [
'title' => 'required|unique:posts|min:3|max:100',
'excerpt' => 'required|min:100|max:200',
'body' => 'required',
];
}
}
Метод messages()
позволяет кастомизировать сообщения об ошибках. И должен возвращать массив атрибутов/правил и соответствующих им сообщений об ошибках:
app/Http/Requests/PostRequest.php<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class PostRequest extends FormRequest {
// Определение, авторизован ли пользователь для выполнения этого запроса @return bool
public function authorize() {
return true;
}
// Возвращает массив правил для проверки полей формы @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' => 'Поле «Текст поста» обязательно для заполнения',
];
}
}
app/Http/Requests/PostRequest.php<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class PostRequest extends FormRequest {
// Определение, авторизован ли пользователь для выполнения этого запроса @return bool
public function authorize() {
return true;
}
// Возвращает массив правил для проверки полей формы @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' => 'Текст поста'
];
}
}
В случае ошибок пользователь будет перенаправлен на предыдущую страницу, а все ошибки валидации будут автоматически записаны во 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
С помощью директивы @error
можно быстро проверить, существуют ли сообщения об ошибках для данного атрибута. Внутри директивы @error
можно использовать переменную $message
, чтобы показать текст ошибки:
resources/views/post/create.blade.php<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
. В примере мы указываем что поле publish_at
может быть null
или должно содержать дату. Если модификатор nullable
отсутствует, значение null
будет считаться недопустимым:
$this->validate($request, [
'title' => 'required|unique:posts|max:100',
'body' => 'required',
'publish_at' => 'nullable|date',
]);