Symfony Validator
Symfony — это набор PHP-компонентов, фреймворк для веб-приложений, философия и сообщество, которые работают вместе в гармонии.
Валидация — это очень распространенная задача в веб-приложениях. Данные, вводимые в формах, нужно проверять. Данные также необходимо проверять перед записью в базу данных или передачей веб-сервису.
Composer и Bitrix Framework
:::warning Есть 2 варианта использования. (Даже 3). Но самое оптимальное — не трогать composer битрикс и использовать свой, подтянув autoload в init. Но если делать как надо, то вот инструкция с объединением
:::
По умолчанию система ожидает увидеть ваш файл composer.json в папке bitrix, но НУЖНО РАЗМЕСТИТЬ В local/composer. В этом случае нужно указать путь до файла в .settings.php, чтобы его конфигурация могла быть использована в продукте.
:::warning Если вы начали использовать Composer. Вам нужно сообщить об этом менеджеру. Вы должны сказать, что вот используется Composer и нужно закрыть для доступа на уровне DevOps доступ к папке /local/composer целиком.
:::
:::tip Не забудьте правило .gitignore на local/composer. А так же добавить 2 правила исключения для файлов: composer.json composer.lock.
Так же, если на вашем проекте используются миграции и проект уже перенес на ПРОД, то необходимо сделать миграцию на настройки .settings через модуль sprint.migrations или описать инструкцию, как это добавить на проде.
:::
Файл .settings.php:
<?php
return [
'composer' => [
'value' => ['config_path' => '/path/to/your/composer.json']
],
// ...
];
В нем необходимо подключить наш файл с зависимостями bitrix/composer-bx.json с помощью плагина Composer Merge Plugin. В минимальном виде ваш composer.json должен содержать вызов плагина и подключение нашей конфигурации.
Файл composer.json (можно скопировать из bitrix/composer.json.example):
{
"require": {
"wikimedia/composer-merge-plugin": "dev-master"
},
"extra": {
"merge-plugin": {
"require": [
"/path/to/bitrix/composer-bx.json"
]
}
}
}
Вместо /path/to/bitrix/ вам нужно указать реальный путь до папки bitrix.
К этому вы можете добавить свои зависимости и настройки. Например, чтобы явно задать путь до папки vendor (по умолчанию она будет там же, где файл composer.json), используйте директиву "vendor-dir".
После описания своей конфигурации останется установить библиотеки:
composer install
Теперь вы можете использовать преимущества composer в своем проекте, подключая файл vendor/autoload.php. При использовании CLI-команд он будет подключен автоматически.
Шаг второй, валидация
Пример
public function isDataValidated(array $values): array {
$validator = Validation::createValidator();
$constraint = new Assert\Collection([
'fields' => [
'name' => new Assert\Length([
'min' => 20,
'max' => 255,
'minMessage' => 'Поле ФИО слишком короткое',
'maxMessage' => 'Поле ФИО слишком большое',
]),
'email' => new Assert\Email([
'message' => 'Поле ПОЧТА заполнено не правильно'
]),
'phone' => new Assert\Regex([
'pattern' => '/^\+7\d{10}$/',
'message' => 'Ваш номер не соответствует формату: +79999999999'
]),
'comment' => new Assert\Length([
'min' => 20,
'max' => 255,
'minMessage' => 'Поле КОММЕНТАРИЙ слишком короткое',
'maxMessage' => 'Поле КОММЕНТАРИЙ слишком большое',
]),
'birthdate' => new Assert\Date([
'message' => 'Поле ДАТА заполнено не правильно'
])
],
'allowExtraFields' => true,
]);
// Валидация данных
$violations = $validator->validate($values, $constraint);
$errorMessages = [];
foreach ($violations as $violation) {
$errorMessages[] = $violation->getMessage();
}
return $errorMessages;
}
1. Создание валидатора
$validator = Validation::createValidator();
Это стандартный способ создания экземпляра валидатора в Symfony. Внутри него используются предустановленные наборы правил для проверки данных.
2. Определение правил валидации
$constraint = new Assert\Collection([
'fields' => [
'name' => new Assert\Length([
'min' => 20,
'max' => 255,
'minMessage' => 'Поле ФИО слишком короткое',
'maxMessage' => 'Поле ФИО слишком большое',
]),
'email' => new Assert\Email([
'message' => 'Поле ПОЧТА заполнено не правильно'
]),
'phone' => new Assert\Regex([
'pattern' => '/^\+7\d{10}$/',
'message' => 'Ваш номер не соответствует формату: +79999999999'
]),
'comment' => new Assert\Length([
'min' => 20,
'max' => 255,
'minMessage' => 'Поле КОММЕНТАРИЙ слишком короткое',
'maxMessage' => 'Поле КОММЕНТАРИЙ слишком большое',
]),
'birthdate' => new Assert\Date([
'message' => 'Поле ДАТА заполнено не правильно'
])
],
'allowExtraFields' => true,
]);
Здесь используется класс Assert\Collection, который позволяет задавать правила валидации для набора полей. В данном случае проверяются поля: name, email, phone, comment и birthdate.
Правила валидации для каждого поля:
• name — Длина значения должна быть в диапазоне от 20 до 255 символов.
• Если длина меньше минимальной, выводится сообщение "Поле ФИО слишком короткое".
• Если длина превышает максимальную, выводится сообщение "Поле ФИО слишком большое".
• email — Используется Assert\Email, который проверяет, является ли значение корректным e-mail. Если проверка не проходит, выводится сообщение "Поле ПОЧТА заполнено не правильно".
• phone — Применяется регулярное выражение Assert\Regex, которое требует, чтобы номер телефона соответствовал формату +7XXXXXXXXXX (где X — цифры). Если формат не совпадает, выводится сообщение "Ваш номер не соответствует формату: +79999999999".
• comment — Длина комментария должна быть между 20 и 255 символами. Сообщения аналогичны полю name, но применимы к полю комментария.
• birthdate — Проверяется, что значение является датой в корректном формате (через Assert\Date). Если формат даты некорректен, выводится сообщение "Поле ДАТА заполнено не правильно".
Опция allowExtraFields
'allowExtraFields' => true,
Этот параметр указывает, что в массиве могут быть дополнительные поля, которые не описаны в правилах валидации. Если эта опция не будет установлена, наличие лишних полей вызовет ошибку.
3. Валидация данных
$violations = $validator->validate($values, $constraint);
Здесь происходит фактическая проверка данных. Метод validate принимает два аргумента:
• $values — массив данных, которые нужно проверить.
• $constraint — набор правил валидации, описанных ранее.
Метод возвращает объект, содержащий список всех нарушений (violations), если таковые имеются.
4. Обработка ошибок
$errorMessages = [];
foreach ($violations as $violation) {
$errorMessages[] = $violation->getMessage();
}
return $errorMessages;
Этот код проходит по всем найденным нарушениям и собирает их сообщения об ошибках в массив $errorMessages. В результате функция возвращает массив с текстами ошибок, если таковые имеются. Если валидация прошла успешно, возвращается пустой массив.
Asset's
- Assert\Blank
Проверяет, что значение является пустым. Полезно для случаев, когда поле должно быть пустым, например, при определенных условиях.
new Assert\Blank([ 'message' => 'Это поле должно быть пустым.', ])
- Assert\NotBlank
Проверяет, что значение не пустое. Часто используется для обязательных полей.
new Assert\NotBlank([ 'message' => 'Это поле не должно быть пустым.', ])
- Assert\NotNull
Проверяет, что значение не равно nul
new Assert\NotNull([ 'message' => 'Это поле не может быть null.', ])
- Assert\IsNull
Проверяет, что значение равно null.
new Assert\IsNull([ 'message' => 'Это поле должно быть null.', ])
- Assert\Length
Используется для проверки длины строк. Это правило уже используется в вашем примере.
new Assert\Length([ 'min' => 10, 'max' => 255, 'minMessage' => 'Минимальная длина поля 10 символов', 'maxMessage' => 'Максимальная длина поля 255 символов', ])
- Assert\Email
Проверяет, что строка является корректным email-адресом. Используется также в вашем примере.
new Assert\Email([ 'message' => 'Неверный формат email', ])
- Assert\Regex
Проверяет значение по регулярному выражению. Пример использования — проверка формата телефона (как в вашем примере).
new Assert\Regex([ 'pattern' => '/^+7\d{10}$/', 'message' => 'Номер телефона должен соответствовать формату +7XXXXXXXXXX', ])
- Assert\Choice
Проверяет, что значение входит в допустимый список вариантов.
new Assert\Choice([ 'choices' => ['male', 'female'], 'message' => 'Пол должен быть "male" или "female".', ])
- Assert\Date
Проверяет, что значение является корректной датой.
new Assert\Date([ 'message' => 'Некорректная дата', ])
- Assert\DateTime
Проверяет, что значение является корректным объектом даты и времени.
new Assert\DateTime([ 'message' => 'Некорректная дата и время', ])
- Assert\Time
Проверяет, что значение является корректным временем.
new Assert\Time([ 'message' => 'Некорректное время', ])
- Assert\Range
Проверяет, что значение находится в заданном диапазоне. Применимо как для чисел, так и для дат.
new Assert\Range([ 'min' => 18, 'max' => 99, 'minMessage' => 'Возраст должен быть не менее 18 лет', 'maxMessage' => 'Возраст должен быть не более 99 лет', ])
- Assert\Type
Проверяет, что значение имеет определенный тип данных (например, строка, число, массив и т.д.).
new Assert\Type([ 'type' => 'integer', 'message' => 'Значение должно быть целым числом', ])
- Assert\Url
Проверяет, что значение является корректным URL.
new Assert\Url([ 'message' => 'Некорректный URL', ])
- Assert\Ip
Проверяет, что значение является корректным IP-адресом (IPv4 или IPv6).
new Assert\Ip([ 'version' => 'all', // или 'ipv4' или 'ipv6' 'message' => 'Некорректный IP-адрес', ])
- Assert\Uuid
Проверяет, что значение является корректным UUID (уникальный идентификатор).
new Assert\Uuid([ 'message' => 'Некорректный UUID', ])
- Assert\Count
Проверяет количество элементов в массиве или коллекции.
new Assert\Count([ 'min' => 1, 'max' => 10, 'minMessage' => 'Должен быть хотя бы один элемент', 'maxMessage' => 'Максимум 10 элементов', ])
- Assert\Unique
Проверяет, что каждый элемент массива уникален.
new Assert\Unique([ 'message' => 'Значения должны быть уникальными', ])
- Assert\GreaterThan
Проверяет, что значение больше указанного числа или даты.
new Assert\GreaterThan([ 'value' => 18, 'message' => 'Значение должно быть больше 18', ])
- Assert\LessThan
Проверяет, что значение меньше указанного числа или даты.
new Assert\LessThan([ 'value' => 100, 'message' => 'Значение должно быть меньше 100', ])
- Assert\EqualTo
Проверяет, что значение равно указанному значению.
new Assert\EqualTo([ 'value' => 42, 'message' => 'Значение должно быть равно 42', ])
- Assert\IdenticalTo
Проверяет, что значение идентично (то есть с учетом типов) указанному значению.
new Assert\IdenticalTo([ 'value' => 42, 'message' => 'Значение должно быть идентично 42', ])
- Assert\DivisibleBy
Проверяет, что значение делится на заданное число без остатка.
new Assert\DivisibleBy([ 'value' => 5, 'message' => 'Значение должно делиться на 5', ])
- Assert\CardScheme
Проверяет, что значение соответствует номеру кредитной карты определенной схемы (Visa, MasterCard и т.д.).
new Assert\CardScheme([ 'schemes' => ['AMEX', 'VISA', 'MASTERCARD'], 'message' => 'Номер карты не соответствует поддерживаемой схеме', ])
- Assert\File
Проверяет, что значение является загруженным файлом, и можно задать дополнительные ограничения (размер файла, MIME-тип и т.д.).
new Assert\File([ 'maxSize' => '1024k', 'mimeTypes' => ['application/pdf', 'application/x-pdf'], 'mimeTypesMessage' => 'Пожалуйста, загрузите файл в формате PDF', ])
- Assert\Image
Проверяет, что загруженный файл является изображением, и можно задать ограничения на размеры.
new Assert\Image([ 'maxSize' => '2M', 'maxWidth' => 1024, 'maxHeight' => 768, 'mimeTypes' => ['image/jpeg', 'image/png'], 'mimeTypesMessage' => 'Пожалуйста, загрузите изображение в формате JPEG или PNG', ])
- Assert\Locale
Проверяет, что значение является корректной локалью.
new Assert\Locale([ 'message' => 'Некорректная локаль', ])