- Введение
- Быстрый старт
- Валидация в классах Form Request
- Мануал по созданию валидаций
- Работа с сообщениями об ошибках
- Доступные правила валидации
- Добавление правил с условиями
- Валидация массивов
- Собственные правила валидации
Laravel предоставляет несколько способов для валидации входящих данных. По умолчанию базовый контроллер использует трейт ValidatesRequests
, который обеспечивает удобный способ валидации HTTP запросов c большим количеством правил.
Перед тем как узнать обо всех функциях, давайте рассмотрим полный пример валидации формы и вывод сообщений об ошибках для пользователя.
Во первых, представим что мы имеем следующие маршруты в файле routes/web.php
:
Route::get('post/create', 'PostController@create');
Route::post('post', 'PostController@store');
Как видно маршрут GET
отображает форму для создания нового поста в блоге, в то время как POST
будет сохранять новую запись в базе данных.
Посмотрим на простой контроллер, который обрабатывает эти маршруты. Метод store
оставим пустым:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PostController extends Controller
{
/**
* Show the form to create a new blog post.
*
* @return Response
*/
public function create()
{
return view('post.create');
}
/**
* Store a new blog post.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
// Validate and store the blog post...
}
}
Теперь мы готовы заполнить метод store
валидацией при создания нового поста. Если проанализировать базовый контроллер (App\Http\Controllers\Controller
), вы заметите, что он включает в себя трейт ValidatesRequests
, который обеспечивает все контроллеры удобным методом validate
.
Метод validate
принимает два параметра экземпляр HTTP запроса и правила валидации. Если все правила не нарушены, код будет выполняться далее. Однако, если проверка не пройдена, будет выброшено исключение и сообщение об ошибке автоматически отправится обратно пользователю. По традициям HTTP запроса, ответ будет перенаправлен обратно с заполненными flash-переменными, в то время как на AJAX запрос отправится JSON.
Для лучшего понимания метода validate
, вернемся обратно к store
:
/**
* Store a new blog post.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$this->validate($request, [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
// The blog post is valid, store in database...
}
Как видно, мы передаем экземпляр с данными HTTP запроса и правила валидации в метод validate
. Помните, что если проверка завершится неудачей, будет автоматически сгенерирован ответ с сообщением об ошибках, иначе ваш контроллер продолжит работать.
Иногда нужно остановить выполнение остальных правил после первой неудачной проверки. Для этого используется атрибут bail
:
$this->validate($request, [
'title' => 'bail|required|unique:posts|max:255',
'body' => 'required',
]);
В этом примере, если для атрибута title
не выполняется правило required
, следующие правило unique
проверяться не будет. Правила выполняются именно в той последовательности, в какой они назначаются.
Если данные HTTP запроса содержат «вложенные» параметры, можно указать их, используя dot-синтаксис:
$this->validate($request, [
'title' => 'required|unique:posts|max:255',
'author.name' => 'required',
'author.description' => 'required',
]);
Что, если входящие данные не проходят проверку с учетом правил? Как упоминалось ранее, Laravel автоматически перенаправляет пользователя на предыдущую страницу. Кроме того, все ошибки валидации будут автоматически записаны во flash-переменные.
Опять же, обратите внимание, что мы не должны явно передавать сообщения об ошибках в представлении маршрута GET
. Это потому, что Laravel будет проверять наличие ошибок в текущем сеансе и автоматически привязывать их к представлению, если они доступны. Переменная $errors
является экземпляром Illuminate\Support\MessageBag
. Для получения дополнительных сведений о работе с этим объектом, смотрите в документации.
{tip} Переменная
$errors
привязана к посредникуIlluminate\View\Middleware\ShareErrorsFromSession
, который входит в группу посредниковweb
. При использовании этого посредника,$errors
всегда будет доступна в ваших представлениях, что позволяет удобно и безопасно ее использовать.
В нашем примере пользователь будет перенаправлен в метод create
вашего контроллера и можно отобразить сообщения об ошибках в представлении:
<!-- /resources/views/post/create.blade.php -->
<h1>Create Post</h1>
@if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<!-- Create Post Form -->
По умолчанию в Laravel включены глобальные посредники TrimStrings
и ConvertEmptyStringsToNull
. Они перечислены в свойстве $middleware
класса App\Http\Kernel
. Из-за этого нужно часто помечать дополнительные поля, как nullable
, если не нужно, чтобы валидатор считал не действительным значение null
. Например:
$this->validate($request, [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
'publish_at' => 'nullable|date',
]);
В этом примере мы указываем что поле publish_at
может быть null
или должно содержать дату. Если модификатор nullable
не добавляется в правило, проверяющий элемент будет рассматривать null
как недопустимую дату.
Если вы хотите настроить вывод ошибок валидации, которые будут во flash-переменных после нарушений правил, переопределите метод formatValidationErrors
в базовом контроллере. Не забудьте подключить класс Illuminate\Contracts\Validation\Validator
:
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
abstract class Controller extends BaseController
{
use DispatchesJobs, ValidatesRequests;
/**
* {@inheritdoc}
*/
protected function formatValidationErrors(Validator $validator)
{
return $validator->errors()->all();
}
}
В последнем примере мы использовали традиционные формы для отправки данных в наше приложение. Однако многие приложения используют AJAX-запросы. При использовании метода validate
во время запроса AJAX, Laravel не будет генерировать ответ с перенаправлением. Вместо этого Laravel генерирует ответ с JSON данными, содержащий в себе все ошибки проверки. Этот ответ будет отправлен с кодом состояния HTTP 422.
Для более сложных сценариев валидаций, будут более удобны Form Requests
. Form Requests это специальные классы, которые содержат в себе логику проверки. Для создания класса, используйте artisan-команду make:request
:
php artisan make:request StoreBlogPost
Сгенерированный класс будет размещен в каталоге app/Http/Requests
. Если этот каталог не существует, он будет создан. Давайте добавим несколько правил проверки в метод rules
:
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
];
}
Ккак же здесь работают правила валидации? Все, что нужно сделать — это указать класс Form Request в аргументах метода вашего контроллера. Входящий запрос перед вызовом метода контроллера будет валидироваться автоматически, что позволит загромождать контроллер логикой валидации:
/**
* Store the incoming blog post.
*
* @param StoreBlogPost $request
* @return Response
*/
public function store(StoreBlogPost $request)
{
// The incoming request is valid...
}
Если проверка не пройдена, то при традиционном запросе ошибки будут записываться в сессию и будут доступны в представлениях, иначе, если запрос был AJAX, HTTP-ответ с кодом 422 будет возвращен пользователю, включая JSON с ошибками валидации.
Если вы хотите добавить хук «after» в Form Requests, можно использовать метод withValidator
. Этот метод получает полностью сформированный валидатор, позволяя вызвать любой из его методов, прежде чем фактически применяются правила:
/**
* Configure the validator instance.
*
* @param \Illuminate\Validation\Validator $validator
* @return void
*/
public function withValidator($validator)
{
$validator->after(function ($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add('field', 'Something is wrong with this field!');
}
});
}
Класс Form Request содержит в себе метод authorize
. В этом методе можно проверить, имеет ли аутентифицированный пользователь права на выполнение данного запроса. Например, можно проверить, есть ли у пользователя право для добавления комментариев в блог:
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
$comment = Comment::find($this->route('comment'));
return $comment && $this->user()->can('update', $comment);
}
Так как все Form Request расширяют базовый класс Request, мы можем использовать метод user
, чтобы получить доступ к текущему пользователю.Так же обратите внимание на вызов метода route
. Этот метод предоставляет доступ к параметрам URI , определенным в маршруте (в приведенном ниже примере это {comment}
):
Route::post('comment/{comment}');
Если метод authorize
возвращает false
, автоматически генерируется ответ с кодом 403 и метод контроллера не выполняется.
Иначе, если логику авторизации организована в другом месте вашего приложения, просто верните true
из метода authorize
:
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
Если вы хотите настроить формат вывода ошибок валидации, которые будут заполнять flash-переменные при неудачном выполнении, переопредилите метод formatErrors
в вашем базовом request (App\Http\Requests\Request
). И не забывайте подключить класс Illuminate\Contracts\Validation\Validator
:
/**
* {@inheritdoc}
*/
protected function formatErrors(Validator $validator)
{
return $validator->errors()->all();
}
Вы можете кастомизировать сообщения об ошибках, используя в form request метод messages
. Этот метод должен возвращать массив атрибутов/правил и их соответствующие сообщения об ошибках:
/**
* Get the error messages for the defined validation rules.
*
* @return array
*/
public function messages()
{
return [
'title.required' => 'A title is required',
'body.required' => 'A message is required',
];
}
Если вы не хотите использовать трейт ValidatesRequests
и его метод validate
, можно создать экземпляр валидатора вручную с помощью фасада Validator
, используя метод make
:
<?php
namespace App\Http\Controllers;
use Validator;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PostController extends Controller
{
/**
* Store a new blog post.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
if ($validator->fails()) {
return redirect('post/create')
->withErrors($validator)
->withInput();
}
// Store the blog post...
}
}
Первый аргумент, передаваемый в метод make
, получает данные для проверки. Вторым аргументом идут правилами проверки, которые должны применяться к данным.
После проверки, если валидация не будет пройдена, вы можете использовать метод withErrors
для загрузки ошибок во flash-переменные. При использовании этого метода переменная $errors
будет автоматически передаваться в ваши представления, после перенаправления, что позволяет легко отображать данные пользователю. Метод withErrors
принимает экземпляр валидатора и MessageBag
или простой массив.
Если вы хотите создать экземпляр валидации вручную, но все же воспользоваться автоматической переадресацией трейта ValidatesRequest
, можно вызвать метод validate
в существующим экземпляре. После того, как проверка терпит неудачу, пользователь будет автоматически перенаправляться, в случае с AJAX-запросом, как и ранее в ответ отправится JSON:
Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
])->validate();
Если у вас есть несколько форм на одной странице, которые необходимо провалидировать, вам понадобится MessageBag
— он позволяет получать сообщения об ошибках для определенной формы. Просто передайте имя в качестве второго аргумента withErrors
:
return redirect('register')
->withErrors($validator, 'login');
Затем можно получить доступ к именованному экземпляру MessageBag
из переменной $errors
:
{{ $errors->login->first('email') }}
Валидатор также позволяет вам использовать функции обратного вызова после завершения всех проверок. Это позволяет легко выполнять дальнейшие проверки и даже добавить больше сообщений об ошибках в коллекции сообщений. Чтобы начать работу, используйте метод after
валидатора:
$validator = Validator::make(...);
$validator->after(function ($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add('field', 'Something is wrong with this field!');
}
});
if ($validator->fails()) {
//
}
После вызова метода errors
в экземпляре валидатора, вы получаете экземпляр 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')) {
//
}
При необходимости, вы можете использовать свои сообщения об ошибках вместо значений по умолчанию. Существует несколько способов для указания кастомных сообщений. Во-первых, можно передать сообщения в качестве третьего аргумента в метод Validator::make
:
$messages = [
'required' => 'The :attribute field is required.',
];
$validator = Validator::make($input, $rules, $messages);
В этом примере :attribute
будет заменен на имя проверяемого поля. Вы также можете использовать и другие строки-переменные. Пример:
$messages = [
'same' => 'The :attribute and :other must match.',
'size' => 'The :attribute must be exactly :size.',
'between' => 'The :attribute must be between :min - :max.',
'in' => 'The :attribute must be one of the following types: :values',
];
Иногда есть необходимость указать собственное сообщение для конкретного поля, это можно сделать с помощью dot-синтаксиса. Просто укажите имя атрибута и текст сообщения:
$messages = [
'email.required' => 'We need to know your e-mail address!',
];
Также можно определять сообщения в файле локализации вместо того, чтобы передавать их в валидатор напрямую. Для этого добавьте сообщения в массив custom
файла локализации resources/lang/xx/validation.php
.
'custom' => [
'email' => [
'required' => 'We need to know your e-mail address!',
],
],
Если вы хотите, чтобы :attribute
был заменен на кастомное имя, можно указать в массиве attributes
файле локализации resources/lang/xx/validation.php
'attributes' => [
'email' => 'email address',
],
Ниже список всех доступных правил и их функции:
<style> .collection-method-list > p { column-count: 3; -moz-column-count: 3; -webkit-column-count: 3; column-gap: 2em; -moz-column-gap: 2em; -webkit-column-gap: 2em; } .collection-method-list a { display: block; } </style>Accepted Active URL After (Date) After Or Equal (Date) Alpha Alpha Dash Alpha Numeric Array Before (Date) Before Or Equal (Date) Between Boolean Confirmed Date Date Format Different Digits Digits Between Dimensions (Image Files) Distinct E-Mail Exists (Database) File Filled Image (File) In In Array Integer IP Address JSON Max MIME Types MIME Type By File Extension Min Nullable Not In Numeric Present Regular Expression Required Required If Required Unless Required With Required With All Required Without Required Without All Same Size String Timezone Unique (Database) URL
Поле должно быть в значении yes
, on
или 1
. Это полезно для проверки принятия правил и лицензий.
Поле должно иметь действительную A или AAAA DNS-запись согласно функции PHP dns_get_record
.
Поле проверки должно быть после date. Строки приводятся к датам функцией strtotime
:
'start_date' => 'required|date|after:tomorrow'
Вместо того чтобы приводить строки к датам, вы можете указать другое поле для сравнения даты:
'finish_date' => 'required|date|after:start_date'
Поле проверки должно быть после или равно date. Для получения дополнительной информации смотрите правило after.
Поле можно содержать только алфавитные символы.
Поле можно содержать только алфавитные символы, цифры, знаки подчёркивания _
и дефисы -
.
Поле можно содержать только алфавитные символы и цифры.
Поле должно быть PHP-массивом.
Поле должно быть датой более ранней, чем date. Строки приводятся к датам функцией strtotime
.
Поле должно быть более ранней или равной date. Строки приводятся к датам функцией strtotime
.
Поле должно быть числом в диапазоне от min до max. Размеры строк, чисел и файлов трактуются аналогично правилу size
.
Поле должно быть логическим (булевым). Разрешенные значения: true
, false
, 1
, 0
, "1"
, и "0"
.
Значение поля должно соответствовать значению поля с этим именем, плюс foo_confirmation
. Например, если проверяется поле password
, то на вход должно быть передано совпадающее по значению поле password_confirmation
.
Поле должно быть правильной датой в соответствии с PHP функцией strtotime
.
Поле должно соответствовать заданному формату. Необходимо использовать функцию date
или date_format
при проверке поля, но не обе.
Значение проверяемого поля должно отличаться от значения поля field.
Поле должно быть числовым и иметь точную длину значения.
Длина значения поля проверки должна быть между min и max.
Файл изображения должен иметь ограничения согласно параметрам:
'avatar' => 'dimensions:min_width=100,min_height=200'
Доступные ограничения: min_width, max_width, min_height, max_height, width, height, ratio.
Ограничение ratio должно быть представлено как ширина к высоте. Это может быть обыкновенная (3/2
) или десятичная (1.5
) дробь:
'avatar' => 'dimensions:ratio=3/2'
Поскольку это правило требует несколько аргументов, вы можете использовать метод Rule::dimensions
:
use Illuminate\Validation\Rule;
Validator::make($data, [
'avatar' => [
'required',
Rule::dimensions()->maxWidth(1000)->maxHeight(500)->ratio(3 / 2),
],
]);
При работе с массивами, поле не должно иметь повторяющихся значений.
'foo.*.id' => 'distinct'
Поле должно быть корректным адресом e-mail.
Поле должно существовать в указанной таблице базы данных.
'state' => 'exists:states'
'state' => 'exists:states,abbreviation'
Иногда может потребоваться подключение к базе данных и использование в запросе exists
, этого можно добиться путем добавления к соединению название таблицы, используя dot-синтаксис:
'email' => 'exists:connection.staff,email'
Если бы вы хотите модифицировать запрос, можно использовать класс Rule
, в данном примере мы будем использовать массив вместо знака |
:
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::exists('staff')->where(function ($query) {
$query->where('account_id', 1);
}),
],
]);
Поле должно быть успешно загруженным файлом.
Поле проверки не должно быть пустым.
Загруженный файл должен быть в формате jpeg, png, bmp, gif или svg.
Значение поля должно быть одним из перечисленных. Поскольку это правило иногда вынуждает вас использовать функцию implode
, для этого случая есть метод Rule::in
:
use Illuminate\Validation\Rule;
Validator::make($data, [
'zones' => [
'required',
Rule::in(['first-zone', 'second-zone']),
],
]);
В массиве должны существовать значения anotherfield.
Поле должно иметь корректное целочисленное значение.
Поле должно быть корректным IP-адресом (v4 или v6).
Поле должно быть IPv4-адресом.
Поле должно быть IPv6-адресом.
Поле проверки должно быть каноничным JSON.
Значение поля должно быть меньше или равно value. Размеры строк, чисел и файлов трактуются аналогично правилу size
.
MIME-тип загруженного файла должен быть одним из перечисленных:
'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'
Чтобы определить MIME-тип загруженного файла, фреймворк будет читать содержимое и пытаться угадать MIME-тип, который может отличаться от того, что указал пользователь.
MIME-тип загруженного файла должен быть одним из перечисленных.
'photo' => 'mimes:jpeg,bmp,png'
Даже если необходимо только указать расширение, это правило проверяет MIME-тип файла, читая содержимое файла и пытаясь угадать его.
Полный список MIME-типов и соответствующие им расширения можно найти в https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types.
Значение поля должно быть больше value. Размеры строк, чисел и файлов трактуются аналогично правилу size
.
Поле проверки может быть равно null
. Это особенно полезно при проверке примитивов, такие как строки и целые числа, которые могут содержать null
значения.
Значение поля не должно быть одним из перечисленных (foo, bar и т.д.).
Поле должно иметь корректное числовое или дробное значение.
Поле для проверки должно присутствовать во входных данных, но может быть пустым.
Поле должно соответствовать заданному регулярному выражению.
Note: Использовании regex
может быть необходимо определить правила в виде массива вместо использования разделителя, особенно если регулярное выражение содержит символ разделителя.
Проверяемое поле должно иметь непустое значение. Поле считается пустым, если одно из следующих значений верно:
- Если значение равно
null
. - Если значение — пустая строка.
- Если значение является пустым массивом или пустым объектом
Countable
. - Если значение это загруженный файл без пути.
Поле должно присутствовать и не быть пустым, если anotherfield равно любому value.
Поле должно присутствовать и не быть пустым, за исключением случая, когда anotherfield равно любому value.
Проверяемое поле должно иметь непустое значение, но только если присутствует хотя бы одно из перечисленных полей (foo, bar и т.д.).
Проверяемое поле должно иметь непустое значение, но только если присутствуют все перечисленные поля (foo, bar и т.д.).
Проверяемое поле должно иметь непустое значение, но только если не присутствует хотя бы одно из перечисленных полей (foo, bar и т.д.).
Проверяемое поле должно иметь непустое значение, но только если не присутствуют все перечисленные поля (foo, bar и т.д.).
Поле должно иметь то же значение, что и поле field.
Поле должно иметь совпадающий с value размер. Для строковых данных value соответствует количество символов, для массива size соответствует количеству элементов массива, для чисел — число, для файлов — размер в килобайтах.
Поле должно быть строкой. Если вы хотите, чтобы поле было null
, следует доолнитель указать это полю правило nullable
.
Поле должно содержать идентификатор часового пояса (таймзоны), один из перечисленных в php-функции timezone_identifiers_list
.
Значение поля должно быть уникальным в заданной таблице базы данных. Если column
не указано, то будет использовано имя поля.
Название колонок:
'email' => 'unique:users,email_address'
Подключения к базе данных
Иногда вам может понадобиться установить собственное соединение с базой данных, как замечено выше, параметр unique:users
, будет использовать соединение по умолчанию. Чтобы переопределить это, укажите подключение и имя таблицы через dot-синтаксис:
'email' => 'unique:connection.users,email_address'
Игнорирование ID при проверке на уникальность:
Иногда потребуется игнорировать ID при проверке на уникальность. Например, рассмотрим обновление профиля пользователя, который включает в себя имя пользователя, адрес электронной почты и местоположение. Конечно, вы хотите убедиться, что адрес электронной почты является уникальным. Однако, если пользователь изменяет только имя и не изменяет электронную почту, нам не требуется вывод ошибки, но тем не менее возникнет исключение, поскольку пользователь уже является владельцем адреса электронной почты.
Для того, чтобы игнорировать ID пользователя, мы будем использовать класс Rule
который позволяет гибко строить наши правила в таком случае. В примере, мы укажем правила в качестве массива вместо |
символа-разделителя:
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::unique('users')->ignore($user->id),
],
]);
Если таблица использует имя столбца первичного ключа помимо id
, можно указать имя столбца при вызове метода ignore
:
'email' => Rule::unique('users')->ignore($user->id, 'user_id')
Добавление дополнительных условий:
Вы также можете указать дополнительные условия, используя метод where
. Например, давайте добавим ограничение, которое проверяет, что account_id
равно 1
:
'email' => Rule::unique('users')->where(function ($query) {
$query->where('account_id', 1);
})
Поле должно быть корректным URL.
Иногда вам нужно проверить некое поле только тогда, когда оно присутствует во входных данных. Для этого добавьте правило sometimes
:
$v = Validator::make($data, [
'email' => 'sometimes|required|email',
]);
В примере выше для поля email
будет запущена валидация только, когда оно присутствует в массиве $data
.
Иногда возникает необходимость добавить правила с более сложной логикой проверки. Например, потребовать поле, только если другое поле имеет значение большее, чем 100. Или понадобится два поля, когда другое поле присутствует. Добавление этих правил не должно вызывать затруднения. Во-первых, создайте экземпляр Validator
с вашими постоянными правилами, которые никогда не изменятся:
$v = Validator::make($data, [
'email' => 'required|email',
'games' => 'required|numeric',
]);
Давайте предположим, что наше веб-приложение для коллекционеров игр. Если коллекционер регистрирует в нашем приложении игру и он владеет больше чем 100 играми в данный момент, мы хотим, чтобы он объяснил, почему он владеет таким количеством игр. Возможно, он управляет магазином игр, или возможно, он просто любит их собирать. Чтобы добавить это требование, мы можем использовать метод sometimes
в экземпляре валидатора:
$v->sometimes('reason', 'required|max:500', function ($input) {
return $input->games >= 100;
});
Первый аргумент, переданный в метод sometimes
это имя поля, которое мы условно проверяем. Второй аргумент — правила, которые мы хотим добавить. Если анонимная функция передается как третий аргумент, и возвращает значение true
, то правила будут добавлены. Этот метод универсален для того, чтобы строить целый комплекс условных проверок. Вы можете даже добавить условные проверки на нескольких полях одновременно:
$v->sometimes(['reason', 'cost'], 'required', function ($input) {
return $input->games >= 100;
});
{tip} Параметр
$input
переданный в анонимную функцию, будет экземпляромIlluminate\Support\Fluent
и может быть использован для доступа к вашим полям и файлам.
Проверка массива полей из формы не должна вызывать затруднений. Например, чтобы проверить, что каждая последующая электронная почта является уникальной, вы можете сделать следующее:
$validator = Validator::make($request->all(), [
'person.*.email' => 'email|unique:users',
'person.*.first_name' => 'required_with:person.*.last_name',
]);
Кроме того, вы можете использовать символ *
в ваших языковых файлах, использовать одно сообщение для проверки массива полей:
'custom' => [
'person.*.email' => [
'unique' => 'Each person must have a unique e-mail address',
]
],
Laravel предоставляет разнообразные и полезные правила для валидации. Однако, возможно, вам потребуется определить некоторые из своих собственных. Один из методов регистрации своих правил метод extend
фасада
Validator
. Давайте зарегистрируем этот метод в сервис-провайдере
:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Validator::extend('foo', function ($attribute, $value, $parameters, $validator) {
return $value == 'foo';
});
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
//
}
}
Анонимная функция получает четыре аргумента: имя проверяемого поля ($attribute
), значение поля ($value
), массив дополнительных параметров ($parameters
) и экземпляр валидатора ($validator
).
Класс и метод также можно передать методу extend
вместо анонимной функции:
Validator::extend('foo', 'FooValidator@validate');
Необходимо будет также определить сообщение об ошибке для вашего правила. Вы можете сделать это, либо передавая его в виде массива строк в валидатор, либо добавив в файл локализации. Это сообщение должно помещаться на первом уровне массива, но не в массиве custom
, который появляется только для сообщения об ошибке конкретного атрибута:
"foo" => "Your input was invalid!",
"accepted" => "The :attribute must be accepted.",
// The rest of the validation error messages...
При создании своих правил проверки, может потребоваться определить места замены для сообщений об ошибках. Вы можете сделать это, реализовав через метод replacer
в фасаде Validator
. Действие необходимо определить внутри метода boot
сервис-провайдера
:
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Validator::extend(...);
Validator::replacer('foo', function ($message, $attribute, $rule, $parameters) {
return str_replace(...);
});
}
По умолчанию, когда проверяемый атрибут отсутствует или содержит пустое значение, как в правиле required
, валидация не выполняется, в том числе и для ваших расширений. Например, unique
не будет выполнено для значения null
:
$rules = ['name' => 'unique'];
$input = ['name' => null];
Validator::make($input, $rules)->passes(); // true
Правило должно подразумевать, что атрибут обязателен, даже, если он пуст. Для создания «скрытых» расширений используйте метод Validator::extendImplicit()
:
Validator::extendImplicit('foo', function ($attribute, $value, $parameters, $validator) {
return $value == 'foo';
});
{note} «Скрытое» расширение лишь подразумевает, что атрибут является обязательным. Будет ли это на самом деле недействительный или пустой атрибут, зависит только от вас.