Другие валидаторы
В composer доступно множество валидаторов, которые можно использовать напрямую, например:
webman/validation (Рекомендуется)
top-think/think-validate
respect/validation
Валидатор webman/validation
Основан на illuminate/validation, предоставляет ручную валидацию, валидацию через аннотации, валидацию на уровне параметров и переиспользуемые наборы правил.
Установка
composer require webman/validation
Основные концепции
- Переиспользование набора правил: Определяйте переиспользуемые
rules,messages,attributesиscenesпутём наследования отsupport\validation\Validator, которые можно использовать как при ручной, так и при валидации через аннотации. - Валидация на уровне метода (атрибуты): Используйте PHP 8 атрибут
#[Validate]для привязки валидации к методам контроллера. - Валидация на уровне параметра (атрибуты): Используйте PHP 8 атрибут
#[Param]для привязки валидации к параметрам методов контроллера. - Обработка исключений: При ошибке валидации выбрасывается
support\validation\ValidationException; класс исключения настраивается. - Валидация с базой данных: При использовании валидации с БД необходимо установить
composer require webman/database.
Ручная валидация
Базовое использование
use support\validation\Validator;
$data = ['email' => 'user@example.com'];
Validator::make($data, [
'email' => 'required|email',
])->validate();
Примечание
validate()выбрасываетsupport\validation\ValidationExceptionпри ошибке валидации. Если вы предпочитаете не использовать исключения, используйте подход сfails()ниже для получения сообщений об ошибках.
Пользовательские сообщения и атрибуты
use support\validation\Validator;
$data = ['contact' => 'user@example.com'];
Validator::make(
$data,
['contact' => 'required|email'],
['contact.email' => 'Invalid email format'],
['contact' => 'Email']
)->validate();
Валидация без исключения (получение сообщений об ошибках)
Если вы предпочитаете не использовать исключения, используйте fails() для проверки и получения сообщений об ошибках через errors() (возвращает MessageBag):
use support\validation\Validator;
$data = ['email' => 'bad-email'];
$validator = Validator::make($data, [
'email' => 'required|email',
]);
if ($validator->fails()) {
$firstError = $validator->errors()->first(); // string
$allErrors = $validator->errors()->all(); // array
$errorsByField = $validator->errors()->toArray(); // array
// handle errors...
}
Переиспользование набора правил (пользовательский валидатор)
namespace app\validation;
use support\validation\Validator;
class UserValidator extends Validator
{
protected array $rules = [
'id' => 'required|integer|min:1',
'name' => 'required|string|min:2|max:20',
'email' => 'required|email',
];
protected array $messages = [
'name.required' => 'Name is required',
'email.required' => 'Email is required',
'email.email' => 'Invalid email format',
];
protected array $attributes = [
'name' => 'Name',
'email' => 'Email',
];
}
Переиспользование при ручной валидации
use app\validation\UserValidator;
UserValidator::make($data)->validate();
Использование сцен (опционально)
scenes — опциональная функция; она валидирует только подмножество полей при вызове withScene(...).
namespace app\validation;
use support\validation\Validator;
class UserValidator extends Validator
{
protected array $rules = [
'id' => 'required|integer|min:1',
'name' => 'required|string|min:2|max:20',
'email' => 'required|email',
];
protected array $scenes = [
'create' => ['name', 'email'],
'update' => ['id', 'name', 'email'],
];
}
use app\validation\UserValidator;
// Сцена не указана -> валидируются все правила
UserValidator::make($data)->validate();
// Сцена указана -> валидируются только поля в этой сцене
UserValidator::make($data)->withScene('create')->validate();
Валидация через аннотации (на уровне метода)
Прямые правила
use support\Request;
use support\validation\annotation\Validate;
class AuthController
{
#[Validate(
rules: [
'email' => 'required|email',
'password' => 'required|string|min:6',
],
messages: [
'email.required' => 'Email is required',
'password.required' => 'Password is required',
],
attributes: [
'email' => 'Email',
'password' => 'Password',
]
)]
public function login(Request $request)
{
return json(['code' => 0, 'msg' => 'ok']);
}
}
Переиспользование наборов правил
use app\validation\UserValidator;
use support\Request;
use support\validation\annotation\Validate;
class UserController
{
#[Validate(validator: UserValidator::class, scene: 'create')]
public function create(Request $request)
{
return json(['code' => 0, 'msg' => 'ok']);
}
}
Множественные слои валидации
use support\validation\annotation\Validate;
class UserController
{
#[Validate(rules: ['email' => 'required|email'])]
#[Validate(rules: ['token' => 'required|string'])]
public function send()
{
return json(['code' => 0, 'msg' => 'ok']);
}
}
Источник данных для валидации
use support\validation\annotation\Validate;
class UserController
{
#[Validate(
rules: ['email' => 'required|email'],
in: ['query', 'body', 'path']
)]
public function send()
{
return json(['code' => 0, 'msg' => 'ok']);
}
}
Параметр in указывает источник данных:
- query — параметры HTTP-запроса из
$request->get() - body — тело HTTP-запроса из
$request->post() - path — параметры пути HTTP-запроса из
$request->route->param()
in может быть строкой или массивом; при массиве значения объединяются по порядку, при этом более поздние перезаписывают более ранние. Если in не указан, по умолчанию используется ['query', 'body', 'path'].
Валидация на уровне параметра (Param)
Базовое использование
use support\validation\annotation\Param;
class MailController
{
public function send(
#[Param(rules: 'required|email')] string $from,
#[Param(rules: 'required|email')] string $to,
#[Param(rules: 'required|string|min:1|max:500')] string $content
) {
return json(['code' => 0, 'msg' => 'ok']);
}
}
Источник данных для валидации
Аналогично, валидация на уровне параметра также поддерживает параметр in для указания источника:
use support\validation\annotation\Param;
class MailController
{
public function send(
#[Param(rules: 'required|email', in: ['body'])] string $from
) {
return json(['code' => 0, 'msg' => 'ok']);
}
}
rules поддерживает строку или массив
use support\validation\annotation\Param;
class MailController
{
public function send(
#[Param(rules: ['required', 'email'])] string $from
) {
return json(['code' => 0, 'msg' => 'ok']);
}
}
Пользовательские сообщения / атрибут
use support\validation\annotation\Param;
class UserController
{
public function updateEmail(
#[Param(
rules: 'required|email',
messages: ['email.email' => 'Invalid email format'],
attribute: 'Email'
)]
string $email
) {
return json(['code' => 0, 'msg' => 'ok']);
}
}
Переиспользование констант правил
final class ParamRules
{
public const EMAIL = ['required', 'email'];
}
class UserController
{
public function send(
#[Param(rules: ParamRules::EMAIL)] string $email
) {
return json(['code' => 0, 'msg' => 'ok']);
}
}
Комбинация валидации на уровне метода и параметра
use support\Request;
use support\validation\annotation\Param;
use support\validation\annotation\Validate;
class UserController
{
#[Validate(rules: ['token' => 'required|string'])]
public function send(
Request $request,
#[Param(rules: 'required|email')] string $from,
#[Param(rules: 'required|integer')] int $id
) {
return json(['code' => 0, 'msg' => 'ok']);
}
}
Автоматический вывод правил (на основе сигнатуры параметров)
При использовании #[Validate] на методе или при использовании #[Param] на любом параметре этого метода компонент автоматически выводит и дополняет базовые правила валидации из сигнатуры параметров метода, затем объединяет их с существующими правилами перед валидацией.
Пример: эквивалентное развёртывание #[Validate]
1) Включён только #[Validate] без ручного указания правил:
use support\validation\annotation\Validate;
class DemoController
{
#[Validate]
public function create(string $content, int $uid)
{
}
}
Эквивалентно:
use support\validation\annotation\Validate;
class DemoController
{
#[Validate(rules: [
'content' => 'required|string',
'uid' => 'required|integer',
])]
public function create(string $content, int $uid)
{
}
}
2) Указаны только частичные правила, остальное дополняется из сигнатуры параметров:
use support\validation\annotation\Validate;
class DemoController
{
#[Validate(rules: [
'content' => 'min:2',
])]
public function create(string $content, int $uid)
{
}
}
Эквивалентно:
use support\validation\annotation\Validate;
class DemoController
{
#[Validate(rules: [
'content' => 'required|string|min:2',
'uid' => 'required|integer',
])]
public function create(string $content, int $uid)
{
}
}
3) Значение по умолчанию / nullable тип:
use support\validation\annotation\Validate;
class DemoController
{
#[Validate]
public function create(string $content = 'default', ?int $uid = null)
{
}
}
Эквивалентно:
use support\validation\annotation\Validate;
class DemoController
{
#[Validate(rules: [
'content' => 'string',
'uid' => 'integer|nullable',
])]
public function create(string $content = 'default', ?int $uid = null)
{
}
}
Обработка исключений
Исключение по умолчанию
При ошибке валидации по умолчанию выбрасывается support\validation\ValidationException, который наследует Webman\Exception\BusinessException и не логирует ошибки.
Поведение ответа по умолчанию обрабатывается в BusinessException::render():
- Обычные запросы: возвращается строковое сообщение, например
token is required. - JSON-запросы: возвращается JSON-ответ, например
{"code": 422, "msg": "token is required.", "data":....}
Настройка через пользовательское исключение
- Глобальная настройка:
exceptionвconfig/plugin/webman/validation/app.php
Многоязычная поддержка
Компонент включает встроенные языковые пакеты китайского и английского языков и поддерживает переопределение в проекте. Порядок загрузки:
- Языковой пакет проекта
resource/translations/{locale}/validation.php - Встроенный компонент
vendor/webman/validation/resources/lang/{locale}/validation.php - Встроенный английский Illuminate (резервный)
Примечание
Язык по умолчанию Webman настраивается вconfig/translation.phpили может быть изменён черезlocale('en');.
Пример локального переопределения
resource/translations/zh_CN/validation.php
return [
'email' => ':attribute is not a valid email format.',
];
Автозагрузка middleware
После установки компонент автоматически загружает middleware валидации через config/plugin/webman/validation/middleware.php; ручная регистрация не требуется.
Генерация из командной строки
Используйте команду make:validator для генерации классов валидаторов (по умолчанию вывод в каталог app/validation).
Примечание
Требуетсяcomposer require webman/console
Базовое использование
- Генерация пустого шаблона
php webman make:validator UserValidator
- Перезапись существующего файла
php webman make:validator UserValidator --force
php webman make:validator UserValidator -f
Генерация правил из структуры таблицы
- Указание имени таблицы для генерации базовых правил (выводит
$rulesиз типа поля/nullable/длины и т.д.; по умолчанию исключает поля, связанные с ORM: laravel используетcreated_at/updated_at/deleted_at, thinkorm используетcreate_time/update_time/delete_time)
php webman make:validator UserValidator --table=wa_users
php webman make:validator UserValidator -t wa_users
- Указание подключения к базе данных (сценарии с несколькими подключениями)
php webman make:validator UserValidator --table=wa_users --database=mysql
php webman make:validator UserValidator -t wa_users -d mysql
Сцены
- Генерация CRUD-сцен:
create/update/delete/detail
php webman make:validator UserValidator --table=wa_users --scenes=crud
php webman make:validator UserValidator -t wa_users -s crud
Сцена
updateвключает поле первичного ключа (для поиска записей) плюс остальные поля;delete/detailпо умолчанию включают только первичный ключ.
Выбор ORM (laravel (illuminate/database) vs think-orm)
- Автовыбор (по умолчанию): Использует установленный/настроенный; при наличии обоих по умолчанию используется illuminate
- Принудительное указание
php webman make:validator UserValidator --table=wa_users --orm=laravel
php webman make:validator UserValidator --table=wa_users --orm=thinkorm
php webman make:validator UserValidator -t wa_users -o thinkorm
Полный пример
php webman make:validator UserValidator -t wa_users -d mysql -s crud -o laravel -f
Модульные тесты
Из корневой директории webman/validation выполните:
composer install
vendor\bin\phpunit -c phpunit.xml
Справочник правил валидации
Доступные правила валидации
[!IMPORTANT]
- Webman Validation основан на
illuminate/validation; имена правил совпадают с Laravel, специфичных правил Webman нет.- Middleware по умолчанию валидирует данные из
$request->all()(GET+POST), объединённые с параметрами маршрута, исключая загруженные файлы; для правил файлов объедините$request->file()с данными самостоятельно или вызовитеValidator::makeвручную.current_passwordзависит от auth guard;exists/uniqueзависят от подключения к БД и query builder; эти правила недоступны при отсутствии соответствующих компонентов.
Ниже перечислены все доступные правила валидации и их назначение:
Boolean
String
Numeric
Array
Date
File
Database
Utility
accepted
Поле должно быть "yes", "on", 1, "1", true или "true". Обычно используется для сценариев подтверждения согласия пользователя с условиями использования.
accepted_if:anotherfield,value,...
Когда другое поле равно указанному значению, поле должно быть "yes", "on", 1, "1", true или "true". Обычно используется для условных сценариев согласия.
active_url
Поле должно иметь валидную A или AAAA запись. Это правило сначала использует parse_url для извлечения хоста URL, затем валидирует с помощью dns_get_record.
after:date
Поле должно быть значением после указанной даты. Дата передаётся в strtotime для преобразования в валидный DateTime:
use support\validation\Validator;
Validator::make($data, [
'start_date' => 'required|date|after:tomorrow',
])->validate();
Можно также передать имя другого поля для сравнения:
Validator::make($data, [
'finish_date' => 'required|date|after:start_date',
])->validate();
Можно использовать fluent-построитель правила date:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'start_date' => [
'required',
Rule::date()->after(\Carbon\Carbon::today()->addDays(7)),
],
])->validate();
afterToday и todayOrAfter удобно выражают «должно быть после сегодня» или «должно быть сегодня или позже»:
Validator::make($data, [
'start_date' => [
'required',
Rule::date()->afterToday(),
],
])->validate();
after_or_equal:date
Поле должно быть в указанную дату или после неё. Подробнее см. after.
Можно использовать fluent-построитель правила date:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'start_date' => [
'required',
Rule::date()->afterOrEqual(\Carbon\Carbon::today()->addDays(7)),
],
])->validate();
anyOf
Rule::anyOf позволяет указать «удовлетворять любому одному набору правил». Например, следующее правило означает, что username должен быть либо email-адресом, либо строкой из букв, цифр, подчёркиваний и дефисов длиной не менее 6 символов:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'username' => [
'required',
Rule::anyOf([
['string', 'email'],
['string', 'alpha_dash', 'min:6'],
]),
],
])->validate();
alpha
Поле должно содержать только Unicode-буквы (\p{L} и \p{M}).
Для разрешения только ASCII (a-z, A-Z) добавьте опцию ascii:
Validator::make($data, [
'username' => 'alpha:ascii',
])->validate();
alpha_dash
Поле может содержать только Unicode-буквы и цифры (\p{L}, \p{M}, \p{N}), плюс ASCII дефис (-) и подчёркивание (_).
Для разрешения только ASCII (a-z, A-Z, 0-9) добавьте опцию ascii:
Validator::make($data, [
'username' => 'alpha_dash:ascii',
])->validate();
alpha_num
Поле может содержать только Unicode-буквы и цифры (\p{L}, \p{M}, \p{N}).
Для разрешения только ASCII (a-z, A-Z, 0-9) добавьте опцию ascii:
Validator::make($data, [
'username' => 'alpha_num:ascii',
])->validate();
array
Поле должно быть PHP array.
При наличии дополнительных параметров у правила array ключи входного массива должны быть в списке параметров. В примере ключ admin не входит в разрешённый список, поэтому он невалиден:
use support\validation\Validator;
$input = [
'user' => [
'name' => 'Taylor Otwell',
'username' => 'taylorotwell',
'admin' => true,
],
];
Validator::make($input, [
'user' => 'array:name,username',
])->validate();
Рекомендуется явно определять разрешённые ключи массива в реальных проектах.
ascii
Поле может содержать только 7-битные ASCII-символы.
bail
Остановить валидацию остальных правил для поля при первой ошибке.
Это правило влияет только на текущее поле. Для «остановки при первой ошибке глобально» используйте валидатор Illuminate напрямую и вызовите stopOnFirstFailure().
before:date
Поле должно быть до указанной даты. Дата передаётся в strtotime для преобразования в валидный DateTime. Как и в after, можно передать имя другого поля для сравнения.
Можно использовать fluent-построитель правила date:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'start_date' => [
'required',
Rule::date()->before(\Carbon\Carbon::today()->subDays(7)),
],
])->validate();
beforeToday и todayOrBefore удобно выражают «должно быть до сегодня» или «должно быть сегодня или раньше»:
Validator::make($data, [
'start_date' => [
'required',
Rule::date()->beforeToday(),
],
])->validate();
before_or_equal:date
Поле должно быть в указанную дату или до неё. Дата передаётся в strtotime для преобразования в валидный DateTime. Как и в after, можно передать имя другого поля для сравнения.
Можно использовать fluent-построитель правила date:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'start_date' => [
'required',
Rule::date()->beforeOrEqual(\Carbon\Carbon::today()->subDays(7)),
],
])->validate();
between:min,max
Размер поля должен быть между min и max (включительно). Оценка для строк, чисел, массивов и файлов такая же, как в size.
boolean
Поле должно преобразовываться в boolean. Допустимые значения: true, false, 1, 0, "1", "0".
Используйте параметр strict для разрешения только true или false:
Validator::make($data, [
'foo' => 'boolean:strict',
])->validate();
confirmed
Поле должно иметь соответствующее поле {field}_confirmation. Например, когда поле — password, требуется password_confirmation.
Можно также указать пользовательское имя поля подтверждения, например confirmed:repeat_username требует, чтобы repeat_username совпадало с текущим полем.
contains:foo,bar,...
Поле должно быть массивом и содержать все указанные значения параметров. Это правило обычно используется для валидации массивов; можно использовать Rule::contains для его построения:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'roles' => [
'required',
'array',
Rule::contains(['admin', 'editor']),
],
])->validate();
doesnt_contain:foo,bar,...
Поле должно быть массивом и не должно содержать ни одного из указанных значений параметров. Можно использовать Rule::doesntContain для построения:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'roles' => [
'required',
'array',
Rule::doesntContain(['admin', 'editor']),
],
])->validate();
current_password
Поле должно совпадать с паролем текущего аутентифицированного пользователя. Можно указать auth guard первым параметром:
Validator::make($data, [
'password' => 'current_password:api',
])->validate();
[!WARNING]
Это правило зависит от компонента auth и конфигурации guard; не используйте при отсутствии интеграции auth.
date
Поле должно быть валидной (не относительной) датой, распознаваемой strtotime.
date_equals:date
Поле должно быть равно указанной дате. Дата передаётся в strtotime для преобразования в валидный DateTime.
date_format:format,...
Поле должно соответствовать одному из указанных форматов. Используйте либо date, либо date_format. Это правило поддерживает все форматы PHP DateTime.
Можно использовать fluent-построитель правила date:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'start_date' => [
'required',
Rule::date()->format('Y-m-d'),
],
])->validate();
decimal:min,max
Поле должно быть числовым с требуемым количеством десятичных знаков:
Validator::make($data, [
'price' => 'decimal:2',
])->validate();
Validator::make($data, [
'price' => 'decimal:2,4',
])->validate();
declined
Поле должно быть "no", "off", 0, "0", false или "false".
declined_if:anotherfield,value,...
Когда другое поле равно указанному значению, поле должно быть "no", "off", 0, "0", false или "false".
different:field
Поле должно отличаться от field.
digits:value
Поле должно быть целым числом длиной value.
digits_between:min,max
Поле должно быть целым числом длиной между min и max.
dimensions
Поле должно быть изображением и удовлетворять ограничениям размеров:
Validator::make($data, [
'avatar' => 'dimensions:min_width=100,min_height=200',
])->validate();
Доступные ограничения: min_width, max_width, min_height, max_height, width, height, ratio.
ratio — соотношение сторон; может быть выражено дробью или float:
Validator::make($data, [
'avatar' => 'dimensions:ratio=3/2',
])->validate();
У этого правила много параметров; рекомендуется использовать Rule::dimensions для построения:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'avatar' => [
'required',
Rule::dimensions()
->maxWidth(1000)
->maxHeight(500)
->ratio(3 / 2),
],
])->validate();
distinct
При валидации массивов значения полей не должны дублироваться:
Validator::make($data, [
'foo.*.id' => 'distinct',
])->validate();
По умолчанию используется нестрогое сравнение. Добавьте strict для строгого сравнения:
Validator::make($data, [
'foo.*.id' => 'distinct:strict',
])->validate();
Добавьте ignore_case для игнорирования регистра:
Validator::make($data, [
'foo.*.id' => 'distinct:ignore_case',
])->validate();
doesnt_start_with:foo,bar,...
Поле не должно начинаться ни с одного из указанных значений.
doesnt_end_with:foo,bar,...
Поле не должно заканчиваться ни на одно из указанных значений.
Поле должно быть валидным email-адресом. Это правило зависит от egulias/email-validator, по умолчанию использует RFCValidation и может использовать другие методы валидации:
Validator::make($data, [
'email' => 'email:rfc,dns',
])->validate();
Доступные методы валидации:
Можно использовать fluent-построитель правил:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'email' => [
'required',
Rule::email()
->rfcCompliant(strict: false)
->validateMxRecord()
->preventSpoofing(),
],
])->validate();
[!WARNING]
dnsиspoofтребуют расширения PHPintl.
encoding:encoding_type
Поле должно соответствовать указанной кодировке символов. Это правило использует mb_check_encoding для определения кодировки файла или строки. Можно использовать с построителем правил для файлов:
use Illuminate\Validation\Rules\File;
use support\validation\Validator;
Validator::make($data, [
'attachment' => [
'required',
File::types(['csv'])->encoding('utf-8'),
],
])->validate();
ends_with:foo,bar,...
Поле должно заканчиваться одним из указанных значений.
enum
Enum — правило на основе класса для валидации того, что значение поля является валидным значением enum. Передайте имя класса enum при построении. Для примитивных значений используйте Backed Enum:
use app\enums\ServerStatus;
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'status' => [Rule::enum(ServerStatus::class)],
])->validate();
Используйте only/except для ограничения значений enum:
use app\enums\ServerStatus;
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'status' => [
Rule::enum(ServerStatus::class)
->only([ServerStatus::Pending, ServerStatus::Active]),
],
])->validate();
Validator::make($data, [
'status' => [
Rule::enum(ServerStatus::class)
->except([ServerStatus::Pending, ServerStatus::Active]),
],
])->validate();
Используйте when для условных ограничений:
use app\Enums\ServerStatus;
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'status' => [
Rule::enum(ServerStatus::class)->when(
$isAdmin,
fn ($rule) => $rule->only(ServerStatus::Active),
fn ($rule) => $rule->only(ServerStatus::Pending),
),
],
])->validate();
exclude
Поле будет исключено из данных, возвращаемых validate/validated.
exclude_if:anotherfield,value
Когда anotherfield равно value, поле будет исключено из данных, возвращаемых validate/validated.
Для сложных условий используйте Rule::excludeIf:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'role_id' => Rule::excludeIf($isAdmin),
])->validate();
Validator::make($data, [
'role_id' => Rule::excludeIf(fn () => $isAdmin),
])->validate();
exclude_unless:anotherfield,value
Если anotherfield не равно value, поле будет исключено из данных, возвращаемых validate/validated. Если value — null (например, exclude_unless:name,null), поле сохраняется только когда поле сравнения null или отсутствует.
exclude_with:anotherfield
Когда anotherfield существует, поле будет исключено из данных, возвращаемых validate/validated.
exclude_without:anotherfield
Когда anotherfield не существует, поле будет исключено из данных, возвращаемых validate/validated.
exists:table,column
Поле должно существовать в указанной таблице базы данных.
Базовое использование правила Exists
Validator::make($data, [
'state' => 'exists:states',
])->validate();
Когда column не указан, по умолчанию используется имя поля. Этот пример проверяет, существует ли столбец state в таблице states.
Указание пользовательского имени столбца
Добавьте имя столбца после имени таблицы:
Validator::make($data, [
'state' => 'exists:states,abbreviation',
])->validate();
Для указания подключения к БД добавьте имя подключения перед именем таблицы:
Validator::make($data, [
'email' => 'exists:connection.staff,email',
])->validate();
Можно также передать имя класса модели; фреймворк определит имя таблицы:
Validator::make($data, [
'user_id' => 'exists:app\model\User,id',
])->validate();
Для пользовательских условий запроса используйте построитель Rule:
use Illuminate\Database\Query\Builder;
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'email' => [
'required',
Rule::exists('staff')->where(function (Builder $query) {
$query->where('account_id', 1);
}),
],
])->validate();
Можно также указать имя столбца напрямую в Rule::exists:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'state' => [Rule::exists('states', 'abbreviation')],
])->validate();
Для проверки существования набора значений объедините с правилом array:
Validator::make($data, [
'states' => ['array', Rule::exists('states', 'abbreviation')],
])->validate();
При наличии и array, и exists один запрос валидирует все значения.
extensions:foo,bar,...
Проверяет, что расширение загруженного файла входит в разрешённый список:
Validator::make($data, [
'photo' => ['required', 'extensions:jpg,png'],
])->validate();
[!WARNING]
Не полагайтесь только на расширение для валидации типа файла; используйте вместе с mimes или mimetypes.
file
Поле должно быть успешно загруженным файлом.
filled
Когда поле существует, его значение не должно быть пустым.
gt:field
Поле должно быть больше указанного field или value. Оба поля должны иметь один тип. Оценка для строк, чисел, массивов и файлов такая же, как в size.
gte:field
Поле должно быть больше или равно указанному field или value. Оба поля должны иметь один тип. Оценка для строк, чисел, массивов и файлов такая же, как в size.
hex_color
Поле должно быть валидным hex-цветом.
image
Поле должно быть изображением (jpg, jpeg, png, bmp, gif или webp).
[!WARNING]
SVG по умолчанию не разрешён из-за риска XSS. Для разрешения добавьтеallow_svg:image:allow_svg.
in:foo,bar,...
Поле должно быть в указанном списке значений. Можно использовать Rule::in для построения:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'zones' => [
'required',
Rule::in(['first-zone', 'second-zone']),
],
])->validate();
При объединении с правилом array каждое значение во входном массиве должно быть в списке in:
use support\validation\Rule;
use support\validation\Validator;
$input = [
'airports' => ['NYC', 'LAS'],
];
Validator::make($input, [
'airports' => [
'required',
'array',
],
'airports.*' => Rule::in(['NYC', 'LIT']),
])->validate();
in_array:anotherfield.*
Поле должно существовать в списке значений anotherfield.
in_array_keys:value.*
Поле должно быть массивом и содержать хотя бы один из указанных значений в качестве ключа:
Validator::make($data, [
'config' => 'array|in_array_keys:timezone',
])->validate();
integer
Поле должно быть целым числом.
Используйте параметр strict для требования типа integer; строковые целые числа будут невалидны:
Validator::make($data, [
'age' => 'integer:strict',
])->validate();
[!WARNING]
Это правило только проверяет прохождение PHPFILTER_VALIDATE_INT; для строгих числовых типов используйте вместе с numeric.
ip
Поле должно быть валидным IP-адресом.
ipv4
Поле должно быть валидным IPv4-адресом.
ipv6
Поле должно быть валидным IPv6-адресом.
json
Поле должно быть валидной JSON-строкой.
lt:field
Поле должно быть меньше указанного field. Оба поля должны иметь один тип. Оценка для строк, чисел, массивов и файлов такая же, как в size.
lte:field
Поле должно быть меньше или равно указанному field. Оба поля должны иметь один тип. Оценка для строк, чисел, массивов и файлов такая же, как в size.
lowercase
Поле должно быть в нижнем регистре.
list
Поле должно быть списком массива. Ключи списка должны быть последовательными числами от 0 до count($array) - 1.
mac_address
Поле должно быть валидным MAC-адресом.
max:value
Поле должно быть меньше или равно value. Оценка для строк, чисел, массивов и файлов такая же, как в size.
max_digits:value
Поле должно быть целым числом длиной не более value.
mimetypes:text/plain,...
Проверяет, что MIME-тип файла входит в список:
Validator::make($data, [
'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime',
])->validate();
MIME-тип определяется по содержимому файла и может отличаться от MIME, указанного клиентом.
mimes:foo,bar,...
Проверяет, что MIME-тип файла соответствует указанному расширению:
Validator::make($data, [
'photo' => 'mimes:jpg,bmp,png',
])->validate();
Хотя параметры — расширения, это правило читает содержимое файла для определения MIME. Соответствие расширения и MIME:
https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
MIME-типы и расширения
Это правило не проверяет соответствие «расширения файла» и «фактического MIME». Например, mimes:png считает валидным photo.txt с содержимым PNG. Для проверки расширения используйте extensions.
min:value
Поле должно быть больше или равно value. Оценка для строк, чисел, массивов и файлов такая же, как в size.
min_digits:value
Поле должно быть целым числом длиной не менее value.
multiple_of:value
Поле должно быть кратным value.
missing
Поле не должно существовать во входных данных.
missing_if:anotherfield,value,...
Когда anotherfield равно любому value, поле не должно существовать.
missing_unless:anotherfield,value
Если anotherfield не равно любому value, поле не должно существовать.
missing_with:foo,bar,...
Когда любое указанное поле существует, поле не должно существовать.
missing_with_all:foo,bar,...
Когда все указанные поля существуют, поле не должно существовать.
not_in:foo,bar,...
Поле не должно быть в указанном списке значений. Можно использовать Rule::notIn для построения:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'toppings' => [
'required',
Rule::notIn(['sprinkles', 'cherries']),
],
])->validate();
not_regex:pattern
Поле не должно соответствовать указанному регулярному выражению.
Это правило использует PHP preg_match. Регулярное выражение должно иметь разделители, например 'email' => 'not_regex:/^.+$/i'.
[!WARNING]
При использованииregex/not_regex, если regex содержит|, используйте форму массива во избежание конфликта с разделителем|.
nullable
Поле может быть null.
numeric
Поле должно быть числовым.
Используйте параметр strict для разрешения только типов integer или float; числовые строки будут невалидны:
Validator::make($data, [
'amount' => 'numeric:strict',
])->validate();
present
Поле должно существовать во входных данных.
present_if:anotherfield,value,...
Когда anotherfield равно любому value, поле должно существовать.
present_unless:anotherfield,value
Если anotherfield не равно любому value, поле должно существовать.
present_with:foo,bar,...
Когда любое указанное поле существует, поле должно существовать.
present_with_all:foo,bar,...
Когда все указанные поля существуют, поле должно существовать.
prohibited
Поле должно отсутствовать или быть пустым. «Пусто» означает:
prohibited_if:anotherfield,value,...
Когда anotherfield равно любому value, поле должно отсутствовать или быть пустым. «Пусто» означает:
Для сложных условий используйте Rule::prohibitedIf:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'role_id' => Rule::prohibitedIf($isAdmin),
])->validate();
Validator::make($data, [
'role_id' => Rule::prohibitedIf(fn () => $isAdmin),
])->validate();
prohibited_if_accepted:anotherfield,...
Когда anotherfield — "yes", "on", 1, "1", true или "true", поле должно отсутствовать или быть пустым.
prohibited_if_declined:anotherfield,...
Когда anotherfield — "no", "off", 0, "0", false или "false", поле должно отсутствовать или быть пустым.
prohibited_unless:anotherfield,value,...
Если anotherfield не равно любому value, поле должно отсутствовать или быть пустым. «Пусто» означает:
prohibits:anotherfield,...
Когда поле существует и не пусто, все поля в anotherfield должны отсутствовать или быть пустыми. «Пусто» означает:
regex:pattern
Поле должно соответствовать указанному регулярному выражению.
Это правило использует PHP preg_match. Регулярное выражение должно иметь разделители, например 'email' => 'regex:/^.+@.+$/i'.
[!WARNING]
При использованииregex/not_regex, если regex содержит|, используйте форму массива во избежание конфликта с разделителем|.
required
Поле должно существовать и не быть пустым. «Пусто» означает:
required_if:anotherfield,value,...
Когда anotherfield равно любому value, поле должно существовать и не быть пустым.
Для сложных условий используйте Rule::requiredIf:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'role_id' => Rule::requiredIf($isAdmin),
])->validate();
Validator::make($data, [
'role_id' => Rule::requiredIf(fn () => $isAdmin),
])->validate();
required_if_accepted:anotherfield,...
Когда anotherfield — "yes", "on", 1, "1", true или "true", поле должно существовать и не быть пустым.
required_if_declined:anotherfield,...
Когда anotherfield — "no", "off", 0, "0", false или "false", поле должно существовать и не быть пустым.
required_unless:anotherfield,value,...
Если anotherfield не равно любому value, поле должно существовать и не быть пустым. Если value — null (например, required_unless:name,null), поле может быть пустым только когда поле сравнения null или отсутствует.
required_with:foo,bar,...
Когда любое указанное поле существует и не пусто, поле должно существовать и не быть пустым.
required_with_all:foo,bar,...
Когда все указанные поля существуют и не пусты, поле должно существовать и не быть пустым.
required_without:foo,bar,...
Когда любое указанное поле пусто или отсутствует, поле должно существовать и не быть пустым.
required_without_all:foo,bar,...
Когда все указанные поля пусты или отсутствуют, поле должно существовать и не быть пустым.
required_array_keys:foo,bar,...
Поле должно быть массивом и содержать хотя бы указанные ключи.
sometimes
Применять последующие правила валидации только когда поле существует. Обычно используется для полей «опционально, но при наличии должно быть валидным»:
Validator::make($data, [
'nickname' => 'sometimes|string|max:20',
])->validate();
same:field
Поле должно совпадать с field.
size:value
Размер поля должен быть равен указанному value. Для строк: количество символов; для чисел: указанное целое (используйте с numeric или integer); для массивов: количество элементов; для файлов: размер в КБ. Пример:
Validator::make($data, [
'title' => 'size:12',
'seats' => 'integer|size:10',
'tags' => 'array|size:5',
'image' => 'file|size:512',
])->validate();
starts_with:foo,bar,...
Поле должно начинаться с одного из указанных значений.
string
Поле должно быть строкой. Для разрешения null используйте вместе с nullable.
timezone
Поле должно быть валидным идентификатором часового пояса (из DateTimeZone::listIdentifiers). Можно передать параметры, поддерживаемые этим методом:
Validator::make($data, [
'timezone' => 'required|timezone:all',
])->validate();
Validator::make($data, [
'timezone' => 'required|timezone:Africa',
])->validate();
Validator::make($data, [
'timezone' => 'required|timezone:per_country,US',
])->validate();
unique:table,column
Поле должно быть уникальным в указанной таблице.
Указание пользовательской таблицы/столбца:
Можно указать имя класса модели напрямую:
Validator::make($data, [
'email' => 'unique:app\model\User,email_address',
])->validate();
Можно указать имя столбца (по умолчанию используется имя поля):
Validator::make($data, [
'email' => 'unique:users,email_address',
])->validate();
Указание подключения к БД:
Validator::make($data, [
'email' => 'unique:connection.users,email_address',
])->validate();
Игнорирование указанного ID:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'email' => [
'required',
Rule::unique('users')->ignore($user->id),
],
])->validate();
[!WARNING]
ignoreне должен получать пользовательский ввод; используйте только системно сгенерированные уникальные ID (автоинкрементный ID или UUID модели), иначе может возникнуть риск SQL-инъекции.
Можно также передать экземпляр модели:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'email' => [
Rule::unique('users')->ignore($user),
],
])->validate();
Если первичный ключ не id, укажите имя первичного ключа:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'email' => [
Rule::unique('users')->ignore($user->id, 'user_id'),
],
])->validate();
По умолчанию используется имя поля как столбец уникальности; можно также указать имя столбца:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'email' => [
Rule::unique('users', 'email_address')->ignore($user->id),
],
])->validate();
Добавление дополнительных условий:
use Illuminate\Database\Query\Builder;
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'email' => [
Rule::unique('users')->where(
fn (Builder $query) => $query->where('account_id', 1)
),
],
])->validate();
Игнорирование мягко удалённых записей:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'email' => [Rule::unique('users')->withoutTrashed()],
])->validate();
Если столбец мягкого удаления не deleted_at:
use support\validation\Rule;
use support\validation\Validator;
Validator::make($data, [
'email' => [Rule::unique('users')->withoutTrashed('was_deleted_at')],
])->validate();
uppercase
Поле должно быть в верхнем регистре.
url
Поле должно быть валидным URL.
Можно указать разрешённые протоколы:
Validator::make($data, [
'url' => 'url:http,https',
'game' => 'url:minecraft,steam',
])->validate();
ulid
Поле должно быть валидным ULID.
uuid
Поле должно быть валидным RFC 9562 UUID (версия 1, 3, 4, 5, 6, 7 или 8).
Можно указать версию:
Validator::make($data, [
'uuid' => 'uuid:4',
])->validate();
Валидатор top-think/think-validate
Описание
Официальный валидатор ThinkPHP
URL проекта
https://github.com/top-think/think-validate
Установка
composer require topthink/think-validate
Быстрый старт
Создайте app/index/validate/User.php
<?php
namespace app\index\validate;
use think\Validate;
class User extends Validate
{
protected $rule = [
'name' => 'require|max:25',
'age' => 'number|between:1,120',
'email' => 'email',
];
protected $message = [
'name.require' => 'Name is required',
'name.max' => 'Name cannot exceed 25 characters',
'age.number' => 'Age must be a number',
'age.between' => 'Age must be between 1 and 120',
'email' => 'Invalid email format',
];
}
Использование
$data = [
'name' => 'thinkphp',
'email' => 'thinkphp@qq.com',
];
$validate = new \app\index\validate\User;
if (!$validate->check($data)) {
var_dump($validate->getError());
}
Примечание
webman не поддерживает методValidate::rule()think-validate
Валидатор workerman/validation
Описание
Этот проект — локализованная версия https://github.com/Respect/Validation
URL проекта
https://github.com/walkor/validation
Установка
composer require workerman/validation
Быстрый старт
<?php
namespace app\controller;
use support\Request;
use Respect\Validation\Validator as v;
use support\Db;
class IndexController
{
public function index(Request $request)
{
$data = v::input($request->post(), [
'nickname' => v::length(1, 64)->setName('Nickname'),
'username' => v::alnum()->length(5, 64)->setName('Username'),
'password' => v::length(5, 64)->setName('Password')
]);
Db::table('user')->insert($data);
return json(['code' => 0, 'msg' => 'ok']);
}
}
Доступ через jQuery
$.ajax({
url : 'http://127.0.0.1:8787',
type : "post",
dataType:'json',
data : {nickname:'Tom', username:'tom cat', password: '123456'}
});
Результат:
{"code":500,"msg":"Username may only contain letters (a-z) and numbers (0-9)"}
Пояснение:
v::input(array $input, array $rules) валидирует и собирает данные. При ошибке валидации выбрасывается Respect\Validation\Exceptions\ValidationException; при успехе возвращаются валидированные данные (массив).
Если бизнес-код не перехватывает исключение валидации, фреймворк webman перехватит его и вернёт JSON (например, {"code":500, "msg":"xxx"}) или обычную страницу исключения в зависимости от HTTP-заголовков. Если формат ответа не соответствует вашим потребностям, можно перехватить ValidationException и вернуть пользовательские данные, как в примере ниже:
<?php
namespace app\controller;
use support\Request;
use Respect\Validation\Validator as v;
use Respect\Validation\Exceptions\ValidationException;
class IndexController
{
public function index(Request $request)
{
try {
$data = v::input($request->post(), [
'username' => v::alnum()->length(5, 64)->setName('Username'),
'password' => v::length(5, 64)->setName('Password')
]);
} catch (ValidationException $e) {
return json(['code' => 500, 'msg' => $e->getMessage()]);
}
return json(['code' => 0, 'msg' => 'ok', 'data' => $data]);
}
}
Руководство по валидатору
use Respect\Validation\Validator as v;
// Валидация по одному правилу
$number = 123;
v::numericVal()->validate($number); // true
// Цепочка валидации
$usernameValidator = v::alnum()->noWhitespace()->length(1, 15);
$usernameValidator->validate('alganet'); // true
// Получить причину первой ошибки валидации
try {
$usernameValidator->setName('Username')->check('alg anet');
} catch (ValidationException $exception) {
echo $exception->getMessage(); // Username may only contain letters (a-z) and numbers (0-9)
}
// Получить все причины ошибок валидации
try {
$usernameValidator->setName('Username')->assert('alg anet');
} catch (ValidationException $exception) {
echo $exception->getFullMessage();
// Выведет
// - Username must satisfy the following rules
// - Username may only contain letters (a-z) and numbers (0-9)
// - Username must not contain whitespace
var_export($exception->getMessages());
// Выведет
// array (
// 'alnum' => 'Username may only contain letters (a-z) and numbers (0-9)',
// 'noWhitespace' => 'Username must not contain whitespace',
// )
}
// Пользовательские сообщения об ошибках
try {
$usernameValidator->setName('Username')->assert('alg anet');
} catch (ValidationException $exception) {
var_export($exception->getMessages([
'alnum' => 'Username may only contain letters and numbers',
'noWhitespace' => 'Username must not contain spaces',
'length' => 'length satisfies the rule, so this will not be shown'
]));
// Выведет
// array(
// 'alnum' => 'Username may only contain letters and numbers',
// 'noWhitespace' => 'Username must not contain spaces'
// )
}
// Валидация объекта
$user = new stdClass;
$user->name = 'Alexandre';
$user->birthdate = '1987-07-01';
$userValidator = v::attribute('name', v::stringType()->length(1, 32))
->attribute('birthdate', v::date()->minAge(18));
$userValidator->validate($user); // true
// Валидация массива
$data = [
'parentKey' => [
'field1' => 'value1',
'field2' => 'value2'
'field3' => true,
]
];
v::key(
'parentKey',
v::key('field1', v::stringType())
->key('field2', v::stringType())
->key('field3', v::boolType())
)
->assert($data); // Можно также использовать check() или validate()
// Опциональная валидация
v::alpha()->validate(''); // false
v::alpha()->validate(null); // false
v::optional(v::alpha())->validate(''); // true
v::optional(v::alpha())->validate(null); // true
// Правило отрицания
v::not(v::intVal())->validate(10); // false
Различия между методами валидатора validate() check() assert()
validate() возвращает boolean, не выбрасывает исключение
check() выбрасывает исключение при ошибке валидации; получить причину первой ошибки через $exception->getMessage()
assert() выбрасывает исключение при ошибке валидации; получить все причины ошибок через $exception->getFullMessage()
Распространённые правила валидации
Alnum() Только буквы и цифры
Alpha() Только буквы
ArrayType() Тип массива
Between(mixed $minimum, mixed $maximum) Проверяет, что ввод находится между двумя значениями.
BoolType() Тип boolean
Contains(mixed $expectedValue) Проверяет, что ввод содержит определённое значение
ContainsAny(array $needles) Проверяет, что ввод содержит хотя бы одно из определённых значений
Digit() Проверяет, что ввод содержит только цифры
Domain() Проверяет валидное доменное имя
Email() Проверяет валидный email-адрес
Extension(string $extension) Проверяет расширение файла
FloatType() Проверяет тип float
IntType() Проверяет тип integer
Ip() Проверяет IP-адрес
Json() Проверяет JSON-данные
Length(int $min, int $max) Проверяет, что длина в допустимом диапазоне
LessThan(mixed $compareTo) Проверяет, что длина меньше указанного значения
Lowercase() Проверяет нижний регистр
MacAddress() Проверяет MAC-адрес
NotEmpty() Проверяет непустое значение
NullType() Проверяет null
Number() Проверяет число
ObjectType() Проверяет тип объекта
StringType() Проверяет тип строки
Url() Проверяет URL
См. https://respect-validation.readthedocs.io/en/2.0/list-of-rules/ для дополнительных правил валидации.