Дата обновления перевода 2021-06-08

Коллекция (Collection)

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

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

See also

Если вы хотите валидировать, что все элементы коллекции уникальны, используйте ограничение уникальности (Unique).

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

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

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

// src/Entity/Author.php
namespace App\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/Entity/Author.php
    namespace App\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 = [
            'personal_email' => '...',
            'short_bio' => '...',
        ];
    }
    
  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    # config/validator/validation.yaml
    App\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
    <!-- config/validator/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 https://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
    
        <class name="App\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
    // src/Entity/Author.php
    namespace App\Entity;
    
    use Symfony\Component\Validator\Constraints as Assert;
    use Symfony\Component\Validator\Mapping\ClassMetadata;
    
    class Author
    {
        public static function loadValidatorMetadata(ClassMetadata $metadata)
        {
            $metadata->addPropertyConstraint('profileData', new Assert\Collection([
                'fields' => [
                    'personal_email' => new Assert\Email(),
                    'short_bio' => [
                        new Assert\NotBlank(),
                        new Assert\Length([
                            '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/Entity/Author.php
    namespace App\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 = ['personal_email' => '[email protected]'];
    }
    
  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    # config/validator/validation.yaml
    App\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
    <!-- config/validator/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 https://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
    
        <class name="App\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
    23
    // src/Entity/Author.php
    namespace App\Entity;
    
    use Symfony\Component\Validator\Constraints as Assert;
    use Symfony\Component\Validator\Mapping\ClassMetadata;
    
    class Author
    {
        protected $profileData = ['personal_email'];
    
        public static function loadValidatorMetadata(ClassMetadata $metadata)
        {
            $metadata->addPropertyConstraint('profileData', new Assert\Collection([
                'fields' => [
                    'personal_email'  => new Assert\Required([
                        new Assert\NotBlank(),
                        new Assert\Email(),
                    ]),
                    'alternate_email' => new Assert\Optional(new Assert\Email()),
                ],
            ]));
        }
    }
    

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

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

use Symfony\Component\Validator\Constraints as Assert;

$constraint = new Assert\Collection([
    'fields' => [
        'name' => new Assert\NotBlank(['groups' => 'basic']),
        'email' => new Assert\NotBlank(['groups' => 'contact']),
    ],
]);

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

$constraint = new Assert\Collection([
    'fields' => [
        'name' => new Assert\Required([
            'constraints' => new Assert\NotBlank(['groups' => 'basic']),
            'groups' => ['basic', 'strict'],
        ]),
        'email' => new Assert\Required([
            "constraints" => new Assert\NotBlank(['groups' => 'contact']),
            'groups' => ['basic', 'strict'],
        ]),
    ],
    'groups' => ['basic', 'strict'],
]);

Опция по умолчанию allowMissingFields требует полей во всех группах. Поэтому, когда вы валидируете в группе contact, $name может быть пустым, но ключ все равно будет необходим. Если это не то поведение, которого вы хотите, ясно используйте ограничение Optional вместо Required.

Опции

allowExtraFields

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

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

allowMissingFields

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

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

extraFieldsMessage

тип: string по умолчанию: Это поле не ожидалось.

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

Вы можете использовать следующие параметры в этом сообщении:

Параметр Описание
{{ field }} Ключ определенного дополнительного поля

fields

тип: array [опция по умолчанию]

Эта опция обязательна и является ассоциативным массивом, определяющим все ключи в коллекции, и, для каждого ключа, какой конкретно валидатор(ы) должен быть выполнен для этого элемента коллекции.

missingFieldsMessage

тип: string по умолчанию: Это поле потсутствует.

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

Вы можете использовать следующие параметры в этом сообщении:

Параметр Описание
{{ field }} Ключ отсутствующего поля, определенного в fields

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.