В этой статье мы расскажем, как можно проверить входящие данные через Контроллеры, Запросы формы (FormRequest) и Правила.
Контроллеры
По умолчанию все контроллеры, расширяющие базовый контроллер, наследуют трейт ValidatesRequests. Он даёт возможность использовать метод validate в ваших контроллерах.
Например, предположим, что пользователь (User) создаёт статью (Article). Возможно, он вводит Название (name) и какой-то Текст (body) для этой статьи, и у статьи есть дата публикации (publish_at). Тогда валидация в контроллере может выглядеть так:
public function store(Request $request) {
$this->validate($request, [
'name' => 'required|string',
'body' => 'required|string',
'publish_at' => 'required|date_format:Y-m-d H:i:s'
]);
// Данные валидны и будет запущен следующий код
...
}
public function store(Request $request) {
// Примечание: также доступен синтаксис массива
$request->validate([
'name' => ['required', 'string'],
'body' => ['required', 'string'],
'publish_at' => ['required', 'date_format:Y-m-d H:i:s'],
]);
// Данные валидны и будет запущен следующий код
...
}
public function store() {
request()->validate([
// Правила валидации...
]);
// Данные валидны и будет запущен следующий код
...
}
public function store() {
$this->validate(request(), [
// Правила валидации...
]);
// Данные валидны и будет запущен следующий код
...
}
Следует также отметить, что в ответе метод validate будут проверенные данные:
public function store(Request $request) {
$validatedData = $request->validate([
'name' => ['required', 'string'],
'body' => ['required', 'string'],
'publish_at' => ['required', 'date_format:Y-m-d H:i:s'],
]);
// Я знаю, что ключами в проверенных данных будет только те, что были проверенны успешно, например: name, body, published_at
$this->articleService->store($validatedData);
}
Или вы можете сделать так:
public function store(Request $request) {
$request->validate([
'name' => ['required', 'string'],
'body' => ['required', 'string'],
'publish_at' => ['required', 'date_format:Y-m-d H:i:s'],
]);
// Я знаю, что ключами в проверенных данных будет только те, что были проверенны успешно, например: name, body, published_at
$this->articleService->store($request->only('name', 'body', 'published_at'));
}
Список доступных правил валидации можно найти здесь.
Запросы форм
Если вы хотите извлечь всю валидационную логику из контроллеров, или же одновременно выполнять и авторизацию и валидацию, то Laravel предоставляет вам класс Запроса формы (Form Request).
Вы можете создать класс Запроса формы, используя один из множества встроенных генераторов:
php artisan make:request StoreArticleRequest
Эта команда создаст следующий класс в app/Http/Requests:
class StoreArticleRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
//
];
}
}
Класс идёт с двумя методами: authorize and rules.
Authorize
Этот метод позволяет предотвратить запуск кода, если возвращает false. Laravel выбросит ошибку 401.
Пример использования:
public function authorize()
{
return $this->user()->can('create articles');
}
Rules
Этот метод возвращает массив с правилами, которые мы использовали ранее в контроллере
public function rules()
{
return [
'name' => ['required', 'string'],
'body' => ['required', 'string'],
'publish_at' => ['required', 'date_format:Y-m-d H:i:s'],
];
}
Примечание: Вы можете тапйхинтить в этот метод любые необходимые вам зависимости.
Итак, как же использовать этот класс? Тайпхинтим его прямо в метод контроллера:
public function store(StoreArticleRequest $request) {
// Валидация успешно пройдена
}
Если валидация не пройдет, то пользователя редиректнет обратно с ошибками, записанными в сессию. Если это был AJAX-запрос, то выдаст ошибку 422 Unprocessable Entity.
Вы можете получить проверенные данные, также как и раньше:
public function store(StoreArticleRequest $request) {
$validatedData = $request->validated();
// Добавление в базу данных
...
}
Классы кастомных Правил
Если вам не хватает встроенных правил валидации, то вы можете создать своё собственное. Используем одну из команд make:
php artisan make:rule IsValidStateInUSA
Он создаст следующий класс в app/Rules:
class IsValidStateInUSA implements Rule
{
public function passes($attribute, $value)
{
//
}
public function message()
{
return 'Сообщение об ошибке валидации.';
}
}
В методе pass находится логика, позволяющая использовать эту проверку. Метод message содержит сообщение, показываемое в случае неудачной проверки.
В нашей проверке IsValidStateInUSA (Это код существующего штата США?), нам нужно, чтобы передаваемый элемент был одним из 50 имеющихся кодов:
class IsValidStateInUSA implements Rule
{
public function passes($attribute, $value)
{
return in_array(strtoupper($value), [
'AL',
'AK',
'AZ',
...
]);
}
public function message()
{
return 'Несуществующий код штата США.';
}
}
Чтобы использовать это правило в контроллере или запросе формы — просто добавляете его вот так:
public function store(Request $request) {
$request->validate([
'state' => ['required', new IsValidStateInUSA],
]);
...
}
Обработка ошибок валидации
Если проверка не пройдена, Laravel автоматически редиректит пользователя обратно, с переменной $errors в сессии.
Создайте файл messages.blade.php и подключите его в свой основной макета:
@if($errors->any())
<div class="alert alert-danger" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
@foreach($errors->all() as $error)
{{ $error }}<br/>
@endforeach
</div>
@endif
Он покажет все ошибки из сессии или, если вы предпочитаете обрабатывать их по одной, то можете использовать blade-хелпер @error:
@error('title')
<div class="alert alert-danger">{{ $message }}</div>
@enderror
Переменная $message будет передана внутрь тега @error.
Настройка сообщений об ошибках
Вы можете настроить эти сообщения с помощью третьего параметра метода validate:
public function store(Request $request) {
$this->validate($request, [
'name' => 'required|string',
'body' => 'required|string',
'publish_at' => 'required|date_format:Y-m-d H:i:s'
], [
'name.required' => 'Поле Название статьи обязательно для заполнения',
'body.required' => 'Поле Текст статьи обязательно для заполнения',
'publish_at.date_format' => 'Поле Дата публикации имеет неверный формат'
]);
// Данные валидны и будет запущен следующий код
...
}
При работе с Запросом формы можно настроить сообщения об ошибках в методе messages:
public function messages()
{
return [
'name.required' => 'Поле Название статьи обязательно для заполнения',
'body.required' => 'Поле Текст статьи обязательно для заполнения',
'publish_at.date_format' => 'Поле Дата публикации имеет неверный формат'
];
}
Самая свежая и подробная документация по валидации в Laravel находится здесь.
Автор: Anthony Rappa
Перевод: Алексей Широков
Наш Телеграм-канал — следите за новостями о Laravel.
