Collection

Это ограничение используется, когда основоположные данные являются коллекцией (т.е. массивом или объектом, реализующим Traversable и ArrayAccess), но вы хотите валидировать разные ключи этой коллекции разными способами. Например, вы можете валидировать ключ email, используя ограничение Email, а ключ коллекции inventory с огранчением Range.

Это ограничение также может убедиться в том, что определённые ключи коллекции присутствуют, и что отсутствуют лишние ключи.

Применяется к свойству или методу
Опции
Класс Collection
Валидатор CollectionValidator

Базовое применение

Ограничение Collection позволяет вам валидировать разные ключи коллекции по-отдельности. Рассмотрите следующий пример:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// src/AppBundle/Entity/Author.php
namespace AppBundle\Entity;

class Author
{
    protected $profileData = array(
        'personal_email' => '...',
        'short_bio' => '...',
    );

    public function setProfileData($key, $value)
    {
        $this->profileData[$key] = $value;
    }
}

Чтобы валидировать то, что элемент personal_email свойства массива profileData является валидным адресом электронной почты, и что элемент short_bio не пустой, но при этом не превышает 100 символов в длину, вам нужно сделать следующее:

  • 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
    25
    26
    27
    // src/AppBundle/Entity/Author.php
    namespace AppBundle\Entity;
    
    use Symfony\Component\Validator\Constraints as Assert;
    
    class Author
    {
        /**
         * @Assert\Collection(
         *     fields = {
         *         "personal_email" = @Assert\Email,
         *         "short_bio" = {
         *             @Assert\NotBlank(),
         *             @Assert\Length(
         *                 max = 100,
         *                 maxMessage = "Your short bio is too long!"
         *             )
         *         }
         *     },
         *     allowMissingFields = true
         * )
         */
         protected $profileData = array(
             'personal_email' => '...',
             'short_bio' => '...',
         );
    }
    
  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    # src/AppBundle/Resources/config/validation.yml
    AppBundle\Entity\Author:
        properties:
            profileData:
                - Collection:
                    fields:
                        personal_email: Email
                        short_bio:
                            - NotBlank
                            - Length:
                                max:   100
                                maxMessage: Your short bio is too long!
                    allowMissingFields: true
    
  • 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
    <!-- 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\Author">
            <property name="profileData">
                <constraint name="Collection">
                    <option name="fields">
                        <value key="personal_email">
                            <constraint name="Email" />
                        </value>
                        <value key="short_bio">
                            <constraint name="NotBlank" />
                            <constraint name="Length">
                                <option name="max">100</option>
                                <option name="maxMessage">Your short bio is too long!</option>
                            </constraint>
                        </value>
                    </option>
                    <option name="allowMissingFields">true</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/Author.php
    namespace AppBundle\Entity;
    
    use Symfony\Component\Validator\Mapping\ClassMetadata;
    use Symfony\Component\Validator\Constraints as Assert;
    
    class Author
    {
        private $options = array();
    
        public static function loadValidatorMetadata(ClassMetadata $metadata)
        {
            $metadata->addPropertyConstraint('profileData', new Assert\Collection(array(
                'fields' => array(
                    'personal_email' => new Assert\Email(),
                    'short_bio' => array(
                        new Assert\NotBlank(),
                        new Assert\Length(array(
                            'max' => 100,
                            'maxMessage' => 'Your short bio is too long!',
                        )),
                    ),
                ),
                'allowMissingFields' => true,
            )));
        }
    }
    

Наличие и отсутствие полей

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

Если вы хотите разрешить отсутствие ключей в коллекции, или вы хотите позволить "дополнительные" ключи в коллекции, то вы можете соответственно изменить опции allowMissingFields и allowExtraFields. В примере выше, опция allowMissingFields была установлена, как "true", что означает, что если бы в свойстве $personalData отсутствовал элемент personal_email или short_bio, то ошибки валидации бы не произошло.

Обязательные и необязательные ограничения поля

Ограничения полей в коллекции можно обернуть в ограничение Required или Optional, чтобы контролировать, должны ли они быть применены всегда (Required), или только при наличии поля (Optional).

