Skip to content

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

  1. Assert\Blank

Проверяет, что значение является пустым. Полезно для случаев, когда поле должно быть пустым, например, при определенных условиях.

new Assert\Blank([ 'message' => 'Это поле должно быть пустым.', ])
  1. Assert\NotBlank

Проверяет, что значение не пустое. Часто используется для обязательных полей.

new Assert\NotBlank([ 'message' => 'Это поле не должно быть пустым.', ])
  1. Assert\NotNull

Проверяет, что значение не равно nul

new Assert\NotNull([ 'message' => 'Это поле не может быть null.', ])
  1. Assert\IsNull

Проверяет, что значение равно null.

new Assert\IsNull([ 'message' => 'Это поле должно быть null.', ])
  1. Assert\Length

Используется для проверки длины строк. Это правило уже используется в вашем примере.

new Assert\Length([ 'min' => 10, 'max' => 255, 'minMessage' => 'Минимальная длина поля 10 символов', 'maxMessage' => 'Максимальная длина поля 255 символов', ])
  1. Assert\Email

Проверяет, что строка является корректным email-адресом. Используется также в вашем примере.

new Assert\Email([ 'message' => 'Неверный формат email', ])
  1. Assert\Regex

Проверяет значение по регулярному выражению. Пример использования — проверка формата телефона (как в вашем примере).

new Assert\Regex([ 'pattern' => '/^+7\d{10}$/', 'message' => 'Номер телефона должен соответствовать формату +7XXXXXXXXXX', ])
  1. Assert\Choice

Проверяет, что значение входит в допустимый список вариантов.

new Assert\Choice([ 'choices' => ['male', 'female'], 'message' => 'Пол должен быть "male" или "female".', ])
  1. Assert\Date

Проверяет, что значение является корректной датой.

new Assert\Date([ 'message' => 'Некорректная дата', ])
  1. Assert\DateTime

Проверяет, что значение является корректным объектом даты и времени.

new Assert\DateTime([ 'message' => 'Некорректная дата и время', ])
  1. Assert\Time

Проверяет, что значение является корректным временем.

new Assert\Time([ 'message' => 'Некорректное время', ])
  1. Assert\Range

Проверяет, что значение находится в заданном диапазоне. Применимо как для чисел, так и для дат.

new Assert\Range([ 'min' => 18, 'max' => 99, 'minMessage' => 'Возраст должен быть не менее 18 лет', 'maxMessage' => 'Возраст должен быть не более 99 лет', ])
  1. Assert\Type

Проверяет, что значение имеет определенный тип данных (например, строка, число, массив и т.д.).

new Assert\Type([ 'type' => 'integer', 'message' => 'Значение должно быть целым числом', ])
  1. Assert\Url

Проверяет, что значение является корректным URL.

new Assert\Url([ 'message' => 'Некорректный URL', ])
  1. Assert\Ip

Проверяет, что значение является корректным IP-адресом (IPv4 или IPv6).

new Assert\Ip([ 'version' => 'all', // или 'ipv4' или 'ipv6' 'message' => 'Некорректный IP-адрес', ])
  1. Assert\Uuid

Проверяет, что значение является корректным UUID (уникальный идентификатор).

new Assert\Uuid([ 'message' => 'Некорректный UUID', ])
  1. Assert\Count

Проверяет количество элементов в массиве или коллекции.

new Assert\Count([ 'min' => 1, 'max' => 10, 'minMessage' => 'Должен быть хотя бы один элемент', 'maxMessage' => 'Максимум 10 элементов', ])
  1. Assert\Unique

Проверяет, что каждый элемент массива уникален.

new Assert\Unique([ 'message' => 'Значения должны быть уникальными', ])
  1. Assert\GreaterThan

Проверяет, что значение больше указанного числа или даты.

new Assert\GreaterThan([ 'value' => 18, 'message' => 'Значение должно быть больше 18', ])
  1. Assert\LessThan

Проверяет, что значение меньше указанного числа или даты.

new Assert\LessThan([ 'value' => 100, 'message' => 'Значение должно быть меньше 100', ])
  1. Assert\EqualTo

Проверяет, что значение равно указанному значению.

new Assert\EqualTo([ 'value' => 42, 'message' => 'Значение должно быть равно 42', ])
  1. Assert\IdenticalTo

Проверяет, что значение идентично (то есть с учетом типов) указанному значению.

new Assert\IdenticalTo([ 'value' => 42, 'message' => 'Значение должно быть идентично 42', ])
  1. Assert\DivisibleBy

Проверяет, что значение делится на заданное число без остатка.

new Assert\DivisibleBy([ 'value' => 5, 'message' => 'Значение должно делиться на 5', ])
  1. Assert\CardScheme

Проверяет, что значение соответствует номеру кредитной карты определенной схемы (Visa, MasterCard и т.д.).

new Assert\CardScheme([ 'schemes' => ['AMEX', 'VISA', 'MASTERCARD'], 'message' => 'Номер карты не соответствует поддерживаемой схеме', ])
  1. Assert\File

Проверяет, что значение является загруженным файлом, и можно задать дополнительные ограничения (размер файла, MIME-тип и т.д.).

new Assert\File([ 'maxSize' => '1024k', 'mimeTypes' => ['application/pdf', 'application/x-pdf'], 'mimeTypesMessage' => 'Пожалуйста, загрузите файл в формате PDF', ])
  1. Assert\Image

Проверяет, что загруженный файл является изображением, и можно задать ограничения на размеры.

new Assert\Image([ 'maxSize' => '2M', 'maxWidth' => 1024, 'maxHeight' => 768, 'mimeTypes' => ['image/jpeg', 'image/png'], 'mimeTypesMessage' => 'Пожалуйста, загрузите изображение в формате JPEG или PNG', ])
  1. Assert\Locale

Проверяет, что значение является корректной локалью.

new Assert\Locale([ 'message' => 'Некорректная локаль', ])