Как применить только подмножество всех ваших ограничений валидации (группы валидации)

По умолчанию, при валидации объекта, все ограничения этого класса будут проверены на предмет того, действительно ли они подойдут. Однако, в некоторых случаях, вам понадобится валидировать объект только по отношению к некоторым ограничениям этого класса. Чтобы сделать это, вы можете организовать каждое ограничение в одну или более "групп валидации", а потом применить валидацию только к одной группе ограничений.

Например, представьте, что у вас есть класс User, который используется как при регистрации пользователя, так и при обновлении контактной информации позже:

  • Annotations
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // src/AppBundle/Entity/User.php
    namespace AppBundle\Entity;
    
    use Symfony\Component\Security\Core\User\UserInterface;
    use Symfony\Component\Validator\Constraints as Assert;
    
    class User implements UserInterface
    {
        /**
         * @Assert\Email(groups={"registration"})
         */
        private $email;
    
        /**
         * @Assert\NotBlank(groups={"registration"})
         * @Assert\Length(min=7, groups={"registration"})
         */
        private $password;
    
        /**
         * @Assert\Length(min=2)
         */
        private $city;
    }
    
  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    # src/AppBundle/Resources/config/validation.yml
    AppBundle\Entity\User:
        properties:
            email:
                - Email: { groups: [registration] }
            password:
                - NotBlank: { groups: [registration] }
                - Length: { min: 7, groups: [registration] }
            city:
                - Length:
                    min: 2
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    <!-- src/AppBundle/Resources/config/validation.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
            http://symfony.com/schema/dic/constraint-mapping
            http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd
        ">
    
        <class name="AppBundle\Entity\User">
            <property name="email">
                <constraint name="Email">
                    <option name="groups">
                        <value>registration</value>
                    </option>
                </constraint>
            </property>
    
            <property name="password">
                <constraint name="NotBlank">
                    <option name="groups">
                        <value>registration</value>
                    </option>
                </constraint>
                <constraint name="Length">
                    <option name="min">7</option>
                    <option name="groups">
                        <value>registration</value>
                    </option>
                </constraint>
            </property>
    
            <property name="city">
                <constraint name="Length">
                    <option name="min">7</option>
                </constraint>
            </property>
        </class>
    </constraint-mapping>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    // src/AppBundle/Entity/User.php
    namespace AppBundle\Entity;
    
    use Symfony\Component\Validator\Mapping\ClassMetadata;
    use Symfony\Component\Validator\Constraints as Assert;
    
    class User
    {
        public static function loadValidatorMetadata(ClassMetadata $metadata)
        {
            $metadata->addPropertyConstraint('email', new Assert\Email(array(
                'groups' => array('registration'),
            )));
    
            $metadata->addPropertyConstraint('password', new Assert\NotBlank(array(
                'groups' => array('registration'),
            )));
            $metadata->addPropertyConstraint('password', new Assert\Length(array(
                'min'    => 7,
                'groups' => array('registration'),
            )));
    
            $metadata->addPropertyConstraint('city', new Assert\Length(array(
                "min" => 3,
            )));
        }
    }
    

В такой конфигурации существует три группы валидации:

Default
Содержит ограничения в текущем классе и все упомянутые классы, которые не принадлежат ни к одной другой группе.
User
Эквивалентна всем ограничениям объекта User в группе Default. Это всегда является именем класса. Разица между этой группой и Default объясняется ниже.
registration
Содержит ограничения только полей email и password.

Ограничения в группе класса Default - это ограничения, которые либо не имеют явной сконфигурированной группы, или которые сконфигурированы в группу, равную имени класса или строке Default.

Caution

При валидации только объекта пользователя (User), не существует разницы между группами Default и User. Но разница существует, если User имеет встроенные объекты. Например, представьте, что User имеет свойство address, которое содержит некоторый объект Address, и что вы добавили ограничение Valid к этому свойству, чтобы оно было валидировано при валидации объекта User.

Если вы валидируете User. используя группу Default, то любые ограничения в классе Address, которые находятся в группе Default будут использованы. Но, если вы валидируете User, используя группу валидации User, тогда будут валидированы только ограничения класса Address.

Другими словами, группа Default и группа класса имени (например, User) идентичны, кроме случаев, когда класс встрое в другой объект, чем тот, валидация которого проводится.

Если у вас есть наследование (например, User extends BaseUser) и вы валидируете с классом имени подкласса (т.е. User), то все ограничения в User и BaseUser будут валидированы. Однако, если вы валидируете, используя базовый класс (т.е. BaseUser), то будут валидированы только ограничения по умолчанию в классе BaseUser.

Чтобы сообщить валидатору об использовании конкретной группы, передайте одно или более имён групп в качестве третьего аргумента метода validate():

1
$errors = $validator->validate($author, null, array('registration'));

Если не указана ни одна группа, будут применены все ограничения, принадлежащие группе Default

Конечно же, вы чаще будете работать с валидацией не напрямую, а через библиотеку форм. Для информации о том, как использовать группы валидации внутри форм, смотрите How to Define the Validation Groups to Use.

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.