Введение
Laravel предоставляет несколько разных подходов к проверке входящих в ваше приложение данных. По умолчанию базовый класс контроллера использует типаж ValidatesRequests, который предоставляет удобный метод проверки входящего HTTP-запроса с помощью различных мощных правил проверки.
Краткое руководство по проверке ввода
Для изучения мощных возможностей проверки ввода в Laravel, давайте рассмотрим полный пример проверки ввода через форму и вывода сообщений об ошибках.
Определение маршрутов
Сначала давайте предположим, что у нас есть следующие маршруты, определённые в файле routes/web.php:
Route::get('post/create', 'PostController@create');
Route::post('post', 'PostController@store');
Очевидно, маршрут GET выведет пользователю форму для написания новой статьи, а маршрут POST сохранит её в БД.
Создание контроллера
Теперь давайте посмотрим на простой контроллер, который обрабатывает эти маршруты. Метод PHPstore()
мы пока оставим пустым:
<?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)
{
// Проверка и сохранение новой статьи.
}
}
Написание логики проверки ввода
Теперь мы готовы наполнить метод PHPstore()
логикой для проверки новой статьи. Если вы посмотрите в базовый класс контроллера приложения (App\Http\Controllers\Controller), то увидите, что в нём используется типаж ValidatesRequests. Этот типаж предоставляет удобный метод PHPvalidate()
всем вашим контроллерам.
Метод PHPvalidate()
принимает входящий HTTP-запрос и набор правил для проверки. Если проверка успешна, ваш код продолжит нормально выполняться. Но если проверка провалится, возникнет исключение, и пользователю будет автоматически отправлен отклик с соответствующей ошибкой. Для обычных HTTP-запросов будет сгенерирован отклик-переадресация, а для AJAX-запросов — JSON-отклик.
Для лучшего понимания метода PHPvalidate()
давайте вернёмся к методу PHPstore()
:
/**
* Сохранение новой статьи.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$this->validate($request, [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
// Статья прошла проверку, сохранение в БД...
}
Как видите, мы просто передали входящий HTTP-запрос и требуемые правила проверки в метод PHPvalidate()
. Если проверка провалится, будет сгенерирован соответствующий отклик. Если проверка успешна, ваш контроллер продолжит нормально выполняться.
добавлено в 5.2 ()
Остановка после первой ошибки ввода
Иногда надо остановить выполнение правил проверки ввода для атрибута после первой ошибки. Для этого назначьте на атрибут правило bail:
$this->validate($request, [
'title' => 'bail|required|unique:posts|max:255',
'body' => 'required',
]);
Если правило required на атрибуте title не выполнится, то правило unique не будет проверяться. Правила будут проверены в порядке их назначения.
Замечание о вложенных атрибутах
Если ваш HTTP-запрос содержит «вложенные» параметры, вы можете указать их в правилах проверки с помощью «точечной» записи:
$this->validate($request, [
'title' => 'required|unique:posts|max:255',
'author.name' => 'required',
'author.description' => 'required',
]);
Вывод ошибок
Что будет, если параметры входящего запроса не пройдут проверку? Как уже было сказано, Laravel автоматически перенаправит пользователя на предыдущую страницу. Вдобавок, все ошибки будут автоматически отправлены в сессию.
Заметьте, мы не привязывали сообщения об ошибках к представлению в нашем маршруте GET. Потому что Laravel проверяет наличие ошибок в данных сессии и автоматически привязывает их к представлению, если они доступны. Поэтому важно помнить, что переменная PHP$errors
будет всегда доступна во всех ваших представлениях при каждом запросе, позволяя вам всегда рассчитывать на то, что она определена и может быть безопасно использована. Переменная PHP$errors
будет экземпляром Illuminate\Support\MessageBag. Более подробно о работе с этим объектом читайте в его документации.
Переменная PHP$errors
привязывается к представлению посредником Illuminate\View\Middleware\ShareErrorsFromSession, который входит в состав группы посредников web.
Итак, в нашем примере при неудачной проверке пользователь будет перенаправлен в метод PHPcreate()
нашего контроллера, позволяя нам вывести сообщения об ошибках в представлении:
<!-- /resources/views/post/create.blade.php -->
<h1>Написать статью</h1>
@if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<!-- Форма написания статьи -->
Настройка формата передачи ошибок
Чтобы настроить формат ошибок проверки, передаваемых в сессию при их возникновении, переопределите formatValidationErrors в базовом контроллере. Не забудьте импортировать класс Illuminate\Contracts\Validation\Validator (для Laravel 5.0 Illuminate\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-запросы. При использовании метода PHPvalidate()
для AJAX-запросов Laravel не создаёт отклик-переадресацию. Вместо этого Laravel создаёт JSON-отклик, содержащий все возникшие при проверке ошибки. Этот JSON-отклик будет отправлен с HTTP-кодом состояния 422.
Проверка запроса формы
Создание запроса формы
Для более сложных сценариев проверки вам может понадобиться «запрос формы». Запросы формы — изменённые классы запросов, содержащие логику проверки. Для создания класса запроса формы используйте Artisan-команду shmake:request
:
shphp artisan make:request StoreBlogPost
Сгенерированный класс будет помещён в папку app/Http/Requests. Если такой папки нет, она будет создана при запуске команды shmake:request
. Давайте добавим несколько правил проверки в метод PHPrules()
:
/**
* Получить правила проверки для применения к запросу.
*
* @return array
*/
public function rules()
{
return [
'title' => 'required|unique|max:255',
'body' => 'required',
];
}
А как же запускаются правила проверки? Надо просто указать тип запроса в методе контроллера. Входящий запрос формы проверяется до вызова метода контроллера, это значит, что вам не надо захламлять ваш контроллер логикой проверки:
/**
* Сохранить входящую статью.
*
* @param StoreBlogPost $request
* @return Response
*/
public function store(StoreBlogPost $request)
{
// Входящий запрос прошёл проверку...
}
Если проверка неуспешна, будет сгенерирован отклик-переадресация для перенаправления пользователя на предыдущую страницу. Также в сессию будут переданы ошибки, и их можно будет отобразить. Если запрос был AJAX-запросом, то пользователю будет возвращён HTTP-отклик с кодом состояния 422, содержащий JSON-представление ошибок проверки.
Авторизация запроса формы
Класс запроса формы также содержит метод PHPauthorize()
. Этим методом вы можете проверить, действительно ли у авторизованного пользователя есть право на изменение данного ресурса. Например, вы можете определить, является ли пользователь владельцем комментария, который он пытается изменить:
/**
* Определить, авторизован ли пользователь для этого запроса.
*
* @return bool
*/
public function authorize()
{
$comment = Comment::find($this->route('comment'));
return $comment && $this->user()->can('update', $comment);
}
Поскольку все запросы форм наследуют базовый класс запроса Laravel, мы можем использовать метод PHPuser()
для получения текущего аутентифицированного пользователя. Также обратите внимание на вызов метода PHProute()
в этом примере. Этот метод даёт вам доступ к параметрам URI, определённым в вызванном маршруте, таким как параметр PHP{comment}
в примере ниже:
Route::post('comment/{comment}');
Если метод PHPauthorize()
возвращает false, то будет автоматически возвращён HTTP-ответ с кодом состояния 403, и метод вашего контроллера не будет выполнен.
Если вы планируете разместить логику авторизации в другой части приложения, просто верните true из метода PHPauthorize()
:
/**
* Определить, авторизован ли пользователь для этого запроса.
*
* @return bool
*/
public function authorize()
{
return true;
}
Настройка формата ошибок
Если хотите настроить формат сообщений об ошибках ввода, передаваемых в сессию при их возникновении, переопределите PHPformatErrors()
в вашем базовом запросе (App\Http\Requests\Request). Не забудьте импортировать класс Illuminate\Contracts\Validation\Validator в начале файла:
/**
* {@inheritdoc}
*/
protected function formatErrors(Validator $validator)
{
return $validator->errors()->all();
}
Настройка сообщений об ошибках
Для настройки сообщений об ошибках, используемых запросом формы, переопределите метод PHPmessages()
. Этот метод должен возвращать массив пар атрибут/правило и соответствующие им сообщения об ошибках:
/**
* Получить сообщения об ошибках для определённых правил проверки.
*
* @return array
*/
public function messages()
{
return [
'title.required' => 'Необходимо указать заголовок',
'body.required' => 'Необходимо написать статью',
];
}
Создание валидаторов вручную
Если вы не хотите использовать метод PHPvalidate()
типажа ValidatesRequests, вы можете создать экземпляр валидатора вручную с помощью фасада Validator. Метод PHPmake()
этого фасада создаёт новый экземпляр валидатора:
<?php
namespace App\Http\Controllers;
use Validator;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PostController extends Controller
{
/**
* Сохранить новую статью.
*
* @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();
}
// Сохранить статью...
}
}
Первый аргумент метода PHPmake()
— данные для проверки. Второй — правила, которые должны быть применены к этим данным.
Если запрос не пройдёт проверку, вы можете использовать метод PHPwithErrors()
, чтобы передать сообщения об ошибках в сессию. При использовании этого метода переменная PHP$errors
автоматически станет общей для ваших представлений после переадресации, позволяя вам легко выводить их пользователю. Метод PHPwithErrors()
принимает валидатор, MessageBag или PHP-массив.
добавлено в 5.3 ()
Автоматическая переадресация
Если вы хотите создать экземпляр валидатора вручную, но при этом иметь возможность автоматической переадресации, предлагаемой типажом ValidatesRequest, то можете вызвать метод PHPvalidate()
на существующем экземпляре валидатора. Если при проверке обнаружатся ошибки, пользователь будет автоматически переадресован, а в случае AJAX-запроса будет возвращён JSON-отклик:
Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
])->validate();
добавлено в 5.0 ()
Использование массивов для указания правил
Несколько правил могут быть разделены либо прямой чертой (|), либо быть отдельными элементами массива.
$validator = Validator::make(
['name' => 'Ваня'],
['name' => ['required', 'min:5']]
);
$validator = Validator::make(
[
'name' => 'Ваня',
'password' => 'плохойпароль',
'email' => 'email@example.com'
],
[
'name' => 'required',
'password' => 'required|min:8',
'email' => 'required|email|unique:users'
]
);
Когда создан экземпляр PHPValidator
, метод PHPfails()
(или PHPpasses()
) может быть использован для проведения проверки.
if ($validator->fails()) {
// Переданные данные не прошли проверку
}
Если валидатор нашёл ошибки, вы можете получить его сообщения таким образом:
$messages = $validator->messages();
Вы также можете получить массив правил, по которым данные не прошли проверку, без самих сообщений — с помощью метода PHPfailed()
:
$failed = $validator->failed();
Именованные наборы ошибок
Если у вас несколько форм на одной странице, вы можете дать имена наборам ошибок MessageBag, и получать сообщения об ошибках для конкретной формы. Просто передайте имя вторым аргументом метода PHPwithErrors()
:
return redirect('register')
->withErrors($validator, 'login');
Теперь вы можете обращаться к экземпляру MessageBag из переменной PHP$errors
:
{{ $errors->login->first('email') }}
Вебхук после проверки
Валидатор также позволяет прикрепить обратные вызовы, которые будут запущены после завершения проверки. Это позволяет легко выполнять последующие проверки, а также добавлять сообщения об ошибках в коллекцию сообщений. Для начала используйте метод PHPafter()
на экземпляре класса PHPValidator
:
$validator = Validator::make(...);
$validator->after(function($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add('field', 'В этом поле что-то не так!');
}
});
if ($validator->fails()) {
//
}
Работа с сообщениями об ошибках
После вызова метода PHPerrors()
(для Laravel 5.0 PHPmessages()
) на экземпляре Validator вы получите объект PHPIlluminate\Support\MessageBag
, который имеет набор полезных методов для работы с сообщениями об ошибках. Переменная PHP$errors
, которая автоматически становится доступной всем представлениям, также является экземпляром класса MessageBag.
Получение первого сообщения для поля
Для получения первого сообщения об ошибке для данного поля используйте метод PHPfirst()
:
$errors = $validator->errors();
echo $errors->first('email');
Получение всех сообщений для одного поля
Для получения массива всех сообщений для данного поля используйте метод PHPget()
:
foreach ($errors->get('email') as $message) {
//
}
добавлено в 5.3 ()
Получение всех сообщений для всех полей
Для получения массива всех сообщения для всех полей используйте метод PHPall()
:
foreach ($errors->all() as $message) {
//
}
Проверка наличия сообщения для поля
Для определения наличия сообщений об ошибках для определённого поля служит метод PHPhas()
:
if ($messages->has('email')) {
//
}
добавлено в 5.2 () 5.1 () 5.0 ()
Получение ошибки в заданном формате
echo $messages->first('email', '<p>:message</p>');
По умолчанию сообщения форматируются в вид, который подходит для Bootstrap.
Получение всех сообщений в заданном формате
foreach ($messages->all('<li>:message</li>') as $message) {
//
}
Изменение сообщений об ошибках
При необходимости вы можете задать свои сообщения об ошибках проверки ввода вместо изначальных. Для этого есть несколько способов. Во-первых, вы можете передать свои сообщения третьим аргументом метода PHPValidator::make()
:
$messages = [
'required' => 'Необходимо указать :attribute.',
];
$validator = Validator::make($input, $rules, $messages);
В этом примере обозначение :attribute будет заменено именем проверяемого поля. Вы можете использовать и другие обозначения. Например:
$messages = [
'same' => ':attribute и :other должны совпадать.',
'size' => ':attribute должен быть равен :size.',
'between' => ':attribute должен быть между :min и :max.',
'in' => ':attribute должен иметь один из следующих типов: :values',
];
Указание своего сообщения для конкретного атрибута
Иногда вам может понадобиться указать своё сообщения только для конкретного поля. Вы можете сделать это с помощью «точечной» записи. Сначала укажите имя атрибута, а затем правило:
$messages = [
'email.required' => 'Нам надо знать ваш e-mail!',
];
Указание своих сообщений в языковых файлах
В большинстве случаев вы будете указывать свои сообщения в языковом файле, а не передавать их напрямую в Validator. Для этого добавьте свои сообщения в массив custom в языковом файле resources/lang/xx/validation.php:
'custom' => [
'email' => [
'required' => 'Нам надо знать ваш e-mail!',
],
],
добавлено в 5.3 ()
Доступные правила проверки
accepted
Поле должно быть в значении yes, on, 1 или true. Это полезно для проверки принятия правил и лицензий.
active_url
добавлено в 5.3 ()
Поле должно иметь корректную запись A или AAAA согласно PHP-функции dns_get_record.
добавлено в 5.2 () 5.1 () 5.0 ()
Поле должно быть корректным URL согласно PHP-функции checkdnsrr.
after:date
Поле должно быть датой, более поздней, чем date. Строки приводятся к датам функцией strtotime:
'start_date' => 'required|date|after:tomorrow'
Вместо того, чтобы передавать строку-дату в strtotime, вы можете указать другое поле для сравнения с датой:
'finish_date' => 'required|date|after:start_date'
alpha
Поле должно содержать только латинские символы.
alpha_dash
Поле должно содержать только латинские символы, цифры, знаки подчёркивания (_) и дефисы (-).
alpha_num
Поле должно содержать только латинские символы и цифры.
array
Поле должно быть PHP-массивом (тип array).
before:date
Поле должно быть датой, более ранней, чем date. Строки приводятся к датам функцией strtotime.
between:min,max
Поле должно быть числом в диапазоне от min до max. Строки, числа и файлы трактуются аналогично правилу PHPsize
.
boolean
Поле должно соответствовать логическому типу. Доступные значения: true, false, 1, 0, "1" и "0".
confirmed
Значение поля должно соответствовать значению поля с этим именем, плюс _confirmation. Например, если проверяется поле password, то на вход должно быть передано совпадающее по значению поле password_confirmation.
date
Поле должно быть правильной датой в соответствии с PHP-функцией strtotime.
date_format:format
Поле должно подходить под заданный формат. При проверке поля вы должны использовать либо date, либо date_format, но не оба сразу.
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.
Ограничение ratio должно быть задано в виде ширины, поделённой на высоту. Это можно указать выражением вида PHP3/2
или в виде нецелого числа PHP1.5
:
'avatar' => 'dimensions:ratio=3/2'
distinct
При работе с массивами поле не должно содержать дублирующих значений.
'foo.*.id' => 'distinct'
Поле должно быть корректным адресом e-mail.
exists:table,column
Поле должно существовать в заданной таблице базы данных.
'state' => 'exists:states'
'state' => 'exists:states,abbreviation'
добавлено в 5.2 ()
Вы также можете указать больше условий, которые будут добавлены к запросу WHERE:
'email' => 'exists:staff,email,account_id,1'
Это условие можно обратить с помощью знака ! :
'email' => 'exists:staff,email,role,!admin'
Если передать значение NULL/NOT_NULL в запрос WHERE, то это добавит проверку значения БД на совпадение с NULL/NOT_NULL:
'email' => 'exists:staff,email,deleted_at,NULL'
'email' => 'exists:staff,email,deleted_at,NOT_NULL'
добавлено в 5.3 ()
Если вы хотите изменить запрос, выполняемый правилом проверки, то можете использовать класс Rule, чтобы задать правило гибко. В этом примере мы также укажем правила проверки в виде массива, вместо использования символа PHP|
для разделения правил:
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,...
Значение поля должно быть одним из перечисленных (foo, bar и т.д.).
добавлено в 5.2 ()
integer
Поле должно иметь корректное целочисленное значение.
ip
Поле должно быть корректным IP-адресом.
json
Поле должно быть JSON-строкой.
max:value
Значение поля должно быть меньше или равно value. Строки, числа и файлы трактуются аналогично правилу PHPsize
.
добавлено в 5.2 ()
mimetypes:text/plain,…
Файл должен быть одного из перечисленных MIME-типов:
'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'
Для определения MIME-типа загруженного файла фреймворк прочитает его содержимое и попытается определить MIME-тип, который может отличаться от указанного клиентом.
mimes:foo,bar,...
MIME-тип загруженного файла должен быть одним из перечисленных.
'photo' => 'mimes:jpeg,bmp,png'
Несмотря на то, что вы просто указываете расширение файла, это правило проверяет MIME-тип файла, обращаясь к его содержимому и распознавая его MIME-тип.
Полный список MIME-типов и соответствующих им расширений можно найти по ссылке [https://svn.apache.org].
min:value
Значение поля должно быть более или равно value. Строки, числа и файлы трактуются аналогично правилу PHPsize
.
добавлено в 5.3 ()
not_in:foo,bar,...
Значение поля не должно быть одним из перечисленных (foo, bar и т.д.).
numeric
Поле должно иметь корректное числовое или дробное значение.
regex:pattern
Поле должно соответствовать заданному регулярному выражению.
При использовании этого правила может быть необходимо указать другие правила в виде элементов массива, вместо разделения их с помощью символа вертикальной черты, особенно если выражение содержит этот символ вертикальной черты (|).
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 размер. Для строк это обозначает длину, для чисел — число, для массивов — число элементов массива, для файлов — размер в килобайтах.
string
Поле должно быть строкового типа. Если вы хотите разрешить для поля значение PHPnull
, назначьте на поле правило PHPnullable
.
timezone
Поле должно содержать корректный идентификатор временной зоны в соответствии с PHP-функцией PHPtimezone_identifiers_list
.
unique:table,column,except,idColumn
Значение поля должно быть уникальным в заданной таблице базы данных. Если column не указано, то будет использовано имя поля.
Указание имени столбца в таблице
'email' => 'unique:users,email_address'
Иногда вам может потребоваться задать собственное соединение для запросов к базе данных от PHPValidator
. Как видно выше, правило проверки PHPunique:users
будет использовать соединение с базой данных по умолчанию для запроса к базе данных. Чтобы изменить это, укажите соединение и имя таблицы, используя «точечную» запись:
'email' => 'unique:connection.users,email_address'
добавлено в 5.0 ()
$verifier = App::make('validation.presence');
$verifier->setConnection('connectionName');
$validator = Validator::make($input, [
'name' => 'required',
'password' => 'required|min:8',
'email' => 'required|email|unique:users',
]);
$validator->setPresenceVerifier($verifier);
Игнорирование определённого ID
Иногда бывает необходимо игнорировать конкретный ID при проверке на уникальность. Например, представим экран «изменения профиля», который содержит имя пользователя, адрес e-mail и местоположение. Разумеется, вы захотите проверить уникальность e-mail. Но если пользователь изменит только поле с именем, и не изменит e-mail, вам надо избежать возникновения ошибки из-за того, что пользователь сам уже является владельцем этого e-mail.
добавлено в 5.3 ()
Чтобы валидатор игнорировал ID пользователя, мы используем класс Rule для гибкого задания правила. В этом примере мы также укажем правила проверки в виде массива, вместо использования символа PHP|
для разделения правил:
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::unique('users')->ignore($user->id),
],
]);
Если в вашей таблице используется первичный ключ с именем, отличающимся от id, укажите его при вызове метода PHPignore()
:
'email' => Rule::unique('users')->ignore($user->id, 'user_id')
добавлено в 5.2 () 5.1 () 5.0 ()
Вам надо, чтобы ошибка возникла только в том случае, когда пользователь укажет e-mail, который уже был использован другим пользователем. Чтобы правило проверки на уникальность игнорировало ID пользователя, передайте ID третьим параметром:
'email' => 'unique:users,email_address,'.$user->id
Если в вашей таблице используется первичный ключ с именем, отличающимся от id, укажите его четвёртым параметром:
'email' => 'unique:users,email_address,'.$user->id.',user_id'
Добавление дополнительных условий
добавлено в 5.3 ()
url
Поле должно быть корректным URL.
Условные правила
В некоторых случаях вам нужно запускать проверки поля, только если оно есть во входном массиве. Чтобы быстро это сделать, добавьте правило sometimes в ваш список правил:
$v = Validator::make($data, [
'email' => 'sometimes|required|email',
]);
В этом примере поле email будет проверено, только если оно есть в массиве $data.
Иногда вам может быть нужно, чтобы поле имело какое-либо значение, только если другое поле имеет значение, скажем, больше 100. Или вы можете требовать наличия двух полей, только когда также указано третье. Это легко достигается условными правилами. Сперва создайте объект PHPValidator
с набором статичных правил, которые никогда не изменяются:
$v = Validator::make($data, [
'email' => 'required|email',
'games' => 'required|numeric',
]);
Теперь предположим, что ваше приложения написано для коллекционеров игр. Если регистрируется коллекционер с более, чем 100 играми, то мы хотим его спросить, зачем ему такое количество. Например, у него может быть магазин игр, или может ему просто нравится их собирать. Итак, для добавления такого условного правила мы используем метод PHPsometimes()
на экземпляре PHPValidator
:
$v->sometimes('reason', 'required|max:500', function ($input) {
return $input->games >= 100;
});
Первый аргумент этого метода — имя поля, которое мы проверяем. Второй аргумент — правило, которое мы хотим добавить, если переданная функция-замыкание (третий аргумент) вернёт true. Этот метод позволяет легко создавать сложные правила проверки ввода. Вы можете даже добавлять условные правила для нескольких полей одновременно:
$v->sometimes(['reason', 'cost'], 'required', function ($input) {
return $input->games >= 100;
});
Параметр PHP$input
, передаваемый замыканию — объект Illuminate\Support\Fluent и может использоваться для чтения проверяемого ввода и файлов.
Проверка ввода массивов
Проверка ввода массива из полей ввода не должна быть сложной. Например, чтобы проверить, что каждый e-mail в данном поле ввода массива уникален, можно сделать так:
$validator = Validator::make($request->all(), [
'person.*.email' => 'email|unique:users',
'person.*.first_name' => 'required_with:person.*.last_name',
]);
Также вы можете использовать символ * при задании сообщений об ошибках ввода в языковых файлах, что позволяет легко использовать одно сообщение для полей на основе массивов:
'custom' => [
'person.*.email' => [
'unique' => 'Каждый пользователь должен иметь уникальный адрес e-mail',
]
],
Собственные правила проверки
Laravel содержит множество полезных правил, однако вам может понадобиться создать собственные. Один из способов зарегистрировать произвольное правило — через метод PHPValidator::extend()
. Давайте используем этот метод в сервис-провайдере для регистрации своего правила:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Validator;
//для версии 5.2 и ранее:
//use Validator;
use Illuminate\Support\ServiceProvider;
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()
{
//
}
}
Переданная функция-замыкание получает четыре аргумента: имя проверяемого поля PHP$attribute
, значение поля PHP$value
, массив параметров PHP$parameters
, переданных правилу, и объект Validator.
Вместо замыкания в метод PHPextend()
также можно передать метод класса:
Validator::extend('foo', 'FooValidator@validate');
Определение сообщения об ошибке
Вам также понадобится определить сообщение об ошибке для нового правила. Вы можете сделать это либо передавая его в виде массива строк в PHPValidator
, либо вписав в языковой файл. Это сообщение необходимо поместить на первом уровне массива, а не в массив custom, который используется только для сообщений по конкретным полям:
"foo" => "Your input was invalid!",
"accepted" => "The :attribute must be accepted.",
// Остальные сообщения об ошибках...
добавлено в 5.0 ()
Расширение класса PHPValidator
Вместо использования функций-замыканий для расширения набора доступных правил вы можете расширить сам класс PHPValidator
. Для этого создайте класс, который наследует Illuminate\Validation\Validator. Вы можете добавить новые методы проверок, начав их имя с validate:
<?php
class CustomValidator extends \Illuminate\Validation\Validator
public function validateFoo($attribute, $value, $parameters)
{
return $value == 'foo';
}
}
Регистрация нового класса PHPValidator
Затем вам нужно зарегистрировать собственное расширение:
Validator::resolver(function($translator, $data, $rules, $messages)
{
return new CustomValidator($translator, $data, $rules, $messages);
});
Иногда при создании своего правила вам может понадобиться определить собственные строки-переменные для замены в сообщениях об ошибках. Это делается путём создания класса, как было описано выше, и вызовом метода PHPValidator::replacer()
. Это можно сделать в методе PHPboot()
сервис-провайдера:
/**
* Загрузка любых сервисов приложения.
*
* @return void
*/
public function boot()
{
Validator::extend(...);
Validator::replacer('foo', function ($message, $attribute, $rule, $parameters) {
return str_replace(...);
});
}
добавлено в 5.0 ()
По умолчанию, если проверяемое поле отсутствует или имеет пустое значение по правилу required, обычные правила не запускаются, в том числе собственные правила. Например, правило unique не будет запущено для значения null:
$rules = ['name' => 'unique'];
$input = ['name' => null];
Validator::make($input, $rules)->passes(); // true
Чтобы применять правило даже для пустых полей, правило должно считать, что поле обязательное. Для создания такого «неявного» наследования используйте метод PHPValidator::extendImplicit()
:
Validator::extendImplicit('foo', function ($attribute, $value, $parameters, $validator) {
return $value == 'foo';
});
«Неявное» наследование только указывает на обязательность поля. А будет ли правило пропускать пустое или отсутствующее поле или нет, зависит от вас.
Комментарии (3)
app/Http/Requests и если запрос был AJAX-запросом, то пользователю будет возвращён HTTP-ответ с кодом состояния 422, содержащий JSON-представление ошибок проверки.
А как быть с AJAXом? Как его проверять с app/Http/Requests ?
Все, разобрался! Сначала делаем обычную форму, потом на нее вешаем JS передачи через ajax, как то так, JS:
Сделал на своем сайте, не хочет работать. Что-то я видимо не так намудрил