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

UniqueEntity

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

See also

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

Note

Для того, чтобы использовать это ограничение, вам нужно установить symfony/doctrine-bridge с помощью Composer.

Применяется к классу
Опции
Класс UniqueEntity
Валидатор UniqueEntityValidator

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

Представьте, что у вас есть сущность User, которая имеет поле email. Вы можете использовать ограничение UniqueEntity, чтобы гарантировать, что поле email остаётся уникальным между всеми ограничениями в вашей таблице пользователей:

  • Annotations
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // src/Entity/User.php
    namespace App\Entity;
    
    use Doctrine\ORM\Mapping as ORM;
    
    // DON'T forget the following use statement!!!
    use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
    
    use Symfony\Component\Validator\Constraints as Assert;
    
    /**
     * @ORM\Entity
     * @UniqueEntity("email")
     */
    class User
    {
        /**
         * @ORM\Column(name="email", type="string", length=255, unique=true)
         * @Assert\Email
         */
        protected $email;
    }
    
  • Attributes
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // src/Entity/User.php
    namespace App\Entity;
    
    use Doctrine\ORM\Mapping as ORM;
    
    // DON'T forget the following use statement!!!
    use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
    
    use Symfony\Component\Validator\Constraints as Assert;
    
    /**
     * @ORM\Entity
     */
    #[UniqueEntity('email')]
    class User
    {
        /**
         * @ORM\Column(name="email", type="string", length=255, unique=true)
         */
        #[Assert\Email]
        protected $email;
    }
    
  • YAML
    1
    2
    3
    4
    5
    6
    7
    # config/validator/validation.yaml
    App\Entity\User:
        constraints:
            - Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity: email
        properties:
            email:
                - Email: ~
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    <!-- 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\User">
            <constraint name="Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity">
                <option name="fields">email</option>
            </constraint>
            <property name="email">
                <constraint name="Email"/>
            </property>
        </class>
    </constraint-mapping>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // src/Entity/User.php
    namespace App\Entity;
    
    // DON'T forget the following use statement!!!
    use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
    
    use Symfony\Component\Validator\Constraints as Assert;
    
    class User
    {
        public static function loadValidatorMetadata(ClassMetadata $metadata)
        {
            $metadata->addConstraint(new UniqueEntity([
                'fields' => 'email',
            ]));
    
            $metadata->addPropertyConstraint('email', new Assert\Email());
        }
    }
    

Caution

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

Caution

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

Опции

em

тип: string

Имя менеджера сущностей, используемого для создания запроса для определения уникальности. Если оно пустое, то правильный менеджер сущностей будетопределён для этого класса. По этой причине, эту опцию наверное лучше не использовать.

entityClass

тип: string

По умолчанию, запрос, выполняемый для гарантирования униикальности использования хранилища текущим экземпляром класса. Однако, в некоторых случаях, например, при использовании маршрутов наследия Doctrine, вам нужно выполнить запрос в другом хранилище. Используйте эту опцию, чтобы определить полное имя класса (FQCN) сущности Doctrine, связанной с хранилищем, которое вы хотите использовать.

errorPath

тип: string по умолчанию: Имя первого поля в fields

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

Рассмотрите этот пример:

  • 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
    // src/Entity/Service.php
    namespace App\Entity;
    
    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
    
    /**
     * @ORM\Entity
     * @UniqueEntity(
     *     fields={"host", "port"},
     *     errorPath="port",
     *     message="This port is already in use on that host."
     * )
     */
    class Service
    {
        /**
         * @ORM\ManyToOne(targetEntity="App\Entity\Host")
         */
        public $host;
    
        /**
         * @ORM\Column(type="integer")
         */
        public $port;
    }
    
  • Attributes
     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/Service.php
    namespace App\Entity;
    
    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
    
    /**
     * @ORM\Entity
     */
    #[UniqueEntity(
        fields: ['host', 'port'],
        errorPath: 'port',
        message: 'This port is already in use on that host.',
    )]
    class Service
    {
        /**
         * @ORM\ManyToOne(targetEntity="App\Entity\Host")
         */
        public $host;
    
        /**
         * @ORM\Column(type="integer")
         */
        public $port;
    }
    
  • YAML
    1
    2
    3
    4
    5
    6
    7
    # config/validator/validation.yaml
    App\Entity\Service:
        constraints:
            - Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity:
                fields: [host, port]
                errorPath: port
                message: 'This port is already in use on that host.'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <!-- 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\Service">
            <constraint name="Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity">
                <option name="fields">
                    <value>host</value>
                    <value>port</value>
                </option>
                <option name="errorPath">port</option>
                <option name="message">This port is already in use on that host.</option>
            </constraint>
        </class>
    
    </constraint-mapping>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // src/Entity/Service.php
    namespace App\Entity;
    
    use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
    use Symfony\Component\Validator\Mapping\ClassMetadata;
    
    class Service
    {
        public $host;
        public $port;
    
        public static function loadValidatorMetadata(ClassMetadata $metadata)
        {
            $metadata->addConstraint(new UniqueEntity([
                'fields' => ['host', 'port'],
                'errorPath' => 'port',
                'message' => 'This port is already in use on that host.',
            ]));
        }
    }
    

Теперь, сообщение будет привязано к полю port с этой конфигурацией.

fields

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

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

Если вам нужно требовать, чтобы два поля были уникальны индивидуально (например, уникальный email и уникальный username), то вы используете две записи UniqueEntity, каждую с одним полем.

groups

type: array | string

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

ignoreNull

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

Если эта опция установлена, как true, то ограничение позволит нескольким сущностям иметь в поле значение null, а валидация будет успешной. Если установлена, как false, то позволено только одно значение null - если вторая сущность также имеет значение null, валидация будет неудачной.

message

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

Сообщение, отображаемое, когда ограничение неудачно. Это сообщение всегда привязано к первому полю, вызывающему нарушение. При использовании нескольких полей в ограничении, отображение можно указать через свойство errorPath.

Сообщения могут включать в себя заполнитель {{ value }}, чтобы отображать строчное представление невалидной записи. Если запись не определяет метод __toString(), то будет использовано следующее общее значение: “Объект класса __CLASS__ идентифицируется <comma separated IDs>”

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

Параметр Описание
{{ value }} Текушее (невалидное) значение
{{ label }} Соответствующий ярлык поля формы

New in version 5.2: Параметр {{ label }} был представлен в Symfony 5.2.

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.

repositoryMethod

тип: string по умолчанию: findBy()

Имя метода хранилища, используемого для определения уникальности. Если оно пустое, то будет использован findBy(). Этот метод в качестве аргумента получает ассоциативный массив fieldName => value (где fieldName - это каждое из полей, сконфигурированных в опции fields). Метод должен возвращать исчислимую PHP-переменную.

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