Description
The current code from https://symfony.com/doc/4.4/reference/constraints/Traverse.html:
<?php
// src/Entity/Book.php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity
* @Assert\Traverse
*/
class Book
{
/**
* @var Author
*
* @ORM\ManyToOne(targetEntity="App\Entity\Author")
*/
protected $author;
/**
* @var Editor
*
* @ORM\ManyToOne(targetEntity="App\Entity\Editor")
*/
protected $editor;
// ...
}
throws a \Symfony\Component\Validator\Exception\ConstraintDefinitionException
with message Traversal was enabled for "App\Entity\Book", but this class does not implement "\Traversable".
(from vendor/symfony/validator/Validator/RecursiveContextualValidator.php
).
From symfony/symfony#10287:
Control traversal at class level (symfony/symfony#8617)
Currently, it is possible whether to traverse a
Traversable
object or not in theValid
constraint:/** * @Assert\Valid(traverse=true) */ private $tags = new TagList();
(actually,
true
is the default)In this way, the validator will iterate the
TagList
instance and validate each of the contained objects. You can also set "traverse" tofalse
to disable iteration.What if you want to specify, that
TagList
instances should always (or never) be traversed? That's currently not possible.With this PR, you can do the following:
/** * @Assert\Traverse(false) */ class TagList implements \IteratorAggregate { // ... }
I understand that the Traverse
constraint is not at all a "shorthand" for Valid
constraints on all nested objects, but rather a means to always disable validator traversal on a custom \Traversable
class. (But I may be wrong)