Валідація
Вступ
Laravel пропонує кілька різних підходів до валідації вхідних даних вашого застосунку. Найпоширеніший - скористатися методом validate, доступним для всіх вхідних HTTP-запитів. Утім, ми розглянемо й інші підходи до валідації.
Laravel містить широкий набір зручних правил валідації, які ви можете застосовувати до даних, - зокрема можливість перевірити унікальність значення в певній таблиці бази даних. Ми детально розглянемо кожне з цих правил, щоб ви ознайомилися з усіма можливостями валідації в Laravel.
Швидкий старт
Щоб дізнатися про потужні можливості валідації в Laravel, розгляньмо повний приклад валідації форми та показу повідомлень про помилки користувачеві. Прочитавши цей загальний огляд, ви добре зрозумієте, як валідувати вхідні дані запиту засобами Laravel:
Визначення маршрутів
Спершу припустімо, що ми маємо такі маршрути у файлі routes/web.php:
use App\Http\Controllers\PostController;
Route::get('/post/create', [PostController::class, 'create']);
Route::post('/post', [PostController::class, 'store']);
Маршрут GET показуватиме форму створення нового допису блогу, а маршрут POST зберігатиме допис у базі даних.
Створення контролера
Далі погляньмо на простий контролер, що обробляє вхідні запити до цих маршрутів. Метод store поки залишимо порожнім:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class PostController extends Controller
{
/**
* Show the form to create a new blog post.
*/
public function create(): View
{
return view('post.create');
}
/**
* Store a new blog post.
*/
public function store(Request $request): RedirectResponse
{
// Validate and store the blog post...
$post = /** ... */
return to_route('post.show', ['post' => $post->id]);
}
}
Написання логіки валідації
Тепер ми готові заповнити метод store логікою валідації нового допису. Для цього скористаємося методом validate, який надає об'єкт Illuminate\Http\Request. Якщо правила валідації пройдено, ваш код виконуватиметься далі як звичайно; однак якщо валідація не пройшла, буде викинуто виняток Illuminate\Validation\ValidationException, і користувачеві автоматично буде надіслано відповідну відповідь із помилкою.
Якщо валідація не пройшла під час традиційного HTTP-запиту, буде згенеровано відповідь-перенаправлення на попередню адресу. Якщо вхідний запит є XHR-запитом, буде повернуто JSON-відповідь із повідомленнями про помилки валідації.
Щоб краще зрозуміти метод validate, повернімося до методу store:
/**
* Store a new blog post.
*/
public function store(Request $request): RedirectResponse
{
$validated = $request->validate([
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);
// The blog post is valid...
return redirect('/posts');
}
Як бачите, правила валідації передаються методу validate. Не хвилюйтеся - усі доступні правила задокументовано. Знову ж таки, якщо валідація не пройде, відповідну відповідь буде згенеровано автоматично. Якщо валідація пройшла, наш контролер продовжить виконуватися як звичайно.
Крім того, ви можете скористатися методом validateWithBag, щоб валідувати запит і зберегти повідомлення про помилки в іменованому наборі помилок:
$validated = $request->validateWithBag('post', [
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);
Зупинка на першій невдалій перевірці
Іноді ви можете захотіти припинити виконання правил валідації для атрибута після першої невдачі. Для цього призначте атрибуту правило bail:
$request->validate([
'title' => ['bail', 'required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);
У цьому прикладі, якщо правило unique для атрибута title не пройде, правило max не перевірятиметься. Правила перевіряються в порядку їх призначення.
Зауваження про вкладені атрибути
Якщо вхідний HTTP-запит містить «вкладені» дані полів, ви можете вказати ці поля у правилах валідації через «крапковий» синтаксис:
$request->validate([
'title' => ['required', 'unique:posts', 'max:255'],
'author.name' => ['required'],
'author.description' => ['required'],
]);
З іншого боку, якщо ім'я вашого поля містить справжню крапку, ви можете явно запобігти її трактуванню як «крапкового» синтаксису, екранувавши її зворотним слешем:
$request->validate([
'title' => ['required', 'unique:posts', 'max:255'],
'v1\.0' => ['required'],
]);
Виведення помилок валідації
Отже, що станеться, якщо поля вхідного запиту не пройдуть указаних правил валідації? Як згадувалося раніше, Laravel автоматично перенаправить користувача на попередню сторінку. Крім того, усі помилки валідації та вхідні дані запиту буде автоматично записано до сесії.
Змінна $errors доступна всім представленням вашого застосунку завдяки middleware Illuminate\View\Middleware\ShareErrorsFromSession, який входить до групи web. Коли цей middleware застосовано, змінна $errors завжди доступна у ваших представленнях, тож ви можете спокійно вважати, що вона завжди визначена. Змінна $errors є екземпляром Illuminate\Support\MessageBag. Докладніше про роботу з цим об'єктом читайте в його документації.
Тож у нашому прикладі, коли валідація не пройде, користувача буде перенаправлено до методу create нашого контролера, що дозволить показати повідомлення про помилки в представленні:
<!-- /resources/views/post/create.blade.php -->
<h1>Create Post</h1>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<!-- Create Post Form -->
Налаштування повідомлень про помилки
Кожне вбудоване правило валідації Laravel має повідомлення про помилку, розташоване у файлі lang/en/validation.php вашого застосунку. Якщо ваш застосунок не має каталогу lang, ви можете створити його командою Artisan lang:publish.
У файлі lang/en/validation.php ви знайдете запис перекладу для кожного правила валідації. Ви вільні змінювати ці повідомлення відповідно до потреб свого застосунку.
Крім того, ви можете скопіювати цей файл до каталогу іншої мови, щоб перекласти повідомлення мовою вашого застосунку. Докладніше про локалізацію в Laravel читайте в повній документації з локалізації.
За замовчуванням каркас застосунку Laravel не містить каталогу
lang. Якщо ви хочете налаштувати мовні файли Laravel, опублікуйте їх командою Artisanlang:publish.
XHR-запити та валідація
У цьому прикладі ми використали традиційну форму для надсилання даних застосунку. Однак багато застосунків отримують XHR-запити від фронтенду на JavaScript. Використовуючи метод validate під час XHR-запиту, Laravel не генеруватиме відповідь-перенаправлення. Натомість Laravel згенерує JSON-відповідь з усіма помилками валідації. Цю JSON-відповідь буде надіслано зі статус-кодом 422.
Директива @error
Ви можете скористатися директивою Blade @error, щоб швидко визначити, чи існують повідомлення про помилки валідації для певного атрибута. Усередині директиви @error ви можете вивести змінну $message, щоб показати повідомлення про помилку:
<!-- /resources/views/post/create.blade.php -->
<label for="title">Post Title</label>
<input
id="title"
type="text"
name="title"
class="@error('title') is-invalid @enderror"
/>
@error('title')
<div class="alert alert-danger">{{ $message }}</div>
@enderror
Якщо ви користуєтеся іменованими наборами помилок, передайте ім'я набору другим аргументом директиви @error:
<input ... class="@error('title', 'post') is-invalid @enderror">
Повторне заповнення форм
Коли Laravel генерує відповідь-перенаправлення через помилку валідації, фреймворк автоматично записує всі вхідні дані запиту до сесії. Це робиться для того, щоб ви могли зручно звернутися до цих даних під час наступного запиту й заново заповнити форму, яку намагався надіслати користувач.
Щоб отримати збережені дані попереднього запиту, викличте метод old на екземплярі Illuminate\Http\Request. Метод old візьме раніше збережені дані із сесії:
$title = $request->old('title');
Laravel також надає глобальний хелпер old. Якщо ви показуєте попередні дані в шаблоні Blade, зручніше скористатися хелпером old, щоб заново заповнити форму. Якщо попередніх даних для вказаного поля немає, буде повернуто null:
<input type="text" name="title" value="{{ old('title') }}">
Зауваження про необов'язкові поля
За замовчуванням Laravel додає middleware TrimStrings та ConvertEmptyStringsToNull до глобального стека вашого застосунку. Через це вам часто доведеться позначати «необов'язкові» поля запиту як nullable, якщо ви не хочете, щоб валідатор вважав значення null недійсними. Наприклад:
$request->validate([
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
'publish_at' => ['nullable', 'date'],
]);
У цьому прикладі ми вказуємо, що поле publish_at може бути або null, або дійсним поданням дати. Якщо модифікатор nullable не додати до визначення правила, валідатор вважатиме null недійсною датою.
Формат відповіді з помилками валідації
Коли ваш застосунок викидає виняток Illuminate\Validation\ValidationException, а вхідний HTTP-запит очікує JSON-відповідь, Laravel автоматично відформатує повідомлення про помилки й поверне HTTP-відповідь 422 Unprocessable Entity.
Нижче наведено приклад формату JSON-відповіді для помилок валідації. Зверніть увагу: вкладені ключі помилок зводяться до «крапкової» нотації:
{
"message": "The team name must be a string. (and 4 more errors)",
"errors": {
"team_name": [
"The team name must be a string.",
"The team name must be at least 1 characters."
],
"authorization.role": [
"The selected authorization.role is invalid."
],
"users.0.email": [
"The users.0.email field is required."
],
"users.2.email": [
"The users.2.email must be a valid email address."
]
}
}
Валідація через запити форм
Створення запитів форм
Для складніших сценаріїв валідації ви можете створити «запит форми» (form request). Запити форм - це власні класи запитів, що інкапсулюють власну логіку валідації та авторизації. Щоб створити клас запиту форми, скористайтеся командою Artisan make:request:
php artisan make:request StorePostRequest
Згенерований клас запиту форми буде розміщено в каталозі app/Http/Requests. Якщо цього каталогу немає, його буде створено під час виконання команди make:request. Кожен згенерований Laravel запит форми має два методи: authorize і rules.
Як ви могли здогадатися, метод authorize відповідає за визначення того, чи може поточний автентифікований користувач виконати дію, яку представляє запит, а метод rules повертає правила валідації, що мають застосовуватися до даних запиту:
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
];
}
Ви можете вказати типи будь-яких потрібних залежностей у сигнатурі методу
rules. Їх буде автоматично розв'язано через сервіс-контейнер Laravel.
Отже, як обчислюються правила валідації? Вам потрібно лише вказати тип запиту в методі контролера. Вхідний запит форми валідується до виклику методу контролера, тобто вам не потрібно захаращувати контролер логікою валідації:
/**
* Store a new blog post.
*/
public function store(StorePostRequest $request): RedirectResponse
{
// The incoming request is valid...
// Retrieve the validated input data...
$validated = $request->validated();
// Retrieve a portion of the validated input data...
$validated = $request->safe()->only(['name', 'email']);
$validated = $request->safe()->except(['name', 'email']);
// Store the blog post...
return redirect('/posts');
}
Якщо валідація не пройде, буде згенеровано відповідь-перенаправлення, щоб повернути користувача на попередню сторінку. Помилки також буде записано до сесії, щоб їх можна було показати. Якщо запит був XHR-запитом, користувачеві буде повернуто HTTP-відповідь зі статус-кодом 422, що містить JSON-подання помилок валідації.
Потрібно додати валідацію запитів форм у реальному часі до вашого фронтенду на Inertia? Перегляньте Laravel Precognition.
Додаткова валідація
Іноді вам потрібно виконати додаткову валідацію після завершення початкової. Це робиться методом after запиту форми.
Метод after має повертати масив викликаних об'єктів чи замикань, які буде виконано після завершення валідації. Передані об'єкти отримають екземпляр Illuminate\Validation\Validator, що дозволить за потреби додати нові повідомлення про помилки:
use Illuminate\Validation\Validator;
/**
* Get the "after" validation callables for the request.
*/
public function after(): array
{
return [
function (Validator $validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add(
'field',
'Something is wrong with this field!'
);
}
}
];
}
Як зазначено, масив, повернений методом after, може також містити викликані класи. Метод __invoke цих класів отримає екземпляр Illuminate\Validation\Validator:
use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;
use Illuminate\Validation\Validator;
/**
* Get the "after" validation callables for the request.
*/
public function after(): array
{
return [
new ValidateUserStatus,
new ValidateShippingTime,
function (Validator $validator) {
//
}
];
}
Зупинка на першій невдалій перевірці
Додавши до класу запиту атрибут StopOnFirstFailure, ви можете повідомити валідатор, що йому слід припинити валідацію всіх атрибутів після першої ж невдачі:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\Attributes\StopOnFirstFailure;
use Illuminate\Foundation\Http\FormRequest;
#[StopOnFirstFailure]
class StorePostRequest extends FormRequest
{
// ...
}
Відхилення невідомих полів
Додавши до класу запиту атрибут FailOnUnknownFields, ви можете вказати Laravel відхиляти будь-які вхідні поля, не визначені правилами валідації вашого запиту:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\Attributes\FailOnUnknownFields;
use Illuminate\Foundation\Http\FormRequest;
#[FailOnUnknownFields]
class StorePostRequest extends FormRequest
{
public function rules(): array
{
return [
'title' => ['required', 'string'],
'body' => ['required', 'string'],
];
}
}
Ви також можете увімкнути цю поведінку глобально для всіх запитів форм зі свого AppServiceProvider:
use Illuminate\Foundation\Http\FormRequest;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
FormRequest::failOnUnknownFields();
}
За потреби ви можете вимкнути цю поведінку для конкретного запиту, передавши атрибуту false:
#[FailOnUnknownFields(false)]
class PublicWebhookRequest extends FormRequest
{
// ...
}
Відхилення невідомих полів дає додатковий захист від проблем на кшталт mass-assignment, не даючи неочікуваним ключам потрапляти глибше у ваш застосунок. Утім, вам усе одно слід налаштувати властивості $fillable / $guarded своєї моделі та зберігати лише довірені валідовані дані.
Налаштування адреси перенаправлення
Коли валідація запиту форми не проходить, генерується відповідь-перенаправлення, що повертає користувача на попередню сторінку. Утім, ви вільні налаштувати цю поведінку. Для цього скористайтеся атрибутом RedirectTo у своєму запиті форми:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\Attributes\RedirectTo;
use Illuminate\Foundation\Http\FormRequest;
#[RedirectTo('/dashboard')]
class StorePostRequest extends FormRequest
{
// ...
}
Або, якщо ви хочете перенаправляти користувачів до іменованого маршруту, скористайтеся натомість атрибутом RedirectToRoute:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\Attributes\RedirectToRoute;
use Illuminate\Foundation\Http\FormRequest;
#[RedirectToRoute('dashboard')]
class StorePostRequest extends FormRequest
{
// ...
}
Налаштування набору помилок
Коли валідація запиту форми не проходить, помилки записуються до набору default. Якщо вам потрібно зберігати їх в іншому іменованому наборі помилок, скористайтеся атрибутом ErrorBag у своєму запиті форми:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\Attributes\ErrorBag;
use Illuminate\Foundation\Http\FormRequest;
#[ErrorBag('login')]
class LoginRequest extends FormRequest
{
// ...
}
Авторизація запитів форм
Клас запиту форми також містить метод authorize. У ньому ви можете визначити, чи справді автентифікований користувач має право оновити певний ресурс. Наприклад, ви можете визначити, чи справді користувач володіє коментарем у блозі, який намагається оновити. Найімовірніше, у цьому методі ви взаємодіятимете зі своїми гейтами та політиками авторизації:
use App\Models\Comment;
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
$comment = Comment::find($this->route('comment'));
return $comment && $this->user()->can('update', $comment);
}
Оскільки всі запити форм успадковують базовий клас запиту Laravel, ми можемо скористатися методом user, щоб отримати поточного автентифікованого користувача. Також зверніть увагу на виклик методу route у прикладі вище. Він дає доступ до параметрів URI, визначених у маршруті, який викликається, - як-от параметр {comment} у прикладі нижче:
Route::post('/comment/{comment}');
Тому, якщо ваш застосунок використовує прив'язку моделей до маршрутів, ваш код можна зробити ще стислішим, звернувшись до розв'язаної моделі як до властивості запиту:
return $this->user()->can('update', $this->comment);
Якщо метод authorize поверне false, автоматично буде повернуто HTTP-відповідь зі статус-кодом 403, а метод вашого контролера не виконається.
Якщо ви плануєте обробляти логіку авторизації запиту в іншій частині застосунку, ви можете цілком прибрати метод authorize або просто повертати true:
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
Ви можете вказати типи будь-яких потрібних залежностей у сигнатурі методу
authorize. Їх буде автоматично розв'язано через сервіс-контейнер Laravel.
Налаштування повідомлень про помилки
Ви можете налаштувати повідомлення про помилки, які використовує запит форми, перевизначивши метод messages. Цей метод має повертати масив пар «атрибут / правило» та відповідних повідомлень про помилки:
/**
* Get the error messages for the defined validation rules.
*
* @return array<string, string>
*/
public function messages(): array
{
return [
'title.required' => 'A title is required',
'body.required' => 'A message is required',
];
}
Налаштування атрибутів валідації
Багато вбудованих повідомлень про помилки валідації в Laravel містять заповнювач :attribute. Якщо ви хочете, щоб заповнювач :attribute у вашому повідомленні замінювався власним іменем атрибута, вкажіть власні імена, перевизначивши метод attributes. Цей метод має повертати масив пар «атрибут / ім'я»:
/**
* Get custom attributes for validator errors.
*
* @return array<string, string>
*/
public function attributes(): array
{
return [
'email' => 'email address',
];
}
Підготовка даних до валідації
Якщо вам потрібно підготувати чи очистити дані запиту перед застосуванням правил валідації, скористайтеся методом prepareForValidation:
use Illuminate\Support\Str;
/**
* Prepare the data for validation.
*/
protected function prepareForValidation(): void
{
$this->merge([
'slug' => Str::slug($this->slug),
]);
}
Так само, якщо вам потрібно нормалізувати дані запиту після завершення валідації, скористайтеся методом passedValidation:
/**
* Handle a passed validation attempt.
*/
protected function passedValidation(): void
{
$this->replace(['name' => 'Taylor']);
}
Ручне створення валідаторів
Якщо ви не хочете використовувати метод validate на запиті, ви можете створити екземпляр валідатора вручну через фасад Validator. Метод make фасаду створює новий екземпляр валідатора:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class PostController extends Controller
{
/**
* Store a new blog post.
*/
public function store(Request $request): RedirectResponse
{
$validator = Validator::make($request->all(), [
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);
if ($validator->fails()) {
return redirect('/post/create')
->withErrors($validator)
->withInput();
}
// Retrieve the validated input...
$validated = $validator->validated();
// Retrieve a portion of the validated input...
$validated = $validator->safe()->only(['name', 'email']);
$validated = $validator->safe()->except(['name', 'email']);
// Store the blog post...
return redirect('/posts');
}
}
Перший аргумент, переданий методу make, - дані, що підлягають валідації. Другий - масив правил валідації, які слід застосувати до цих даних.
Визначивши, що валідація запиту не пройшла, ви можете скористатися методом withErrors, щоб записати повідомлення про помилки до сесії. Використовуючи цей метод, змінна $errors автоматично стане доступною вашим представленням після перенаправлення, що дозволить легко показати помилки користувачеві. Метод withErrors приймає валідатор, MessageBag або PHP-масив.
Зупинка на першій невдалій перевірці
Метод stopOnFirstFailure повідомить валідатор, що йому слід припинити валідацію всіх атрибутів після першої ж невдачі:
if ($validator->stopOnFirstFailure()->fails()) {
// ...
}
Автоматичне перенаправлення
Якщо ви хочете створити екземпляр валідатора вручну, але водночас скористатися автоматичним перенаправленням, яке дає метод validate HTTP-запиту, викличте метод validate на наявному екземплярі валідатора. Якщо валідація не пройде, користувача буде автоматично перенаправлено або, у випадку XHR-запиту, повернено JSON-відповідь:
Validator::make($request->all(), [
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
])->validate();
Ви можете скористатися методом validateWithBag, щоб зберегти повідомлення про помилки в іменованому наборі помилок, якщо валідація не пройде:
Validator::make($request->all(), [
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
])->validateWithBag('post');
Іменовані набори помилок
Якщо на одній сторінці у вас кілька форм, ви можете захотіти дати ім'я MessageBag, що містить помилки валідації, аби отримувати повідомлення для конкретної форми. Для цього передайте ім'я другим аргументом withErrors:
return redirect('/register')->withErrors($validator, 'login');
Далі ви можете звернутися до іменованого екземпляра MessageBag через змінну $errors:
{{ $errors->login->first('email') }}
Налаштування повідомлень про помилки
За потреби ви можете надати власні повідомлення про помилки, які валідатор використовуватиме замість типових повідомлень Laravel. Указати власні повідомлення можна кількома способами. По-перше, ви можете передати їх третім аргументом методу Validator::make:
$validator = Validator::make($input, $rules, $messages = [
'required' => 'The :attribute field is required.',
]);
У цьому прикладі заповнювач :attribute буде замінено фактичним іменем поля, що валідується. Ви можете використовувати й інші заповнювачі в повідомленнях валідації. Наприклад:
$messages = [
'same' => 'The :attribute and :other must match.',
'size' => 'The :attribute must be exactly :size.',
'between' => 'The :attribute value :input is not between :min - :max.',
'in' => 'The :attribute must be one of the following types: :values',
];
Власне повідомлення для конкретного атрибута
Іноді ви можете захотіти вказати власне повідомлення лише для конкретного атрибута. Це робиться через «крапкову» нотацію: спершу ім'я атрибута, потім правило:
$messages = [
'email.required' => 'We need to know your email address!',
];
Власні значення атрибутів
Багато вбудованих повідомлень про помилки Laravel містять заповнювач :attribute, який замінюється іменем поля чи атрибута, що валідується. Щоб налаштувати значення для заміни цих заповнювачів у конкретних полях, передайте масив власних атрибутів четвертим аргументом методу Validator::make:
$validator = Validator::make($input, $rules, $messages, [
'email' => 'email address',
]);
Додаткова валідація
Іноді вам потрібно виконати додаткову валідацію після завершення початкової. Це робиться методом after валідатора. Метод after приймає замикання або масив викликаних об'єктів, які буде виконано після завершення валідації. Вони отримають екземпляр Illuminate\Validation\Validator, що дозволить за потреби додати нові повідомлення про помилки:
use Illuminate\Support\Facades\Validator;
$validator = Validator::make(/* ... */);
$validator->after(function ($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add(
'field', 'Something is wrong with this field!'
);
}
});
if ($validator->fails()) {
// ...
}
Як зазначено, метод after також приймає масив викликаних об'єктів - це особливо зручно, якщо ваша логіка «після валідації» інкапсульована у викликаних класах, які отримають екземпляр Illuminate\Validation\Validator через метод __invoke:
use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;
$validator->after([
new ValidateUserStatus,
new ValidateShippingTime,
function ($validator) {
// ...
},
]);
Робота з валідованими даними
Провалідувавши вхідні дані запиту через запит форми чи створений вручну валідатор, ви можете захотіти отримати саме ті дані, які пройшли валідацію. Це можна зробити кількома способами. По-перше, ви можете викликати метод validated на запиті форми чи екземплярі валідатора. Цей метод повертає масив валідованих даних:
$validated = $request->validated();
$validated = $validator->validated();
Як альтернативу ви можете викликати метод safe на запиті форми чи екземплярі валідатора. Він повертає екземпляр Illuminate\Support\ValidatedInput. Цей об'єкт має методи only, except і all, щоб отримати підмножину валідованих даних або весь їх масив:
$validated = $request->safe()->only(['name', 'email']);
$validated = $request->safe()->except(['name', 'email']);
$validated = $request->safe()->all();
Крім того, екземпляр Illuminate\Support\ValidatedInput можна ітерувати й звертатися до нього як до масиву:
// Validated data may be iterated...
foreach ($request->safe() as $key => $value) {
// ...
}
// Validated data may be accessed as an array...
$validated = $request->safe();
$email = $validated['email'];
Якщо ви хочете додати до валідованих даних додаткові поля, викличте метод merge:
$validated = $request->safe()->merge(['name' => 'Taylor Otwell']);
Якщо ви хочете отримати валідовані дані як колекцію, викличте метод collect:
$collection = $request->safe()->collect();
Робота з повідомленнями про помилки
Викликавши метод errors на екземплярі Validator, ви отримаєте екземпляр Illuminate\Support\MessageBag, що має низку зручних методів для роботи з повідомленнями про помилки. Змінна $errors, автоматично доступна всім представленням, теж є екземпляром класу MessageBag.
Отримання першого повідомлення для поля
Щоб отримати перше повідомлення про помилку для певного поля, скористайтеся методом first:
$errors = $validator->errors();
echo $errors->first('email');
Отримання всіх повідомлень для поля
Якщо вам потрібен масив усіх повідомлень для певного поля, скористайтеся методом get:
foreach ($errors->get('email') as $message) {
// ...
}
Якщо ви валідуєте поле форми, що є масивом, ви можете отримати всі повідомлення для кожного елемента масиву за допомогою символу *:
foreach ($errors->get('attachments.*') as $message) {
// ...
}
Отримання всіх повідомлень для всіх полів
Щоб отримати масив усіх повідомлень для всіх полів, скористайтеся методом all:
foreach ($errors->all() as $message) {
// ...
}
Визначення наявності повідомлень для поля
Метод has дозволяє визначити, чи існують повідомлення про помилки для певного поля:
if ($errors->has('email')) {
// ...
}
Власні повідомлення у мовних файлах
Кожне вбудоване правило валідації Laravel має повідомлення про помилку, розташоване у файлі lang/en/validation.php вашого застосунку. Якщо ваш застосунок не має каталогу lang, ви можете створити його командою Artisan lang:publish.
У файлі lang/en/validation.php ви знайдете запис перекладу для кожного правила валідації. Ви вільні змінювати ці повідомлення відповідно до потреб свого застосунку.
Крім того, ви можете скопіювати цей файл до каталогу іншої мови, щоб перекласти повідомлення мовою вашого застосунку. Докладніше про локалізацію в Laravel читайте в повній документації з локалізації.
За замовчуванням каркас застосунку Laravel не містить каталогу
lang. Якщо ви хочете налаштувати мовні файли Laravel, опублікуйте їх командою Artisanlang:publish.
Власні повідомлення для конкретних атрибутів
Ви можете налаштувати повідомлення про помилки для вказаних комбінацій атрибута й правила у мовних файлах валідації вашого застосунку. Для цього додайте свої налаштування до масиву custom у файлі lang/xx/validation.php:
'custom' => [
'email' => [
'required' => 'We need to know your email address!',
'max' => 'Your email address is too long!'
],
],
Атрибути у мовних файлах
Багато вбудованих повідомлень про помилки Laravel містять заповнювач :attribute, який замінюється іменем поля чи атрибута, що валідується. Якщо ви хочете, щоб частину :attribute вашого повідомлення було замінено власним значенням, вкажіть власне ім'я атрибута в масиві attributes вашого файлу lang/xx/validation.php:
'attributes' => [
'email' => 'email address',
],
За замовчуванням каркас застосунку Laravel не містить каталогу
lang. Якщо ви хочете налаштувати мовні файли Laravel, опублікуйте їх командою Artisanlang:publish.
Значення у мовних файлах
Деякі вбудовані повідомлення про помилки валідації в Laravel містять заповнювач :value, який замінюється поточним значенням атрибута запиту. Однак подекуди вам може знадобитися, щоб частину :value вашого повідомлення було замінено зрозумілішим поданням значення. Наприклад, розгляньмо правило, яке вказує, що номер кредитної картки обов'язковий, якщо payment_type має значення cc:
Validator::make($request->all(), [
'credit_card_number' => ['required_if:payment_type,cc']
]);
Якщо це правило валідації не пройде, воно створить таке повідомлення про помилку:
The credit card number field is required when payment type is cc.
Замість показувати cc як значення типу платежу, ви можете вказати зрозуміліше подання у своєму файлі lang/xx/validation.php, визначивши масив values:
'values' => [
'payment_type' => [
'cc' => 'credit card'
],
],
За замовчуванням каркас застосунку Laravel не містить каталогу
lang. Якщо ви хочете налаштувати мовні файли Laravel, опублікуйте їх командою Artisanlang:publish.
Після визначення цього значення правило валідації створить таке повідомлення про помилку:
The credit card number field is required when payment type is credit card.
Доступні правила валідації
Нижче наведено список усіх доступних правил валідації та їхнє призначення:
Booleans
Strings
Active URL Alpha Alpha Dash Alpha Numeric Ascii Confirmed Current Password Different Doesnt Start With Doesnt End With Email Ends With Enum Hex Color In IP Address JSON Lowercase MAC Address Max Min Not In Regular Expression Not Regular Expression Same Size Starts With String Uppercase URL ULID UUID
Numbers
Between Decimal Different Digits Digits Between Greater Than Greater Than Or Equal Integer Less Than Less Than Or Equal Max Max Digits Min Min Digits Multiple Of Numeric Same Size
Arrays
Dates
Files
Between Dimensions Encoding Extensions File Image Max Min MIME Types MIME Type By File Extension Size
Database
Utilities
Any Of Bail Exclude Exclude If Exclude Unless Exclude With Exclude Without Filled Missing Missing If Missing Unless Missing With Missing With All Nullable Present Present If Present Unless Present With Present With All Prohibited Prohibited If Prohibited If Accepted Prohibited If Declined Prohibited Unless Prohibits Required Required If Required If Accepted Required If Declined Required Unless Required With Required With All Required Without Required Without All Required Array Keys Sometimes
accepted
Поле, що валідується, має бути "yes", "on", 1, "1", true чи "true". Це корисно для перевірки прийняття «Умов використання» та подібних полів.
accepted_if:anotherfield,value,...
Поле, що валідується, має бути "yes", "on", 1, "1", true чи "true", якщо інше поле дорівнює вказаному значенню. Це корисно для перевірки прийняття «Умов використання» та подібних полів.
active_url
Поле, що валідується, має мати дійсний запис A чи AAAA згідно з PHP-функцією dns_get_record. Ім'я хоста з наданого URL витягується PHP-функцією parse_url перед передаванням до dns_get_record.
after:date
Поле, що валідується, має бути значенням після вказаної дати. Дати передаються до PHP-функції strtotime, щоб перетворити їх на дійсний екземпляр DateTime:
'start_date' => ['required', 'date', 'after:tomorrow']
Замість передавати рядок дати для обчислення через strtotime, ви можете вказати інше поле для порівняння:
'finish_date' => ['required', 'date', 'after:start_date']
Для зручності правила на основі дат можна будувати плинним конструктором date:
use Illuminate\Validation\Rule;
'start_date' => [
'required',
Rule::date()->after(today()->addDays(7)),
],
Методи afterToday і todayOrAfter дозволяють плинно виразити, що дата має бути після сьогодні або сьогодні чи пізніше відповідно:
'start_date' => [
'required',
Rule::date()->afterToday(),
],
after_or_equal:date
Поле, що валідується, має бути значенням після вказаної дати або дорівнювати їй. Докладніше дивіться правило after.
Для зручності правила на основі дат можна будувати плинним конструктором date:
use Illuminate\Validation\Rule;
'start_date' => [
'required',
Rule::date()->afterOrEqual(today()->addDays(7)),
],
anyOf
Правило валідації Rule::anyOf дозволяє вказати, що поле має задовольняти будь-який із наведених наборів правил. Наприклад, наступне правило перевірить, що поле username є або адресою електронної пошти, або буквено-цифровим рядком (із дефісами) щонайменше з 6 символів:
use Illuminate\Validation\Rule;
'username' => [
'required',
Rule::anyOf([
['string', 'email'],
['string', 'alpha_dash', 'min:6'],
]),
],
alpha
Поле, що валідується, має складатися виключно з літер Unicode, що входять до \p{L} та \p{M}.
Щоб обмежити це правило символами діапазону ASCII (a-z та A-Z), передайте правилу опцію ascii:
'username' => ['alpha:ascii'],
alpha_dash
Поле, що валідується, має складатися виключно з буквено-цифрових символів Unicode, що входять до \p{L}, \p{M}, \p{N}, а також ASCII-дефісів (-) та ASCII-підкреслень (_).
Щоб обмежити це правило символами діапазону ASCII (a-z, A-Z та 0-9), передайте правилу опцію ascii:
'username' => ['alpha_dash:ascii'],
alpha_num
Поле, що валідується, має складатися виключно з буквено-цифрових символів Unicode, що входять до \p{L}, \p{M} та \p{N}.
Щоб обмежити це правило символами діапазону ASCII (a-z, A-Z та 0-9), передайте правилу опцію ascii:
'username' => ['alpha_num:ascii'],
array
Поле, що валідується, має бути PHP-масивом (array).
Коли правилу array передано додаткові значення, кожен ключ вхідного масиву має бути присутнім у переданому списку значень. У прикладі нижче ключ admin у вхідному масиві недійсний, бо його немає в списку значень, переданих правилу array:
use Illuminate\Support\Facades\Validator;
$input = [
'user' => [
'name' => 'Taylor Otwell',
'username' => 'taylorotwell',
'admin' => true,
],
];
Validator::make($input, [
'user' => ['array:name,username'],
]);
Загалом вам слід завжди вказувати ключі масиву, які дозволено в ньому мати.
ascii
Поле, що валідується, має складатися виключно із 7-бітних символів ASCII.
bail
Припинити виконання правил валідації для поля після першої невдалої перевірки.
Тоді як правило bail припиняє валідацію лише конкретного поля, метод stopOnFirstFailure повідомить валідатор, що йому слід припинити валідацію всіх атрибутів після першої ж невдачі:
if ($validator->stopOnFirstFailure()->fails()) {
// ...
}
before:date
Поле, що валідується, має бути значенням перед указаною датою. Дати передаються до PHP-функції strtotime, щоб перетворити їх на дійсний екземпляр DateTime. Крім того, як і в правилі after, як значення date можна передати ім'я іншого поля.
Для зручності правила на основі дат можна також будувати плинним конструктором date:
use Illuminate\Validation\Rule;
'start_date' => [
'required',
Rule::date()->before(today()->subDays(7)),
],
Методи beforeToday і todayOrBefore дозволяють плинно виразити, що дата має бути до сьогодні або сьогодні чи раніше відповідно:
'start_date' => [
'required',
Rule::date()->beforeToday(),
],
before_or_equal:date
Поле, що валідується, має бути значенням перед указаною датою або дорівнювати їй. Дати передаються до PHP-функції strtotime, щоб перетворити їх на дійсний екземпляр DateTime. Крім того, як і в правилі after, як значення date можна передати ім'я іншого поля.
Для зручності правила на основі дат можна також будувати плинним конструктором date:
use Illuminate\Validation\Rule;
'start_date' => [
'required',
Rule::date()->beforeOrEqual(today()->subDays(7)),
],
between:min,max
Поле, що валідується, має мати розмір між указаними min і max (включно). Рядки, числа, масиви та файли оцінюються так само, як у правилі size.
boolean
Поле, що валідується, має піддаватися приведенню до булевого типу. Прийнятні значення: true, false, 1, 0, "1" та "0".
Ви можете скористатися параметром strict, щоб вважати поле дійсним лише тоді, коли його значення є true чи false:
'foo' => ['boolean:strict']
confirmed
Поле, що валідується, має мати відповідне поле {field}_confirmation. Наприклад, якщо валідується поле password, у вхідних даних має бути присутнє поле password_confirmation.
Ви також можете передати власне ім'я поля підтвердження. Наприклад, confirmed:repeat_username очікуватиме, що поле repeat_username збігатиметься з полем, що валідується.
contains:foo,bar,...
Поле, що валідується, має бути масивом, який містить усі передані значення. Оскільки це правило часто потребує implode масиву, для плинної побудови правила можна скористатися методом Rule::contains:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'roles' => [
'required',
'array',
Rule::contains(['admin', 'editor']),
],
]);
doesnt_contain:foo,bar,...
Поле, що валідується, має бути масивом, який не містить жодного з переданих значень. Оскільки це правило часто потребує implode масиву, для плинної побудови правила можна скористатися методом Rule::doesntContain:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'roles' => [
'required',
'array',
Rule::doesntContain(['admin', 'editor']),
],
]);
current_password
Поле, що валідується, має збігатися з паролем автентифікованого користувача. Ви можете вказати гард автентифікації першим параметром правила:
'password' => ['current_password:api']
date
Поле, що валідується, має бути дійсною невідносною датою згідно з PHP-функцією strtotime.
date_equals:date
Поле, що валідується, має дорівнювати вказаній даті. Дати передаються до PHP-функції strtotime, щоб перетворити їх на дійсний екземпляр DateTime.
date_format:format,...
Поле, що валідується, має відповідати одному з указаних форматів. Валідуючи поле, слід використовувати або date, або date_format, але не обидва. Це правило підтримує всі формати, які підтримує PHP-клас DateTime.
Для зручності правила на основі дат можна будувати плинним конструктором date:
use Illuminate\Validation\Rule;
'start_date' => [
'required',
Rule::date()->format('Y-m-d'),
],
decimal:min,max
Поле, що валідується, має бути числовим і містити вказану кількість десяткових знаків:
// Must have exactly two decimal places (9.99)...
'price' => ['decimal:2']
// Must have between 2 and 4 decimal places...
'price' => ['decimal:2,4']
declined
Поле, що валідується, має бути "no", "off", 0, "0", false чи "false".
declined_if:anotherfield,value,...
Поле, що валідується, має бути "no", "off", 0, "0", false чи "false", якщо інше поле дорівнює вказаному значенню.
different:field
Поле, що валідується, має мати значення, відмінне від field.
digits:value
Ціле число, що валідується, має мати точну довжину value.
digits_between:min,max
Ціле число, що валідується, має мати довжину між указаними min і max.
dimensions
Файл, що валідується, має бути зображенням, яке відповідає обмеженням розмірів, указаним у параметрах правила:
'avatar' => ['dimensions:min_width=100,min_height=200']
Доступні обмеження: min_width, max_width, min_height, max_height, width, height, ratio, min_ratio, max_ratio.
Обмеження ratio слід подавати як ширину, поділену на висоту. Це можна вказати або дробом на кшталт 3/2, або числом із рухомою комою на кшталт 1.5:
'avatar' => ['dimensions:ratio=3/2']
Обмеження min_ratio та max_ratio дозволяють задати діапазон прийнятних співвідношень сторін:
'avatar' => ['dimensions:min_ratio=1/2,max_ratio=3/2']
Оскільки це правило потребує кількох аргументів, часто зручніше скористатися методом Rule::dimensions для плинної побудови правила:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'avatar' => [
'required',
Rule::dimensions()
->maxWidth(1000)
->maxHeight(500)
->ratio(3 / 2),
],
]);
Ви також можете скористатися методами minRatio, maxRatio та ratioBetween, щоб плинно задати обмеження співвідношення:
Rule::dimensions()->ratioBetween(min: 1 / 2, max: 3 / 2)
distinct
Валідуючи масиви, поле, що валідується, не має містити повторюваних значень:
'foo.*.id' => ['distinct']
За замовчуванням distinct використовує нестроге порівняння змінних. Щоб застосувати строге порівняння, додайте до визначення правила параметр strict:
'foo.*.id' => ['distinct:strict']
Ви можете додати до аргументів правила ignore_case, щоб воно ігнорувало відмінності в регістрі:
'foo.*.id' => ['distinct:ignore_case']
doesnt_start_with:foo,bar,...
Поле, що валідується, не має починатися з жодного з переданих значень.
doesnt_end_with:foo,bar,...
Поле, що валідується, не має закінчуватися жодним із переданих значень.
Поле, що валідується, має бути відформатоване як адреса електронної пошти. Це правило використовує пакет egulias/email-validator. За замовчуванням застосовується валідатор RFCValidation, але ви можете застосувати й інші стилі валідації:
'email' => ['email:rfc,dns']
Наведений вище приклад застосує валідації RFCValidation та DNSCheckValidation. Ось повний список стилів валідації, які можна застосувати:
rfc:RFCValidation- валідувати адресу згідно з підтримуваними RFC.strict:NoRFCWarningsValidation- валідувати адресу згідно з підтримуваними RFC, відхиляючи її за наявності попереджень (наприклад, крапка наприкінці чи кілька крапок поспіль).dns:DNSCheckValidation- переконатися, що домен адреси має дійсний MX-запис.spoof:SpoofCheckValidation- переконатися, що адреса не містить гомогліфів чи оманливих символів Unicode.filter:FilterEmailValidation- переконатися, що адреса дійсна згідно з PHP-функцієюfilter_var.filter_unicode:FilterEmailValidation::unicode()- переконатися, що адреса дійсна згідно з PHP-функцієюfilter_var, дозволяючи деякі символи Unicode.
Для зручності правила валідації електронної пошти можна будувати плинним конструктором:
use Illuminate\Validation\Rule;
$request->validate([
'email' => [
'required',
Rule::email()
->rfcCompliant(strict: false)
->validateMxRecord()
->preventSpoofing()
],
]);
Валідатори
dnsіspoofпотребують PHP-розширенняintl.
encoding:encoding_type
Поле, що валідується, має відповідати вказаному кодуванню символів. Це правило використовує PHP-функцію mb_check_encoding, щоб перевірити кодування переданого файлу чи рядка. Для зручності правило encoding можна будувати плинним конструктором файлових правил Laravel:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\File;
Validator::validate($input, [
'attachment' => [
'required',
File::types(['csv'])
->encoding('utf-8'),
],
]);
ends_with:foo,bar,...
Поле, що валідується, має закінчуватися одним із переданих значень.
enum
Правило Enum - це правило на основі класу, що перевіряє, чи містить поле дійсне значення enum. Правило Enum приймає ім'я enum як єдиний аргумент конструктора. Валідуючи примітивні значення, правилу Enum слід передавати enum на основі значень (backed enum):
use App\Enums\ServerStatus;
use Illuminate\Validation\Rule;
$request->validate([
'status' => [Rule::enum(ServerStatus::class)],
]);
Методи only та except правила Enum дозволяють обмежити, які випадки enum вважати дійсними:
Rule::enum(ServerStatus::class)
->only([ServerStatus::Pending, ServerStatus::Active]);
Rule::enum(ServerStatus::class)
->except([ServerStatus::Pending, ServerStatus::Active]);
Метод when дозволяє умовно змінювати правило Enum:
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Rule;
Rule::enum(ServerStatus::class)
->when(
Auth::user()->isAdmin(),
fn ($rule) => $rule->only(...),
fn ($rule) => $rule->only(...),
);
exclude
Поле, що валідується, буде виключено з даних запиту, які повертають методи validate та validated.
exclude_if:anotherfield,value
Поле, що валідується, буде виключено з даних запиту, які повертають методи validate та validated, якщо поле anotherfield дорівнює value.
Якщо потрібна складна умовна логіка виключення, скористайтеся методом Rule::excludeIf. Він приймає булеве значення або замикання. Замикання має повертати true чи false, вказуючи, чи слід виключити поле:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($request->all(), [
'role_id' => [Rule::excludeIf($request->user()->is_admin)],
]);
Validator::make($request->all(), [
'role_id' => [Rule::excludeIf(fn () => $request->user()->is_admin)],
]);
exclude_unless:anotherfield,value
Поле, що валідується, буде виключено з даних запиту, які повертають методи validate та validated, якщо тільки поле anotherfield не дорівнює value. Якщо value є null (exclude_unless:name,null), поле буде виключено, якщо тільки поле для порівняння не є null або відсутнє в даних запиту.
Якщо потрібна складна умовна логіка виключення, скористайтеся методом Rule::excludeUnless. Він приймає булеве значення або замикання. Замикання має повертати true чи false, вказуючи, чи не слід виключати поле:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($request->all(), [
'role_id' => [Rule::excludeUnless($request->user()->is_admin)],
]);
Validator::make($request->all(), [
'role_id' => [Rule::excludeUnless(fn () => $request->user()->is_admin)],
]);
exclude_with:anotherfield
Поле, що валідується, буде виключено з даних запиту, які повертають методи validate та validated, якщо поле anotherfield присутнє.
exclude_without:anotherfield
Поле, що валідується, буде виключено з даних запиту, які повертають методи validate та validated, якщо поле anotherfield відсутнє.
exists:table,column
Поле, що валідується, має існувати у вказаній таблиці бази даних.
Базове використання правила Exists
'state' => ['exists:states']
Якщо опцію column не вказано, буде використано ім'я поля. Тож у цьому випадку правило перевірить, що таблиця states містить запис зі значенням колонки state, що збігається зі значенням атрибута state у запиті.
Указання власного імені колонки
Ви можете явно вказати ім'я колонки бази даних, яку має використовувати правило валідації, розмістивши його після імені таблиці:
'state' => ['exists:states,abbreviation']
Подекуди вам може знадобитися вказати конкретне підключення до бази даних для запиту exists. Це робиться додаванням імені підключення перед іменем таблиці:
'email' => ['exists:connection.staff,email']
Замість указувати ім'я таблиці напряму, ви можете вказати модель Eloquent, за якою буде визначено ім'я таблиці:
'user_id' => ['exists:App\Models\User,id']
Якщо ви хочете налаштувати запит, який виконує правило валідації, скористайтеся класом Rule для плинного визначення правила.
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::exists('staff')->where(function (Builder $query) {
$query->where('account_id', 1);
}),
],
]);
Ви можете явно вказати ім'я колонки для правила exists, згенерованого методом Rule::exists, передавши його другим аргументом методу exists:
'state' => [Rule::exists('states', 'abbreviation')],
Іноді ви можете захотіти перевірити, чи існує в базі даних масив значень. Це робиться додаванням до поля обох правил - exists та array:
'states' => ['array', Rule::exists('states', 'abbreviation')],
Коли полю призначено обидва ці правила, Laravel автоматично побудує єдиний запит, щоб визначити, чи всі передані значення існують у вказаній таблиці.
extensions:foo,bar,...
Файл, що валідується, має мати призначене користувачем розширення, що відповідає одному з перелічених:
'photo' => ['required', 'extensions:jpg,png'],
Ніколи не покладайтеся на перевірку файлу лише за призначеним користувачем розширенням. Це правило зазвичай слід використовувати в поєднанні з правилами mimes чи mimetypes.
file
Поле, що валідується, має бути успішно завантаженим файлом.
filled
Поле, що валідується, не має бути порожнім, коли воно присутнє.
gt:field
Поле, що валідується, має бути більшим за вказане field чи value. Обидва поля мають бути одного типу. Рядки, числа, масиви та файли оцінюються за тими самими домовленостями, що й у правилі size.
gte:field
Поле, що валідується, має бути більшим за вказане field чи value або дорівнювати йому. Обидва поля мають бути одного типу. Рядки, числа, масиви та файли оцінюються за тими самими домовленостями, що й у правилі size.
hex_color
Поле, що валідується, має містити дійсне значення кольору у шістнадцятковому форматі.
image
Файл, що валідується, має бути зображенням (jpg, jpeg, png, bmp, gif чи webp).
За замовчуванням правило
imageне дозволяє файли SVG через можливість XSS-вразливостей. Якщо вам потрібно дозволити SVG, передайте правилуimageдирективуallow_svg(image:allow_svg).
in:foo,bar,...
Поле, що валідується, має входити до переданого списку значень. Оскільки це правило часто потребує implode масиву, для плинної побудови правила можна скористатися методом Rule::in:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'zones' => [
'required',
Rule::in(['first-zone', 'second-zone']),
],
]);
Коли правило in поєднано з правилом array, кожне значення вхідного масиву має бути присутнім у списку значень, переданих правилу in. У прикладі нижче код аеропорту LAS у вхідному масиві недійсний, бо його немає в переданому списку:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
$input = [
'airports' => ['NYC', 'LAS'],
];
Validator::make($input, [
'airports' => [
'required',
'array',
],
'airports.*' => Rule::in(['NYC', 'LIT']),
]);
in_array:anotherfield.*
Поле, що валідується, має існувати серед значень anotherfield.
in_array_keys:value.*
Поле, що валідується, має бути масивом, який містить принаймні одне з переданих значень як ключ:
'config' => ['array', 'in_array_keys:timezone']
integer
Поле, що валідується, має бути цілим числом.
Ви можете скористатися параметром strict, щоб вважати поле дійсним лише тоді, коли його тип - integer. Рядки з цілими значеннями вважатимуться недійсними:
'age' => ['integer:strict']
Це правило не перевіряє, що вхідні дані мають тип змінної «integer», а лише те, що вони мають тип, прийнятний для PHP-правила
FILTER_VALIDATE_INT. Якщо вам потрібно перевірити, що вхідні дані є числом, використовуйте це правило в поєднанні з правиломnumeric.
ip
Поле, що валідується, має бути IP-адресою.
ipv4
Поле, що валідується, має бути адресою IPv4.
ipv6
Поле, що валідується, має бути адресою IPv6.
json
Поле, що валідується, має бути дійсним рядком JSON.
lt:field
Поле, що валідується, має бути меншим за вказане field. Обидва поля мають бути одного типу. Рядки, числа, масиви та файли оцінюються за тими самими домовленостями, що й у правилі size.
lte:field
Поле, що валідується, має бути меншим за вказане field або дорівнювати йому. Обидва поля мають бути одного типу. Рядки, числа, масиви та файли оцінюються за тими самими домовленостями, що й у правилі size.
lowercase
Поле, що валідується, має бути в нижньому регістрі.
list
Поле, що валідується, має бути масивом-списком. Масив вважається списком, якщо його ключі є послідовними числами від 0 до count($array) - 1.
mac_address
Поле, що валідується, має бути MAC-адресою.
max:value
Поле, що валідується, має бути меншим за максимальне value або дорівнювати йому. Рядки, числа, масиви та файли оцінюються так само, як у правилі size.
max_digits:value
Ціле число, що валідується, має мати максимальну довжину value.
mimetypes:text/plain,...
Файл, що валідується, має відповідати одному з указаних MIME-типів:
'video' => ['mimetypes:video/avi,video/mpeg,video/quicktime'],
'media' => ['mimetypes:image/*,video/*'],
Щоб визначити MIME-тип завантаженого файлу, буде прочитано його вміст, і фреймворк спробує вгадати тип, який може відрізнятися від наданого клієнтом.
mimes:foo,bar,...
Файл, що валідується, має мати MIME-тип, що відповідає одному з перелічених розширень:
'photo' => ['mimes:jpg,bmp,png']
Хоча вам потрібно вказати лише розширення, це правило насправді перевіряє MIME-тип файлу, читаючи його вміст і вгадуючи тип. Повний перелік MIME-типів та відповідних їм розширень можна знайти тут:
https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
MIME-типи та розширення
Це правило не перевіряє відповідність між MIME-типом і розширенням, яке користувач призначив файлу. Наприклад, правило mimes:png вважатиме файл із дійсним вмістом PNG дійсним зображенням PNG, навіть якщо файл названо photo.txt. Якщо ви хочете перевірити призначене користувачем розширення, скористайтеся правилом extensions.
min:value
Поле, що валідується, має мати мінімальне значення value. Рядки, числа, масиви та файли оцінюються так само, як у правилі size.
min_digits:value
Ціле число, що валідується, має мати мінімальну довжину value.
multiple_of:value
Поле, що валідується, має бути кратним value.
missing
Поле, що валідується, не має бути присутнім у вхідних даних.
missing_if:anotherfield,value,...
Поле, що валідується, не має бути присутнім, якщо поле anotherfield дорівнює будь-якому value.
missing_unless:anotherfield,value
Поле, що валідується, не має бути присутнім, якщо тільки поле anotherfield не дорівнює будь-якому value.
missing_with:foo,bar,...
Поле, що валідується, не має бути присутнім, лише якщо присутнє будь-яке з інших указаних полів.
missing_with_all:foo,bar,...
Поле, що валідується, не має бути присутнім, лише якщо присутні всі інші вказані поля.
not_in:foo,bar,...
Поле, що валідується, не має входити до переданого списку значень. Для плинної побудови правила можна скористатися методом Rule::notIn:
use Illuminate\Validation\Rule;
Validator::make($data, [
'toppings' => [
'required',
Rule::notIn(['sprinkles', 'cherries']),
],
]);
not_regex:pattern
Поле, що валідується, не має збігатися з указаним регулярним виразом.
Внутрішньо це правило використовує PHP-функцію preg_match. Указаний шаблон має відповідати тому самому форматуванню, якого потребує preg_match, тобто містити й дійсні роздільники. Наприклад: 'email' => ['not_regex:/^.+$/i'].
nullable
Поле, що валідується, може бути null.
numeric
Поле, що валідується, має бути числовим.
Ви можете скористатися параметром strict, щоб вважати поле дійсним лише тоді, коли його значення має тип integer чи float. Числові рядки вважатимуться недійсними:
'amount' => ['numeric:strict']
present
Поле, що валідується, має існувати у вхідних даних.
present_if:anotherfield,value,...
Поле, що валідується, має бути присутнім, якщо поле anotherfield дорівнює будь-якому value.
present_unless:anotherfield,value
Поле, що валідується, має бути присутнім, якщо тільки поле anotherfield не дорівнює будь-якому value.
present_with:foo,bar,...
Поле, що валідується, має бути присутнім, лише якщо присутнє будь-яке з інших указаних полів.
present_with_all:foo,bar,...
Поле, що валідується, має бути присутнім, лише якщо присутні всі інші вказані поля.
prohibited
Поле, що валідується, має бути відсутнім або порожнім. Поле є «порожнім», якщо воно відповідає одному з таких критеріїв:
- Значення дорівнює
null. - Значення є порожнім рядком.
- Значення є порожнім масивом або порожнім об'єктом
Countable. - Значення є завантаженим файлом із порожнім шляхом.
prohibited_if:anotherfield,value,...
Поле, що валідується, має бути відсутнім або порожнім, якщо поле anotherfield дорівнює будь-якому value. Поле є «порожнім», якщо воно відповідає одному з таких критеріїв:
- Значення дорівнює
null. - Значення є порожнім рядком.
- Значення є порожнім масивом або порожнім об'єктом
Countable. - Значення є завантаженим файлом із порожнім шляхом.
Якщо потрібна складна умовна логіка заборони, скористайтеся методом Rule::prohibitedIf. Він приймає булеве значення або замикання. Замикання має повертати true чи false, вказуючи, чи слід заборонити поле:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($request->all(), [
'role_id' => [Rule::prohibitedIf($request->user()->is_admin)],
]);
Validator::make($request->all(), [
'role_id' => [Rule::prohibitedIf(fn () => $request->user()->is_admin)],
]);
prohibited_if_accepted:anotherfield,...
Поле, що валідується, має бути відсутнім або порожнім, якщо поле anotherfield дорівнює "yes", "on", 1, "1", true чи "true".
prohibited_if_declined:anotherfield,...
Поле, що валідується, має бути відсутнім або порожнім, якщо поле anotherfield дорівнює "no", "off", 0, "0", false чи "false".
prohibited_unless:anotherfield,value,...
Поле, що валідується, має бути відсутнім або порожнім, якщо тільки поле anotherfield не дорівнює будь-якому value. Поле є «порожнім», якщо воно відповідає одному з таких критеріїв:
- Значення дорівнює
null. - Значення є порожнім рядком.
- Значення є порожнім масивом або порожнім об'єктом
Countable. - Значення є завантаженим файлом із порожнім шляхом.
Якщо потрібна складна умовна логіка заборони, скористайтеся методом Rule::prohibitedUnless. Він приймає булеве значення або замикання. Замикання має повертати true чи false, вказуючи, чи не слід забороняти поле:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($request->all(), [
'role_id' => [Rule::prohibitedUnless($request->user()->is_admin)],
]);
Validator::make($request->all(), [
'role_id' => [Rule::prohibitedUnless(fn () => $request->user()->is_admin)],
]);
prohibits:anotherfield,...
Якщо поле, що валідується, не є відсутнім чи порожнім, усі поля в anotherfield мають бути відсутніми або порожніми. Поле є «порожнім», якщо воно відповідає одному з таких критеріїв:
- Значення дорівнює
null. - Значення є порожнім рядком.
- Значення є порожнім масивом або порожнім об'єктом
Countable. - Значення є завантаженим файлом із порожнім шляхом.
regex:pattern
Поле, що валідується, має збігатися з указаним регулярним виразом.
Внутрішньо це правило використовує PHP-функцію preg_match. Указаний шаблон має відповідати тому самому форматуванню, якого потребує preg_match, тобто містити й дійсні роздільники. Наприклад: 'email' => ['regex:/^.+@.+$/i'].
required
Поле, що валідується, має бути присутнім у вхідних даних і не бути порожнім. Поле є «порожнім», якщо воно відповідає одному з таких критеріїв:
- Значення дорівнює
null. - Значення є порожнім рядком.
- Значення є порожнім масивом або порожнім об'єктом
Countable. - Значення є завантаженим файлом без шляху.
required_if:anotherfield,value,...
Поле, що валідується, має бути присутнім і не порожнім, якщо поле anotherfield дорівнює будь-якому value.
Якщо ви хочете побудувати складнішу умову для правила required_if, скористайтеся методом Rule::requiredIf. Він приймає булеве значення або замикання. Замикання має повертати true чи false, вказуючи, чи є поле обов'язковим:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($request->all(), [
'role_id' => [Rule::requiredIf($request->user()->is_admin)],
]);
Validator::make($request->all(), [
'role_id' => [Rule::requiredIf(fn () => $request->user()->is_admin)],
]);
required_if_accepted:anotherfield,...
Поле, що валідується, має бути присутнім і не порожнім, якщо поле anotherfield дорівнює "yes", "on", 1, "1", true чи "true".
required_if_declined:anotherfield,...
Поле, що валідується, має бути присутнім і не порожнім, якщо поле anotherfield дорівнює "no", "off", 0, "0", false чи "false".
required_unless:anotherfield,value,...
Поле, що валідується, має бути присутнім і не порожнім, якщо тільки поле anotherfield не дорівнює будь-якому value. Це також означає, що anotherfield має бути присутнім у даних запиту, якщо тільки value не є null. Якщо value є null (required_unless:name,null), поле буде обов'язковим, якщо тільки поле для порівняння не є null або відсутнє в даних запиту.
Якщо ви хочете побудувати складнішу умову для правила required_unless, скористайтеся методом Rule::requiredUnless. Він приймає булеве значення або замикання. Замикання має повертати true чи false, вказуючи, чи не є поле обов'язковим:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($request->all(), [
'role_id' => [Rule::requiredUnless($request->user()->is_admin)],
]);
Validator::make($request->all(), [
'role_id' => [Rule::requiredUnless(fn () => $request->user()->is_admin)],
]);
required_with:foo,bar,...
Поле, що валідується, має бути присутнім і не порожнім, лише якщо будь-яке з інших указаних полів присутнє й не порожнє.
required_with_all:foo,bar,...
Поле, що валідується, має бути присутнім і не порожнім, лише якщо всі інші вказані поля присутні й не порожні.
required_without:foo,bar,...
Поле, що валідується, має бути присутнім і не порожнім, лише коли будь-яке з інших указаних полів порожнє чи відсутнє.
required_without_all:foo,bar,...
Поле, що валідується, має бути присутнім і не порожнім, лише коли всі інші вказані поля порожні чи відсутні.
required_array_keys:foo,bar,...
Поле, що валідується, має бути масивом і містити принаймні вказані ключі.
same:field
Указане field має збігатися з полем, що валідується.
size:value
Поле, що валідується, має мати розмір, що відповідає вказаному value. Для рядкових даних value відповідає кількості символів. Для числових - вказаному цілому значенню (атрибут також має мати правило numeric чи integer). Для масиву size відповідає результату count. Для файлів size відповідає розміру файлу в кілобайтах. Погляньмо на приклади:
// Validate that a string is exactly 12 characters long...
'title' => ['size:12'];
// Validate that a provided integer equals 10...
'seats' => ['integer', 'size:10'];
// Validate that an array has exactly 5 elements...
'tags' => ['array', 'size:5'];
// Validate that an uploaded file is exactly 512 kilobytes...
'image' => ['file', 'size:512'];
starts_with:foo,bar,...
Поле, що валідується, має починатися з одного з переданих значень.
string
Поле, що валідується, має бути рядком. Якщо ви хочете дозволити полю бути також null, призначте йому правило nullable.
Для зручності правила валідації рядків можна також будувати плинним конструктором Rule::string():
use Illuminate\Validation\Rule;
'title' => [
'required',
Rule::string()
->min(3)
->max(255)
->alphaDash(ascii: true),
],
Конструктор рядкових правил надає методи для поширених обмежень, зокрема alpha, alphaDash, alphaNumeric, ascii, between, doesntEndWith, doesntStartWith, endsWith, exactly, lowercase, max, min, startsWith та uppercase. Оскільки конструктор підтримує умови, ви можете також скористатися методами when та unless, щоб застосовувати обмеження умовно.
timezone
Поле, що валідується, має бути дійсним ідентифікатором часового поясу згідно з методом DateTimeZone::listIdentifiers.
Аргументи, які приймає метод DateTimeZone::listIdentifiers, можна також передати цьому правилу валідації:
'timezone' => ['required', 'timezone:all'];
'timezone' => ['required', 'timezone:Africa'];
'timezone' => ['required', 'timezone:per_country,US'];
unique:table,column
Поле, що валідується, не має існувати у вказаній таблиці бази даних.
Указання власного імені таблиці чи колонки:
Замість указувати ім'я таблиці напряму, ви можете вказати модель Eloquent, за якою буде визначено ім'я таблиці:
'email' => ['unique:App\Models\User,email_address']
Опція column дозволяє вказати відповідну колонку бази даних для поля. Якщо її не вказано, буде використано ім'я поля, що валідується.
'email' => ['unique:users,email_address']
Указання власного підключення до бази даних
Подекуди вам може знадобитися задати власне підключення для запитів, які робить валідатор. Це робиться додаванням імені підключення перед іменем таблиці:
'email' => ['unique:connection.users,email_address']
Змушення правила Unique ігнорувати певний ID:
Іноді ви можете захотіти ігнорувати певний ідентифікатор під час перевірки унікальності. Наприклад, розгляньмо екран «оновлення профілю», що містить ім'я користувача, адресу електронної пошти та місцезнаходження. Ви, імовірно, захочете перевірити унікальність адреси. Однак якщо користувач змінює лише поле імені, а не адреси, ви не хочете, щоб виникала помилка валідації, адже користувач уже є власником цієї адреси.
Щоб вказати валідатору ігнорувати ідентифікатор користувача, скористаємося класом Rule для плинного визначення правила.
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::unique('users')->ignore($user->id),
],
]);
Ніколи не передавайте методу
ignoreвхідні дані запиту, які контролює користувач. Натомість передавайте лише згенерований системою унікальний ідентифікатор - як-от автоінкрементний ID чи UUID з екземпляра моделі Eloquent. Інакше ваш застосунок стане вразливим до SQL-ін'єкцій.
Замість передавати методу ignore значення ключа моделі, ви можете передати весь екземпляр моделі. Laravel автоматично витягне з неї ключ:
Rule::unique('users')->ignore($user)
Якщо ваша таблиця використовує ім'я колонки первинного ключа, відмінне від id, ви можете вказати його під час виклику методу ignore:
Rule::unique('users')->ignore($user->id, 'user_id')
За замовчуванням правило unique перевіряє унікальність колонки, ім'я якої збігається з іменем атрибута, що валідується. Утім, ви можете передати інше ім'я колонки другим аргументом методу unique:
Rule::unique('users', 'email_address')->ignore($user->id)
Додавання додаткових умов Where:
Ви можете вказати додаткові умови запиту, налаштувавши його методом where. Наприклад, додаймо умову, що обмежує запит записами зі значенням колонки account_id, рівним 1:
'email' => Rule::unique('users')->where(fn (Builder $query) => $query->where('account_id', 1))
Ігнорування м'яко видалених записів під час перевірки унікальності:
За замовчуванням правило unique враховує м'яко видалені записи, визначаючи унікальність. Щоб виключити їх із перевірки, викличте метод withoutTrashed:
Rule::unique('users')->withoutTrashed();
Якщо ваша модель використовує для м'яко видалених записів колонку з іменем, відмінним від deleted_at, вкажіть її під час виклику withoutTrashed:
Rule::unique('users')->withoutTrashed('was_deleted_at');
uppercase
Поле, що валідується, має бути у верхньому регістрі.
url
Поле, що валідується, має бути дійсним URL.
Якщо ви хочете вказати протоколи URL, які слід вважати дійсними, передайте їх як параметри правила валідації:
'url' => ['url:http,https'],
'game' => ['url:minecraft,steam'],
ulid
Поле, що валідується, має бути дійсним універсально унікальним лексикографічно сортованим ідентифікатором (ULID).
uuid
Поле, що валідується, має бути дійсним універсально унікальним ідентифікатором (UUID) за RFC 9562 (версії 1, 3, 4, 5, 6, 7 чи 8).
Ви також можете перевірити, що переданий UUID відповідає специфікації UUID за версією:
'uuid' => ['uuid:4']
Умовне додавання правил
Пропуск валідації, коли поля мають певні значення
Подекуди ви можете захотіти не валідувати певне поле, якщо інше поле має певне значення. Це робиться правилом exclude_if. У цьому прикладі поля appointment_date та doctor_name не валідуватимуться, якщо поле has_appointment має значення false:
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($data, [
'has_appointment' => ['required', 'boolean'],
'appointment_date' => ['exclude_if:has_appointment,false', 'required', 'date'],
'doctor_name' => ['exclude_if:has_appointment,false', 'required', 'string'],
]);
Як альтернативу ви можете скористатися правилом exclude_unless, щоб не валідувати поле, якщо тільки інше поле не має певного значення:
$validator = Validator::make($data, [
'has_appointment' => ['required', 'boolean'],
'appointment_date' => ['exclude_unless:has_appointment,true', 'required', 'date'],
'doctor_name' => ['exclude_unless:has_appointment,true', 'required', 'string'],
]);
Валідація за наявності
У деяких ситуаціях ви можете захотіти виконувати перевірки для поля лише тоді, коли воно присутнє у даних, що валідуються. Щоб швидко цього досягти, додайте до списку правило sometimes:
$validator = Validator::make($data, [
'email' => ['sometimes', 'required', 'email'],
]);
У прикладі вище поле email валідуватиметься лише тоді, коли воно присутнє в масиві $data.
Якщо ви намагаєтеся валідувати поле, яке має бути присутнім завжди, але може бути порожнім, перегляньте зауваження про необов'язкові поля.
Складна умовна валідація
Іноді ви можете захотіти додавати правила валідації на основі складнішої умовної логіки. Наприклад, ви можете зробити поле обов'язковим лише тоді, коли інше поле має значення більше за 100. Або вам можуть знадобитися два поля з певним значенням лише тоді, коли присутнє інше поле. Додавати такі правила не обов'язково болісно. Спершу створіть екземпляр Validator зі статичними правилами, які ніколи не змінюються:
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($request->all(), [
'email' => ['required', 'email'],
'games' => ['required', 'integer', 'min:0'],
]);
Припустімо, наш веб-застосунок призначений для колекціонерів ігор. Якщо колекціонер реєструється в нашому застосунку і має понад 100 ігор, ми хочемо, щоб він пояснив, чому їх так багато. Наприклад, можливо, він тримає магазин перепродажу ігор, а може, просто любить їх колекціонувати. Щоб додати цю вимогу умовно, ми можемо скористатися методом sometimes екземпляра Validator.
use Illuminate\Support\Fluent;
$validator->sometimes('reason', ['required', 'max:500'], function (Fluent $input) {
return $input->games >= 100;
});
Перший аргумент, переданий методу sometimes, - ім'я поля, яке ми валідуємо умовно. Другий - список правил, які хочемо додати. Якщо замикання, передане третім аргументом, повертає true, правила буде додано. Цей метод дозволяє легко будувати складні умовні перевірки. Ви можете навіть додавати умовні перевірки одразу для кількох полів:
$validator->sometimes(['reason', 'cost'], 'required', function (Fluent $input) {
return $input->games >= 100;
});
Параметр
$input, переданий вашому замиканню, буде екземпляромIlluminate\Support\Fluentі дозволить звертатися до ваших вхідних даних і файлів, що валідуються.
Складна умовна валідація масивів
Іноді ви можете захотіти валідувати поле на основі іншого поля в тому самому вкладеному масиві, індексу якого не знаєте. У таких ситуаціях ви можете дозволити своєму замиканню приймати другий аргумент - поточний елемент масиву, що валідується:
$input = [
'channels' => [
[
'type' => 'email',
'address' => 'abigail@example.com',
],
[
'type' => 'url',
'address' => 'https://example.com',
],
],
];
$validator->sometimes('channels.*.address', 'email', function (Fluent $input, Fluent $item) {
return $item->type === 'email';
});
$validator->sometimes('channels.*.address', 'url', function (Fluent $input, Fluent $item) {
return $item->type !== 'email';
});
Як і параметр $input, параметр $item є екземпляром Illuminate\Support\Fluent, коли дані атрибута є масивом; інакше це рядок.
Валідація масивів
Як зазначено в документації правила array, правило array приймає список дозволених ключів масиву. Якщо в масиві присутні будь-які додаткові ключі, валідація не пройде:
use Illuminate\Support\Facades\Validator;
$input = [
'user' => [
'name' => 'Taylor Otwell',
'username' => 'taylorotwell',
'admin' => true,
],
];
Validator::make($input, [
'user' => ['array:name,username'],
]);
Загалом вам слід завжди вказувати ключі масиву, які дозволено в ньому мати. Інакше методи validate та validated валідатора повернуть усі валідовані дані, зокрема масив і всі його ключі, навіть якщо ці ключі не валідувалися іншими правилами.
Валідація вкладених масивів
Валідація вкладених полів форми на основі масивів не обов'язково болісна. Ви можете скористатися «крапковою нотацією», щоб валідувати атрибути всередині масиву. Наприклад, якщо вхідний HTTP-запит містить поле photos[profile], ви можете валідувати його так:
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($request->all(), [
'photos.profile' => ['required', 'image'],
]);
Ви також можете валідувати кожен елемент масиву. Наприклад, щоб перевірити унікальність кожної адреси електронної пошти в масиві, зробіть так:
$validator = Validator::make($request->all(), [
'users.*.email' => ['email', 'unique:users'],
'users.*.first_name' => ['required_with:users.*.last_name'],
]);
Так само ви можете використовувати символ *, указуючи власні повідомлення валідації у мовних файлах, що дозволяє легко застосувати одне повідомлення до полів-масивів:
'custom' => [
'users.*.email' => [
'unique' => 'Each user must have a unique email address',
]
],
Доступ до даних вкладеного масиву
Іноді вам може знадобитися звернутися до значення певного елемента вкладеного масиву, призначаючи атрибуту правила валідації. Це робиться методом Rule::forEach. Метод forEach приймає замикання, яке буде викликано для кожної ітерації атрибута-масиву й отримає значення атрибута та його явне повне ім'я. Замикання має повертати масив правил для цього елемента:
use App\Rules\HasPermission;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
$validator = Validator::make($request->all(), [
'companies.*.id' => Rule::forEach(function (string|null $value, string $attribute) {
return [
Rule::exists(Company::class, 'id'),
new HasPermission('manage-company', $value),
];
}),
]);
Індекси та позиції в повідомленнях про помилки
Валідуючи масиви, ви можете захотіти послатися в повідомленні про помилку на індекс чи позицію конкретного елемента, який не пройшов валідацію. Для цього включіть у своє власне повідомлення заповнювачі :index (починається з 0), :position (починається з 1) чи :ordinal-position (починається з 1st):
use Illuminate\Support\Facades\Validator;
$input = [
'photos' => [
[
'name' => 'BeachVacation.jpg',
'description' => 'A photo of my beach vacation!',
],
[
'name' => 'GrandCanyon.jpg',
'description' => '',
],
],
];
Validator::validate($input, [
'photos.*.description' => ['required'],
], [
'photos.*.description.required' => 'Please describe photo #:position.',
]);
З наведеним вище прикладом валідація не пройде, і користувач побачить помилку «Please describe photo #2.»
За потреби ви можете посилатися на глибше вкладені індекси та позиції через second-index, second-position, third-index, third-position тощо.
'photos.*.attributes.*.string' => 'Invalid attribute for photo #:second-position.',
Валідація файлів
Laravel надає різноманітні правила валідації для завантажених файлів - як-от mimes, image, min і max. Хоча ви вільні вказувати ці правила окремо, Laravel також пропонує плинний конструктор правил валідації файлів, який може здатися вам зручним:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\File;
Validator::validate($input, [
'attachment' => [
'required',
File::types(['mp3', 'wav'])
->min(1024)
->max(12 * 1024),
],
]);
Валідація типів файлів
Хоча під час виклику методу types вам потрібно вказати лише розширення, цей метод насправді перевіряє MIME-тип файлу, читаючи його вміст і вгадуючи тип. Повний перелік MIME-типів та відповідних їм розширень можна знайти тут:
https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
Валідація розмірів файлів
Для зручності мінімальний і максимальний розміри файлу можна вказати рядком із суфіксом одиниць. Підтримуються суфікси kb, mb, gb і tb:
File::types(['mp3', 'wav'])
->min('1kb')
->max('10mb');
Валідація файлів зображень
Якщо ваш застосунок приймає зображення, завантажені користувачами, ви можете скористатися конструктором image правила File, щоб переконатися, що файл є зображенням (jpg, jpeg, png, bmp, gif чи webp).
Крім того, правило dimensions дозволяє обмежити розміри зображення:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\File;
Validator::validate($input, [
'photo' => [
'required',
File::image()
->min(1024)
->max(12 * 1024)
->dimensions(Rule::dimensions()->maxWidth(1000)->maxHeight(500)),
],
]);
Докладніше про валідацію розмірів зображень читайте в документації правила dimensions.
За замовчуванням правило
imageне дозволяє файли SVG через можливість XSS-вразливостей. Якщо вам потрібно дозволити SVG, передайте правилуimageпараметрallowSvg: true:File::image(allowSvg: true).
Валідація розмірів зображень
Ви також можете валідувати розміри зображення. Наприклад, щоб перевірити, що завантажене зображення має ширину щонайменше 1000 пікселів і висоту 500 пікселів, скористайтеся правилом dimensions:
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\File;
File::image()->dimensions(
Rule::dimensions()
->maxWidth(1000)
->maxHeight(500)
)
Докладніше про валідацію розмірів зображень читайте в документації правила dimensions.
Валідація паролів
Щоб переконатися, що паролі мають достатній рівень складності, скористайтеся об'єктом правила Password від Laravel:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\Password;
$validator = Validator::make($request->all(), [
'password' => ['required', 'confirmed', Password::min(8)],
]);
Об'єкт правила Password дозволяє легко налаштувати вимоги до складності паролів у вашому застосунку - наприклад, вказати, що пароль має містити щонайменше одну літеру, цифру, символ чи літери різного регістру:
// Require at least 8 characters...
Password::min(8)
// Require at least one letter...
Password::min(8)->letters()
// Require at least one uppercase and one lowercase letter...
Password::min(8)->mixedCase()
// Require at least one number...
Password::min(8)->numbers()
// Require at least one symbol...
Password::min(8)->symbols()
Крім того, ви можете переконатися, що пароль не було скомпрометовано в публічному витоку даних, за допомогою методу uncompromised:
Password::min(8)->uncompromised()
Внутрішньо об'єкт правила Password використовує модель k-анонімності, щоб визначити, чи пароль витік, через сервіс haveibeenpwned.com, не жертвуючи приватністю чи безпекою користувача.
За замовчуванням, якщо пароль з'являється у витоку даних хоча б раз, він вважається скомпрометованим. Ви можете налаштувати цей поріг першим аргументом методу uncompromised:
// Ensure the password appears less than 3 times in the same data leak...
Password::min(8)->uncompromised(3);
Звісно, ви можете об'єднати всі методи з наведених вище прикладів у ланцюжок:
Password::min(8)
->letters()
->mixedCase()
->numbers()
->symbols()
->uncompromised()
Ви можете перетворити об'єкт правила Password на рядок, придатний для HTML-атрибута passwordrules, методом toPasswordRulesString:
<input
type="password"
name="password"
autocomplete="new-password"
passwordrules="{{ Password::defaults()->toPasswordRulesString() }}"
/>
Визначення типових правил для паролів
Вам може бути зручно вказати типові правила валідації паролів в одному місці застосунку. Це легко зробити методом Password::defaults, який приймає замикання. Замикання, передане методу defaults, має повертати типову конфігурацію правила Password. Зазвичай defaults слід викликати в методі boot одного із сервіс-провайдерів вашого застосунку:
use Illuminate\Validation\Rules\Password;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Password::defaults(function () {
$rule = Password::min(8);
return $this->app->isProduction()
? $rule->mixedCase()->uncompromised()
: $rule;
});
}
Далі, коли ви захочете застосувати типові правила до конкретного пароля, викличте метод defaults без аргументів:
'password' => ['required', Password::defaults()],
Подекуди ви можете захотіти приєднати до типових правил валідації паролів додаткові правила. Це робиться методом rules:
use App\Rules\ZxcvbnRule;
Password::defaults(function () {
$rule = Password::min(8)->rules([new ZxcvbnRule]);
// ...
});
Власні правила валідації
Використання об'єктів правил
Laravel надає різноманітні корисні правила валідації; утім, ви можете захотіти визначити власні. Один зі способів зареєструвати власні правила - використати об'єкти правил. Щоб згенерувати новий об'єкт правила, скористайтеся командою Artisan make:rule. Скористаймося цією командою, щоб згенерувати правило, яке перевіряє, що рядок записано у верхньому регістрі. Laravel помістить нове правило в каталог app/Rules. Якщо цього каталогу немає, Laravel створить його під час виконання команди:
php artisan make:rule Uppercase
Щойно правило створено, ми готові визначити його поведінку. Об'єкт правила містить єдиний метод validate. Він отримує ім'я атрибута, його значення та колбек, який слід викликати в разі невдачі з повідомленням про помилку:
<?php
namespace App\Rules;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class Uppercase implements ValidationRule
{
/**
* Run the validation rule.
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (strtoupper($value) !== $value) {
$fail('The :attribute must be uppercase.');
}
}
}
Щойно правило визначено, ви можете приєднати його до валідатора, передавши екземпляр об'єкта правила разом з іншими правилами:
use App\Rules\Uppercase;
$request->validate([
'name' => ['required', 'string', new Uppercase],
]);
Переклад повідомлень валідації
Замість передавати замиканню $fail буквальне повідомлення про помилку, ви можете передати ключ рядка перекладу і вказати Laravel перекласти повідомлення:
if (strtoupper($value) !== $value) {
$fail('validation.uppercase')->translate();
}
За потреби ви можете передати заміни заповнювачів і бажану мову першим і другим аргументами методу translate:
$fail('validation.location')->translate([
'value' => $this->value,
], 'fr');
Доступ до додаткових даних
Якщо вашому класу власного правила потрібен доступ до всіх інших даних, що валідуються, він може реалізувати інтерфейс Illuminate\Contracts\Validation\DataAwareRule. Цей інтерфейс вимагає, щоб ваш клас визначив метод setData. Laravel автоматично викличе його (перед початком валідації) з усіма даними, що валідуються:
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\DataAwareRule;
use Illuminate\Contracts\Validation\ValidationRule;
class Uppercase implements DataAwareRule, ValidationRule
{
/**
* All of the data under validation.
*
* @var array<string, mixed>
*/
protected $data = [];
// ...
/**
* Set the data under validation.
*
* @param array<string, mixed> $data
*/
public function setData(array $data): static
{
$this->data = $data;
return $this;
}
}
Або, якщо вашому правилу потрібен доступ до екземпляра валідатора, що виконує валідацію, реалізуйте інтерфейс ValidatorAwareRule:
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Contracts\Validation\ValidatorAwareRule;
use Illuminate\Validation\Validator;
class Uppercase implements ValidationRule, ValidatorAwareRule
{
/**
* The validator instance.
*
* @var \Illuminate\Validation\Validator
*/
protected $validator;
// ...
/**
* Set the current validator.
*/
public function setValidator(Validator $validator): static
{
$this->validator = $validator;
return $this;
}
}
Використання замикань
Якщо функціональність власного правила потрібна вам у застосунку лише раз, ви можете скористатися замиканням замість об'єкта правила. Замикання отримує ім'я атрибута, його значення та колбек $fail, який слід викликати, якщо валідація не пройшла:
use Illuminate\Support\Facades\Validator;
use Closure;
$validator = Validator::make($request->all(), [
'title' => [
'required',
'max:255',
function (string $attribute, mixed $value, Closure $fail) {
if ($value === 'foo') {
$fail("The {$attribute} is invalid.");
}
},
],
]);
Неявні правила
За замовчуванням, коли атрибут, що валідується, відсутній або містить порожній рядок, звичайні правила валідації - зокрема власні - не виконуються. Наприклад, правило unique не виконуватиметься для порожнього рядка:
use Illuminate\Support\Facades\Validator;
$rules = ['name' => ['unique:users,name']];
$input = ['name' => ''];
Validator::make($input, $rules)->passes(); // true
Щоб власне правило виконувалося навіть тоді, коли атрибут порожній, правило має неявно вказувати, що атрибут обов'язковий. Щоб швидко згенерувати новий об'єкт неявного правила, скористайтеся командою Artisan make:rule з опцією --implicit:
php artisan make:rule Uppercase --implicit
«Неявне» правило лише натякає, що атрибут обов'язковий. Чи справді воно відхилятиме відсутній чи порожній атрибут - вирішувати вам.