Например, если вы хотите требовать, чтобы поле personal_email массива profileData не было пустым и являлось валидным адресом электронной почты, а поле alternate_email было необязательным, но являлось валидным адресом электронной почты в случае его заполнения, вы можете сделать следующее:

  • Annotations
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    // src/AppBundle/Entity/Author.php
    namespace AppBundle\Entity;
    
    use Symfony\Component\Validator\Constraints as Assert;
    
    class Author
    {
        /**
         * @Assert\Collection(
         *     fields={
         *         "personal_email"  = @Assert\Required({@Assert\NotBlank, @Assert\Email}),
         *         "alternate_email" = @Assert\Optional(@Assert\Email)
         *     }
         * )
         */
         protected $profileData = array('personal_email');
    }
    
  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    # src/AppBundle/Resources/config/validation.yml
    AppBundle\Entity\Author:
        properties:
            profile_data:
                - Collection:
                    fields:
                        personal_email:
                            - Required
                                - NotBlank: ~
                                - Email: ~
                        alternate_email:
                            - Optional:
                                - Email: ~
    
  • 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
    <!-- 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\Author">
            <property name="profile_data">
                <constraint name="Collection">
                    <option name="fields">
                        <value key="personal_email">
                            <constraint name="Required">
                                <constraint name="NotBlank" />
                                <constraint name="Email" />
                            </constraint>
                        </value>
                        <value key="alternate_email">
                            <constraint name="Optional">
                                <constraint name="Email" />
                            </constraint>
                        </value>
                    </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
    // src/AppBundle/Entity/Author.php
    namespace AppBundle\Entity;
    
    use Symfony\Component\Validator\Mapping\ClassMetadata;
    use Symfony\Component\Validator\Constraints as Assert;
    
    class Author
    {
        protected $profileData = array('personal_email');
    
        public static function loadValidatorMetadata(ClassMetadata $metadata)
        {
            $metadata->addPropertyConstraint('profileData', new Assert\Collection(array(
                'fields' => array(
                    'personal_email'  => new Assert\Required(
                        array(new Assert\NotBlank(), new Assert\Email())
                    ),
                    'alternate_email' => new Assert\Optional(new Assert\Email()),
                ),
            )));
        }
    }
    

Даже если allowMissingFields не установлен, как "true", вы теперь можете полностью опустить свойство alternate_email из массива profileData, так как оно Optional. Однакое, если поле personal_email не существует в массиве, то ограничение NotBlank всё равно будет применено (так как оно обёрнуто в Required) и вы получите нарушение ограничения.

Опции

fields

тип: array [default option]

This option is required and is an associative array defining all of the keys in the collection and, for each key, exactly which validator(s) should be executed against that element of the collection.

allowExtraFields

тип: boolean по умолчанию: false

Если эта опция установлена, как false, а основоположная коллекция содержит один или более элементов, не включённых в опцию fields, будет возвращена ошибка валидации. Если установлена, как true, дополнительные поля допустимы.

extraFieldsMessage

тип: boolean по умолчанию: Поля {{ fields }} не ожидались.

Сообщение, отображаемое, если allowExtraFields - "false", и обнаружено дополнительное поле.

allowMissingFields

тип: boolean по умолчанию: false

Если эта опция установлена, как false, и одно или более полей из опции fields отсутствуют в освноположной коллекции, будет возвращена ошибка валидации. Если установленка, как true, то отсутствие некоторых полей опции fields в основоположной коллекции допускается.

missingFieldsMessage

тип: boolean по умолчанию: Поля {{ fields }} отсутствуют.

Сообщение, отображаемое, если allowMissingFields - "false", и одно или более полей отсутствуют в основоположной коллекции.

payload

type: mixed default: null

This option can be used to attach arbitrary domain-specific data to a constraint. The configured payload is not used by the Validator component, but its processing is completely up to you.

For example, you may want to use several error levels to present failed constraints differently in the front-end depending on the severity of the error.

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