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

Traverse

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

Применяется класс
к опциям
Класс Traverse

Базовое использование

В следующем примере, создайте два класса BookCollection и Book, которые имеют все ограничения в своих свойствах.

  • 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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    // src/Entity/BookCollection.php
    namespace App\Entity;
    
    use Doctrine\Common\Collections\ArrayCollection;
    use Doctrine\Common\Collections\Collection
    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Component\Validator\Constraints as Assert;
    
    /**
     * @ORM\Entity
     * @Assert\Traverse
     */
    class BookCollection implements \IteratorAggregate
    {
        /**
         * @var string
         *
         * @ORM\Column
         *
         * @Assert\NotBlank
         */
        protected $name = '';
    
        /**
         * @var Collection|Book[]
         *
         * @ORM\ManyToMany(targetEntity="App\Entity\Book")
         */
        protected $books;
    
        // некоторые другие свойства
    
        public function __construct()
        {
            $this->books = new ArrayCollection();
        }
    
        // ... setter для имени, adder и remover для книг
    
        // имя может быть валидировано путем вызова геттера
        public function getName(): string
        {
            return $this->name;
        }
    
        /**
         * @return \Generator|Book[] The books for a given author
         */
        public function getBooksForAuthor(Author $author): iterable
        {
            foreach ($this->books as $book) {
                if ($book->isAuthoredBy($author)) {
                    yield $book;
                }
            }
        }
    
        // ни один из методов выше, или любой другой, не имеют конкретного геттера
        // могут быть использованы для валидации всех вложенных книг;
        // этот объект должен быть траверсирован для вызова итератора
        public function getIterator()
        {
            return $this->books->getIterator();
        }
    }
    
  • 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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    // src/Entity/BookCollection.php
    namespace App\Entity;
    
    use Doctrine\Common\Collections\ArrayCollection;
    use Doctrine\Common\Collections\Collection
    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Component\Validator\Constraints as Assert;
    
    /**
     * @ORM\Entity
     */
    #[Assert\Traverse]
    class BookCollection implements \IteratorAggregate
    {
        /**
         * @var string
         *
         * @ORM\Column
         */
        #[Assert\NotBlank]
        protected $name = '';
    
        /**
         * @var Collection|Book[]
         *
         * @ORM\ManyToMany(targetEntity="App\Entity\Book")
         */
        protected $books;
    
        //  некоторые другие свойства
    
        public function __construct()
        {
            $this->books = new ArrayCollection();
        }
    
        // ... setter для имени, adder и remover для книг
    
        // имя может быть валидировано путем вызова геттера
        public function getName(): string
        {
            return $this->name;
        }
    
        /**
         * @return \Generator|Book[] The books for a given author
         */
        public function getBooksForAuthor(Author $author): iterable
        {
            foreach ($this->books as $book) {
                if ($book->isAuthoredBy($author)) {
                    yield $book;
                }
            }
        }
    
        // ни один из методов выше, или любой другой, не имеют конкретного геттера
        // могут быть использованы для валидации всех вложенных книг;
        // этот объект должен быть траверсирован для вызова итератора
        public function getIterator()
        {
            return $this->books->getIterator();
        }
    }
    
  • YAML
    1
    2
    3
    4
    # config/validator/validation.yaml
    App\Entity\BookCollection:
        constraints:
            - Traverse: ~
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    <!-- 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\BookCollection">
            <constraint name="Traverse"/>
        </class>
    </constraint-mapping>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    // src/Entity/BookCollection.php
    namespace App\Entity;
    
    use Symfony\Component\Validator\Constraints as Assert;
    use Symfony\Component\Validator\Mapping\ClassMetadata;
    
    class BookCollection
    {
        // ...
    
        public static function loadValidatorMetadata(ClassMetadata $metadata)
        {
            $metadata->addConstraint(new Assert\Traverse());
        }
    }
    

Когда объект реализует \Traversable (как здесь, с дочерним \IteratorAggregate), его стратегия траверсирования будет установлена безусловно, а объект будет итерирован без определения ограничения. Это полезнее всего добавлять для ясности или для отключения траверсирования, используя опцию traverse. Если публичный геттер существует для возвращения внутренней коллекции книг, вроде getBooks(): Collection, вместо этого может быть использовано ограничение Valid в свойстве $books.

Опции

Опция groups недоступна для этого ограничения.

traverse

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

Экземпляры \Traversable траверсируются по умолчанию, используйте эту опцию, чтобы отключить валидацию:

  • Annotations
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    // src/Entity/BookCollection.php
    
    // ... same as above
    
    /**
     * ...
     * @Assert\Traverse(false)
     */
     class BookCollection implements \IteratorAggregate
     {
         // ...
     }
    
  • Attributes
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    // src/Entity/BookCollection.php
    
    // ... то же, что и выше
    
    /**
     * ...
     */
     #[Assert\Traverse(false)]
     class BookCollection implements \IteratorAggregate
     {
         // ...
     }
    
  • YAML
    1
    2
    3
    4
    # config/validator/validation.yaml
    App\Entity\BookCollection:
        constraints:
            - Traverse: false
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    <!-- 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\BookCollection">
            <constraint name="Traverse">false</constraint>
        </class>
    </constraint-mapping>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    // src/Entity/BookCollection.php
    namespace App\Entity;
    
    use Symfony\Component\Validator\Constraints as Assert;
    use Symfony\Component\Validator\Mapping\ClassMetadata;
    
    class BookCollection
    {
        // ...
    
        public static function loadValidatorMetadata(ClassMetadata $metadata)
        {
            $metadata->addConstraint(new Assert\Traverse(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.