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

Дата обновления перевода 2023-01-14

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

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

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

See also

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

??????????? ? ???????? ??? ??????
????? Collection
????????? CollectionValidator

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 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 символов в длину, вам нужно сделать следующее:

  • Attributes
  • YAML
  • XML
  • 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
// src/Entity/Author.php
namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;

// IMPORTANT: nested attributes requires PHP 8.1 or higher
class Author
{
    #[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,
    )]
    protected $profileData = [
        'personal_email' => '...',
        'short_bio' => '...',
    ];
}

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

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

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

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

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

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

  • Attributes
  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// src/Entity/Author.php
namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;

class Author
{
    #[Assert\Collection(
        fields: [
            'personal_email' => new Assert\Required([
                new Assert\NotBlank,
                new Assert\Email,
            ]),
            'alternate_email' => new Assert\Optional(
                new Assert\Email
            ),
        ],
    )]
    protected $profileData = ['personal_email' => 'email@example.com'];
}

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

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

1
2
3
4
5
6
7
8
use Symfony\Component\Validator\Constraints as Assert;

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
$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 [опция по умолчанию ]

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

groups

type: array | string

It defines the validation group or groups of this constraint. Read more about validation groups.

missingFieldsMessage

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

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

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

???????? ????????
{{ field }} ???? ?????????????? ????, ????????????? ? fields

payload

тип: mixed по умолчанию: null

Эта опция может быть использована, чтобы добавить к ограничению произвольные данные, относящиеся к домену. Сконфигурированная нагрузка не используется компонентом Валидатор, но его обработка полностью зависит от вас.

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