Symfony 2.6. Как создать пользовательский Validation Constraint.

Вы можете создать собственный валидационный фильтр путем расширения базового класса фильтраConstraint. Например, вы собираетесь создать простой валидатор, который проверяет, содержит ли строка только буквы и цифры.

Создание класса фильтра

Прежде всего, необходимо создать класс фильтра и отнаследоваться от Constraint:

// src/AppBundle/Validator/Constraints/ContainsAlphanumeric.php
namespace AppBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class ContainsAlphanumeric extends Constraint
{
    public $message = 'The string "%string%" contains an illegal character: it can only contain letters or numbers.';
}
Аннотации @Annotation необходимые для этого нового ограничения для того, 
чтобы сделать его доступным для использования в классах через аннотации. 
Опции для вашего фильтра представлены в качестве открытых свойств класса фильтра.

Создание самого валидатора

Как вы можете видеть, ограничение класса довольно минимальны. Фактическая проверка осуществляется другим классом «constraint validator». Класс фильтра валидатора, содержит метод валидатора validatedBy(), который, по умолчанию, содержит в себе некий простой код:

// in the base Symfony\Component\Validator\Constraint class
public function validatedBy()
{
    return get_class($this).'Validator';
}

Другими словами, если вы создаете пользовательский ограничение (например, MyConstraint), Symfony будет автоматически искать другой класс, MyConstraintValidator, который, фактически выполняет проверку.

Класс проверки также прост, и имеет только один обязательный метод validate():

// src/AppBundle/Validator/Constraints/ContainsAlphanumericValidator.php
namespace AppBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class ContainsAlphanumericValidator extends ConstraintValidator
{
    public function validate($value, Constraint $constraint)
    {
        if (!preg_match('/^[a-zA-Za0-9]+$/', $value, $matches)) {
            // If you're using the new 2.5 validation API (you probably are!)
            $this->context->buildViolation($constraint->message)
                ->setParameter('%string%', $value)
                ->addViolation();

            // If you're using the old 2.4 validation API
            /*
            $this->context->addViolation(
                $constraint->message,
                array('%string%' => $value)
            );
            */
        }
    }
}

Внутри validate, вам не нужно возвращать значение. Вместо этого, вы добавляете варианты нарушений проверок в свойства context валидатора и значение будет считаться действительным, если оно не вызывает каких-либо нарушений. Метод buildViolation принимает сообщение об ошибке в качестве аргумента и возвращает экземпляр ConstraintViolationBuilderInterface. Вызов метода addViolation, наконец, добавляет нарушение в контекст.

Способ buildViolation был добавлен в Symfony 2.5. Примеры использования 
с более старыми версиями Symfony приведены на соответствующих этой версии 
странице документации.

 Использование нового валидатора

Использовать пользовательские валидаторы очень легко, так же, как и встроенные в Symfony:

// src/AppBundle/Entity/AcmeEntity.php
use Symfony\Component\Validator\Constraints as Assert;
use AppBundle\Validator\Constraints as AcmeAssert;

class AcmeEntity
{
    // ...

    /**
     * @Assert\NotBlank
     * @AcmeAssert\ContainsAlphanumeric
     */
    protected $name;

    // ...
}

Если ваш ограничение содержит параметры, то они должны быть открытыми свойствами пользовательского класса Constraint, который вы создали ранее. Эти параметры могут быть настроены как параметры ограничений для ядра Symfony.

Ограничение валидаторов с зависимостями

Если ваш валидатор имеет зависимости, например, подключения к базе данных, он должен быть настроен в качестве службы контейнера внедрения зависимостей. Эта служба должна включать в себя тег validator.constraint_validator  и атрибут псевдоним:

# app/config/services.yml
services:
    validator.unique.your_validator_name:
        class: Fully\Qualified\Validator\Class\Name
        tags:
            - { name: validator.constraint_validator, alias: alias_name }

Теперь Ваш класс ограничения должны использовать этот псевдоним, чтобы ссылаться на соответствующий валидатор:

public function validatedBy()
{
    return 'alias_name';
}

Как упоминалось выше, Symfony будет автоматически искать класса ограничения, содержащий соответствующие средства проверки. Если ваш валидатор указан в качестве службы, важно переопределить метод validatedBy () для возврата псевдонима, который использоваться при определении вашего сервиса, в противном случае Symfony не будет использовать ваш сервис, и экземпляр класса будет использоваться без указанных зависимостей.

Класс Constraint Validator

Кроме проверки свойств класса, ограничение может иметь область , указывающую на своей Constraint класс:

public function getTargets()
{
    return self::CLASS_CONSTRAINT;
}

При этом, метод validate() валидатора получает  объект в качестве первого аргумента:

class ProtocolClassValidator extends ConstraintValidator
{
    public function validate($protocol, Constraint $constraint)
    {
        if ($protocol->getFoo() != $protocol->getBar()) {
            // If you're using the new 2.5 validation API (you probably are!)
            $this->context->buildViolation($constraint->message)
                ->atPath('foo')
                ->addViolation();

            // If you're using the old 2.4 validation API
            /*
            $this->context->addViolationAt(
                'foo',
                $constraint->message,
                array(),
                null
            );
            */
        }
    }
}

Обратите внимание, что ограничение класса валидатора применяется для самого класса, а не для его свойства:

# src/AppBundle/Resources/config/validation.yml
AppBundle\Entity\AcmeEntity:
    constraints:
        - AppBundle\Validator\Constraints\ContainsAlphanumeric: ~

Symfony 2.6. Как создать пользовательский Validation Constraint.: 1 комментарий

Добавить комментарий

Ваш адрес email не будет опубликован.

17 + семь =