Валидация
11.x
.
Почему это важно?
- Введение
- Быстрый старт
- Определение роутов
- Создание контроллера
- Написание логики валидации
- Отображение ошибок валидации
- Заметка о дополнительных полях
- Валидация Form Request
- Создание Form Request
- Авторизация Form Request
- Настройка формата вывода ошибок
- Настройка сообщений об ошибках
- Создание валидаторов вручную
- Автоматическое перенаправление
- MessageBag
- Хук после валидации
- Работа с сообщениями об ошибках
- Пользовательские сообщения об ошибках
- Доступные правила валидации
- Добавление правил с условиями
- Валидация массивов
- Собственные правила валидации
Введение
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
{
/**
* Показать форму для создания новой записи в блоге.
*
* @return Response
*/
public function create()
{
return view('post.create');
}
/**
* Хранить новую запись в блоге.
*
* @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|unique:posts|max:255',
'body' => 'required',
]);
В этом примере, если для атрибута title
не выполняется правило required
, следующие правило unique
проверяться не будет. Правила выполняются именно в той последовательности, в какой они назначаются.
Заметка о вложенных атрибутах
Если данные HTTP запроса содержат “вложенные” параметры, можно указать их, используя синтаксис с точкой:
$this->validate($request, [
'title' => 'required|unique:posts|max:255',
'author.name' => 'required',
'author.description' => 'required',
]);
Отображение ошибок валидации
Что, если входящие данные не проходят проверку с учетом правил? Как упоминалось ранее, Laravel автоматически перенаправляет пользователя на предыдущую страницу. Кроме того, все ошибки валидации будут автоматически записаны во flash-переменные.
Опять же, обратите внимание, что мы не должны явно передавать сообщения об ошибках в шаблоне роута GET
. Это потому, что Laravel будет проверять наличие ошибок в текущем сеансе и автоматически привязывать их к шаблону, если они доступны. Переменная $errors
является экземпляром Illuminate\Support\MessageBag
. Для получения дополнительных сведений о работе с этим объектом, смотрите в документации.
Переменная
$errors
привязана к посредникуIlluminate\View\Middleware\ShareErrorsFromSession
, который входит в группу посредниковweb
. При использовании этого посредника,$errors
всегда будет доступна в ваших шаблонах, что позволяет удобно и безопасно ее использовать.
В нашем примере пользователь будет перенаправлен в метод 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 включены глобальные посредники 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 запросы и валидация
В последнем примере мы использовали традиционные формы для отправки данных в наше приложение. Однако многие приложения используют AJAX-запросы. При использовании метода validate
во время запроса AJAX, Laravel не будет генерировать ответ с перенаправлением. Вместо этого Laravel генерирует ответ с JSON данными, содержащий в себе все ошибки проверки. Этот ответ будет отправлен с кодом состояния HTTP 422.
Валидация Form Request
Создание Form Request
Для более сложных сценариев валидаций, будут более удобны Form Requests
. Form Requests это специальные классы, которые содержат в себе логику проверки. Для создания класса, используйте artisan-команду make:request
:
php artisan make:request StoreBlogPost
Сгенерированный класс будет размещен в каталоге app/Http/Requests
. Если этот каталог не существует, он будет создан. Давайте добавим несколько правил проверки в метод rules
:
/**
* Получить правила валидации, применимые к запросу.
*
* @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 с ошибками валидации.
Добавление хуков в Form Request
Если вы хотите добавить хук “after” в Form Requests, можно использовать метод withValidator
. Этот метод получает полностью сформированный валидатор, позволяя вызвать любой из его методов, прежде чем фактически применяются правила:
/**
* Настройка экземпляра валидатора.
*
* @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
Класс Form Request содержит в себе метод authorize
. В этом методе можно проверить, имеет ли аутентифицированный пользователь права на выполнение данного запроса. Например, можно проверить, есть ли у пользователя право для добавления комментариев в блог:
/**
* Определить авторизован ли пользователь делать такой запрос.
*
* @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
:
/**
* Определить авторизован ли пользователь делать такой запрос.
*
* @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
Если у вас есть несколько форм на одной странице, которые необходимо провалидировать, вам понадобится MessageBag
— он позволяет получать сообщения об ошибках для определенной формы. Просто передайте имя в качестве второго аргумента withErrors
:
return redirect('register')
->withErrors($validator, 'login');
You may then access the named MessageBag
instance from the $errors
variable:
{{ $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',
];
Указание пользовательского сообщения для заданного атрибута
Иногда есть необходимость указать собственное сообщение для конкретного поля, это можно сделать с помощью синтаксиса с точкой. Просто укажите имя атрибута и текст сообщения:
$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',
],
Доступные правила валидации
Ниже приведен список всех доступных правил и их функции:
- 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
- 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
accepted
Поле должно быть в значении yes
, on
или 1
. Это полезно для проверки принятия правил и лицензий.
active_url
Поле должно иметь действительную A или AAAA DNS-запись согласно функции PHP dns_get_record
.
after:date
Поле проверки должно быть после date. Строки приводятся к датам функцией strtotime
:
'start_date' => 'required|date|after:tomorrow'
Вместо того чтобы приводить строки к датам, вы можете указать другое поле для сравнения даты:
'finish_date' => 'required|date|after:start_date'
after_or_equal:date
Поле проверки должно быть после или равно date. Для получения дополнительной информации смотрите правило after
alpha
Поле должно содержать только алфавитные символы.
alpha_dash
Поле можно содержать только алфавитные символы, цифры, знаки подчёркивания _
и дефисы -
.
alpha_num
Поле можно содержать только алфавитные символы и цифры.
array
Поле должно быть PHP-массивом.
before:date
Поле должно быть датой более ранней, чем заданная дата. Строки приводятся к датам функцией strtotime
.
before_or_equal:date
Поле должно быть более ранней или равной заданной дате. Строки приводятся к датам функцией strtotime
.
between:min,max
Поле должно быть числом в диапазоне от min до max. Размеры строк, чисел и файлов трактуются аналогично правилу size
.
boolean
Поле должно быть логическим (булевым). Разрешенные значения: true
, false
, 1
, 0
, "1"
, и "0"
.
confirmed
Значение поля должно соответствовать значению поля с этим именем, плюс foo_confirmation
. Например, если проверяется поле password
, то на вход должно быть передано совпадающее по значению поле password_confirmation
.
date
Поле должно быть правильной датой в соответствии с PHP функцией strtotime
.
date_format:format
Поле должно соответствовать заданному формату. Необходимо использовать функцию date
или date_format
при проверке поля, но не обе.
different:field
Значение проверяемого поля должно отличаться от значения поля field.
digits: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.
Ограничение 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),
],
]);
distinct
При работе с массивами, поле не должно иметь повторяющихся значений.
'foo.*.id' => 'distinct'
Поле должно быть корректным адресом e-mail.
exists:table,column
Поле должно существовать в указанной таблице базы данных.
Базовое использование правила Exists
'state' => 'exists:states'
Указание пользовательского названия столбца
'state' => 'exists:states,abbreviation'
Иногда может потребоваться подключение к базе данных и использование в запросе exists
, этого можно добиться путем добавления к соединению название таблицы, используя синтаксис с точкой:
'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);
}),
],
]);
file
Поле должно быть успешно загруженным файлом.
filled
Поле не должно быть пустым.
image
Загруженный файл должен быть в формате jpeg, png, bmp, gif или svg.
in:foo,bar,...
Значение поля должно быть одним из перечисленных. Поскольку это правило иногда вынуждает вас использовать функцию implode
, для этого случая есть метод Rule::in
:
use Illuminate\Validation\Rule;
Validator::make($data, [
'zones' => [
'required',
Rule::in(['first-zone', 'second-zone']),
],
]);
in_array:anotherfield
В массиве должны существовать значения anotherfield.
integer
Поле должно иметь корректное целочисленное значение.
ip
Поле должно быть корректным IP-адресом.
ipv4
Поле должно быть IPv4-адресом.
ipv6
Поле должно быть IPv6-адресом.
json
Поле должно быть валидной строкой JSON.
max:value
Значение поля должно быть меньше или равно value. Размеры строк, чисел и файлов трактуются аналогично правилу size
.
mimetypes:text/plain,...
MIME-тип загруженного файла должен быть одним из перечисленных:
'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'
Чтобы определить MIME-тип загруженного файла, фреймворк будет читать содержимое и пытаться угадать MIME-тип, который может отличаться от того, что указал пользователь.
mimes:foo,bar,...
MIME-тип загруженного файла должен быть одним из перечисленных.
Основное использование MIME-правила
'photo' => 'mimes:jpeg,bmp,png'
Даже если необходимо только указать расширение, это правило проверяет MIME-тип файла, читая содержимое файла и пытаясь угадать его.
Полный список MIME-типов и соответствующие им расширения можно найти в: https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
min:value
Значение поля должно быть больше value. Размеры строк, чисел и файлов трактуются аналогично правилу size
.
nullable
Поле может быть равно null
. Это особенно полезно при проверке примитивов, такие как строки и целые числа, которые могут содержать null
значения.
not_in:foo,bar,...
Поле не должно быть включено в заданный список значений. Метод Rule::notIn
можно использовать для конструирования этого правила:
use Illuminate\Validation\Rule;
Validator::make($data, [
'toppings' => [
'required',
Rule::notIn(['sprinkles', 'cherries']),
],
]);
numeric
Поле должно иметь корректное числовое или дробное значение.
present
Поле для проверки должно присутствовать во входных данных, но может быть пустым.
regex:pattern
Поле должно соответствовать заданному регулярному выражению.
Примечание: Для использования regex
может быть необходимо определить правила в виде массива вместо использования разделителя, особенно если регулярное выражение содержит символ разделителя.
required
Проверяемое поле должно иметь непустое значение. Поле считается пустым, если одно из следующих значений верно:
- Если значение равно
null
. - Если значение — пустая строка.
- Если значение является пустым массивом или пустым объектом
Countable
. - Если значение это загруженный файл без пути.
required_if:anotherfield,value,...
Поле должно присутствовать и не быть пустым, если anotherfield равно любому value.
required_unless:anotherfield,value,...
Поле должно присутствовать и не быть пустым, за исключением случая, когда anotherfield равно любому value.
required_with:foo,bar,...
Проверяемое поле должно иметь непустое значение, но только если присутствует хотя бы одно из перечисленных полей (foo, bar и т.д.).
required_with_all:foo,bar,...
Проверяемое поле должно иметь непустое значение, но только если присутствуют все перечисленные поля (foo, bar и т.д.).
required_without:foo,bar,...
Проверяемое поле должно иметь непустое значение, но только если не присутствует хотя бы одно из перечисленных полей (foo, bar и т.д.).
required_without_all:foo,bar,...
Проверяемое поле должно иметь непустое значение, но только если не присутствуют все перечисленные поля (foo, bar и т.д.).
same:field
Поле должно иметь то же значение, что и поле field.
size:value
Поле должно иметь совпадающий с value размер. Для строковых данных value соответствует количество символов, для массива size соответствует количеству элементов массива, для чисел — число, для файлов — размер в килобайтах.
string
Поле должно быть строкой. Если вы хотите, чтобы поле было null
, следует доолнитель указать это полю правило nullable
.
timezone
Поле должно содержать идентификатор часового пояса (таймзоны), один из перечисленных в php-функции timezone_identifiers_list
.
unique:table,column,except,idColumn
Значение поля должно быть уникальным в заданной таблице базы данных. Если column
не указано, то будет использовано имя поля.
Указание пользовательского названия столбца:
'email' => 'unique:users,email_address'
Пользовательское подключение к БД
Иногда вам может понадобиться установить собственное соединение с базой данных, как замечено выше, параметр unique:users
, будет использовать соединение по умолчанию. Чтобы переопределить это, укажите подключение и имя таблицы через синтаксис с точкой:
'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:
Вы также можете указать дополнительные условия, используя метод where
. Например, давайте добавим ограничение, которое проверяет, что account_id
равно 1
:
'email' => Rule::unique('users')->where(function ($query) {
$query->where('account_id', 1);
})
url
Поле должно быть корректным 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;
});
Параметр
$input
переданный в анонимную функцию, будет экземпляромIlluminate\Support\Fluent
и может быть использован для доступа к вашим полям и файлам.
Валидация массивов
Проверка массива полей из формы не должна вызывать затруднений. Например, чтобы проверить, что каждая последующая электронная почта является уникальной, вы можете сделать следующее:
$validator = Validator::make($request->all(), [
'photos.profile' => 'required|image',
]);
Кроме того, вы можете использовать символ *
в ваших языковых файлах, использовать одно сообщение для проверки массива полей:
$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
{
/**
* Предварительная загрузка любых сервисов приложения.
*
* @return void
*/
public function boot()
{
Validator::extend('foo', function ($attribute, $value, $parameters, $validator) {
return $value == 'foo';
});
}
/**
* Регистрация нового сервис-провайдера.
*
* @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';
});
“Скрытое” расширение лишь подразумевает, что атрибут является обязательным. Будет ли это на самом деле недействительный или пустой атрибут, зависит только от вас.