Respect/Validation для PHP: полное руководство с примерами
Respect/Validation — это мощная и элегантная библиотека для валидации данных в PHP. В отличие от встроенных функций PHP (таких как filter_var или регулярных выражений), Respect/Validation предлагает объектно-ориентированный, цепочечный (fluent) интерфейс для построения сложных правил валидации. Библиотека позволяет создавать читаемые, самодокументируемые проверки, которые легко поддерживать и расширять.
Зачем нужна эта библиотека? В любом веб-приложении необходимо проверять пользовательский ввод: email, пароли, URL, IP-адреса, даты, числовые диапазоны и многое другое. Без системы валидации код быстро превращается в кашу из if-else и регулярных выражений. Respect/Validation решает эту проблему, предоставляя более 100 готовых правил (валидаторов), которые можно комбинировать, создавая сложные цепочки проверок. Библиотека также поддерживает кастомные сообщения об ошибках на разных языках, что делает её идеальным выбором для интернациональных проектов.
Ключевая особенность — цепочки валидации. Вы можете объединять несколько правил в одну цепочку, и они будут применяться последовательно. Если хотя бы одно правило не проходит, валидация останавливается (по умолчанию) и возвращается ошибка. Это позволяет писать компактный, но при этом очень выразительный код.
Установка
Установка производится через Composer — стандартный менеджер пакетов для PHP. Выполните в терминале в корне вашего проекта:
composer require respect/validation
После установки подключите автозагрузчик Composer в вашем PHP-файле:
require_once 'vendor/autoload.php';
Быстрый старт
Минимальный рабочий пример проверки email и пароля:
use Respect\Validation\Validator as v;
$email = 'user@example.com';
$password = 'StrongP@ss1';
// Создаем цепочку валидации
$validator = v::email()->length(6, 100)->notEmpty();
if ($validator->validate($email)) {
echo "Email валиден!";
} else {
// Получаем массив ошибок
$errors = $validator->getMessages();
print_r($errors);
}
// Проверка пароля
$passwordValidator = v::alnum()->noWhitespace()->length(8, 32);
if ($passwordValidator->validate($password)) {
echo "Пароль валиден!";
}
В этом примере v::email() проверяет формат email, length(6, 100) — длину строки, notEmpty() — что значение не пустое. Все правила объединены в цепочку.
Основные методы и классы
Рассмотрим 8 ключевых методов (правил) библиотеки. Каждое правило — это статический метод класса Respect\Validation\Validator (обычно импортируется как v).
1. v::email()
Сигнатура: public static function email(): Validator
Что делает: Проверяет, является ли значение корректным email-адресом в соответствии с RFC 5321/5322.
Пример:
$validator = v::email();
var_dump($validator->validate('test@test.com')); // true
var_dump($validator->validate('not-an-email')); // false
2. v::alnum()
Сигнатура: public static function alnum(string $additionalChars = ''): Validator
Что делает: Проверяет, содержит ли строка только буквы (a-z, A-Z) и цифры (0-9). Можно передать дополнительные разрешённые символы.
Пример:
$validator = v::alnum();
var_dump($validator->validate('abc123')); // true
var_dump($validator->validate('hello world')); // false (пробел не разрешен)
// С дополнительными символами
$validatorWithDash = v::alnum('-');
var_dump($validatorWithDash->validate('my-name')); // true
3. v::length()
Сигнатура: public static function length(int $min = null, int $max = null): Validator
Что делает: Проверяет длину строки (или количество элементов массива/объекта Countable). Если указан только $min — проверяет минимальную длину, если только $max — максимальную.
Пример:
$validator = v::length(5, 10);
var_dump($validator->validate('hello')); // true (5 символов)
var_dump($validator->validate('hi')); // false (2 символа)
var_dump($validator->validate('toolongstring')); // false (13 символов)
// Только минимальная длина
$minValidator = v::length(3);
var_dump($minValidator->validate('ab')); // false
4. v::numericVal()
Сигнатура: public static function numericVal(): Validator
Что делает: Проверяет, является ли значение числовым (integer, float или строка, содержащая число). В отличие от v::intVal(), допускает дробные числа.
Пример:
$validator = v::numericVal();
var_dump($validator->validate(123)); // true
var_dump($validator->validate('3.14')); // true
var_dump($validator->validate('abc')); // false
5. v::intVal()
Сигнатура: public static function intVal(): Validator
Что делает: Проверяет, является ли значение целым числом (integer). Строки, содержащие целые числа, также проходят проверку.
Пример:
$validator = v::intVal();
var_dump($validator->validate(42)); // true
var_dump($validator->validate('42')); // true
var_dump($validator->validate(3.14)); // false
var_dump($validator->validate('3.14')); // false
6. v::date()
Сигнатура: public static function date(string $format = 'Y-m-d'): Validator
Что делает: Проверяет, является ли строка корректной датой в заданном формате. По умолчанию формат Y-m-d (например, 2023-12-31).
Пример:
$validator = v::date('d/m/Y');
var_dump($validator->validate('31/12/2023')); // true
var_dump($validator->validate('2023-12-31')); // false (неверный формат)
$defaultValidator = v::date();
var_dump($defaultValidator->validate('2023-12-31')); // true
7. v::notEmpty()
Сигнатура: public static function notEmpty(): Validator
Что делает: Проверяет, что значение не является "пустым". Пустыми считаются: null, пустая строка '', 0, '0', пустой массив [], false. Это аналог !empty() в PHP, но с более строгой логикой.
Пример:
$validator = v::notEmpty();
var_dump($validator->validate('hello')); // true
var_dump($validator->validate('')); // false
var_dump($validator->validate(null)); // false
var_dump($validator->validate(0)); // false (0 считается пустым)
8. v::in()
Сигнатура: public static function in(mixed $haystack, bool $strict = false): Validator
Что делает: Проверяет, содержится ли значение в заданном массиве (или реализует интерфейс Traversable). Параметр $strict включает строгое сравнение (===).
Пример:
$allowedRoles = ['admin', 'user', 'moderator'];
$validator = v::in($allowedRoles);
var_dump($validator->validate('admin')); // true
var_dump($validator->validate('guest')); // false
// Строгое сравнение
$strictValidator = v::in(['1', 2, 3], true);
var_dump($strictValidator->validate('1')); // true (строка '1' есть в массиве)
var_dump($strictValidator->validate(1)); // false (число 1 не равно строке '1' при строгом сравнении)
Реальный практический пример
Создадим полноценный класс для валидации регистрации пользователя. Пример включает проверку имени, email, пароля, возраста и согласия с условиями.
use Respect\Validation\Validator as v;
use Respect\Validation\Exceptions\NestedValidationException;
class UserRegistrationValidator
{
private array $errors = [];
/**
* Валидирует данные регистрации
* @param array $data Ассоциативный массив с ключами: name, email, password, age, agree
* @return bool true, если все данные валидны
*/
public function validate(array $data): bool
{
$this->errors = [];
// 1. Имя: только буквы, от 2 до 50 символов, не пустое
$nameValidator = v::alnum(' ')
->length(2, 50)
->notEmpty()
->setName('name');
try {
$nameValidator->assert($data['name'] ?? '');
} catch (NestedValidationException $e) {
$this->errors['name'] = $e->getMessages();
}
// 2. Email: валидный email, не пустой
$emailValidator = v::email()
->notEmpty()
->setName('email');
try {
$emailValidator->assert($data['email'] ?? '');
} catch (NestedValidationException $e) {
$this->errors['email'] = $e->getMessages();
}
// 3. Пароль: буквы и цифры, от 8 до 32 символов, без пробелов
$passwordValidator = v::alnum()
->noWhitespace()
->length(8, 32)
->notEmpty()
->setName('password');
try {
$passwordValidator->assert($data['password'] ?? '');
} catch (NestedValidationException $e) {
$this->errors['password'] = $e->getMessages();
}
// 4. Возраст: целое число от 18 до 120
$ageValidator = v::intVal()
->between(18, 120)
->notEmpty()
->setName('age');
try {
$ageValidator->assert($data['age'] ?? '');
} catch (NestedValidationException $e) {
$this->errors['age'] = $e->getMessages();
}
// 5. Согласие: должно быть true (булево)
$agreeValidator = v::boolVal()
->trueVal()
->setName('agree');
try {
$agreeValidator->assert($data['agree'] ?? false);
} catch (NestedValidationException $e) {
$this->errors['agree'] = $e->getMessages();
}
return empty($this->errors);
}
/**
* Возвращает массив ошибок валидации
* @return array
*/
public function getErrors(): array
{
return $this->errors;
}
}
// Использование:
$validator = new UserRegistrationValidator();
$userData = [
'name' => 'Иван Петров',
'email' => 'ivan@example.com',
'password' => 'SecurePass123',
'age' => 25,
'agree' => true,
];
if ($validator->validate($userData)) {
echo "Регистрация прошла успешно!";
} else {
echo "Ошибки валидации:\n";
print_r($validator->getErrors());
}
// Пример с ошибками:
$badData = [
'name' => 'A', // слишком короткое имя
'email' => 'not-email',
'password' => 'short',
'age' => 15, // меньше 18
'agree' => false,
];
if (!$validator->validate($badData)) {
echo "Найдены ошибки:\n";
foreach ($validator->getErrors() as $field => $messages) {
echo "Поле '$field': " . implode(', ', $messages) . "\n";
}
}
Советы по производительности и типичные ошибки
Советы по производительности
- Используйте
validate()вместоassert()для простых проверок. Методvalidate()возвращает boolean и не генерирует исключения, что быстрее.assert()выбрасывает исключение при ошибке, что удобно для детальной обработки, но медленнее. - Кэшируйте валидаторы. Если вы используете один и тот же валидатор многократно (например, в цикле), создайте его один раз и переиспользуйте. Создание объекта валидатора — лёгкая операция, но в циклах с тысячами итераций это может дать прирост.
- Не используйте цепочки для простых проверок. Если нужно проверить только одно условие (например, email), не создавайте цепочку — используйте одиночный валидатор.
- Избегайте избыточных правил. Например,
v::notEmpty()уже включено в некоторые валидаторы (например,v::email()не пропустит пустую строку). Проверьте документацию, чтобы не дублировать проверки.
Типичные ошибки
Также в библиотеке
PDF генерация в Rust: обзор библиотек и инструментов для создания PDF-документов
Стандартная библиотека Kotlin: полный обзор и примеры
Отправка email на JavaScript (Node.js): nodemailer, sendgrid, mailgun
Криптография в Kotlin: шифрование и хеши