Skip to content

Commit 3ff0acd

Browse files
committed
[Validator] Fixed Traverse constraint reference
1 parent 2a475ba commit 3ff0acd

File tree

1 file changed

+63
-23
lines changed

1 file changed

+63
-23
lines changed

reference/constraints/Traverse.rst

Lines changed: 63 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
Traverse
22
========
33

4-
Objects do not validate nested objects by default unless explicitly using
5-
this constraint.
6-
If only specific nested objects should be validated by cascade, consider
7-
using the :doc:`/reference/constraints/Valid` instead.
4+
Objects properties are only validated if they are accessible, either by being
5+
public or having public accessor methods (e.g a public getter).
6+
If your object needs to be traversed to validate its data, you can use this
7+
constraint.
88

99
+----------------+-------------------------------------------------------------------------------------+
1010
| Applies to | :ref:`class <validation-class-target>` |
@@ -17,17 +17,14 @@ using the :doc:`/reference/constraints/Valid` instead.
1717
Basic Usage
1818
-----------
1919

20-
In the following example, create three classes ``Book``, ``Author`` and
21-
``Editor`` that all have constraints on their properties. Furthermore,
22-
``Book`` stores an ``Author`` and an ``Editor`` instance that must be
23-
valid too. Instead of adding the ``Valid`` constraint to both fields,
24-
configure the ``Traverse`` constraint on the ``Book`` class.
20+
In the following example, create two classes ``BookCollection`` and ``Book``
21+
that all have constraints on their properties.
2522

2623
.. configuration-block::
2724

2825
.. code-block:: php-annotations
2926
30-
// src/AppBundle/Entity/Book.php
27+
// src/AppBundle/Entity/BookCollection.php
3128
namespace AppBundle\Entity;
3229
3330
use Doctrine\ORM\Mapping as ORM;
@@ -37,31 +34,66 @@ configure the ``Traverse`` constraint on the ``Book`` class.
3734
* @ORM\Entity
3835
* @Assert\Traverse
3936
*/
40-
class Book
37+
class BookCollection implements \IteratorAggregate
4138
{
4239
/**
43-
* @var Author
40+
* @var string
41+
*
42+
* @ORM\Column
4443
*
45-
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Author")
44+
* @Assert\NotBlank
4645
*/
47-
protected $author;
46+
protected $name = '';
4847
4948
/**
50-
* @var Editor
49+
* @var Book[]
5150
*
52-
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Editor")
51+
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Book")
5352
*/
54-
protected $editor;
53+
protected $books;
5554
56-
// ...
55+
// some other properties
56+
57+
public function __construct()
58+
{
59+
$this->books = new ArrayCollection();
60+
}
61+
62+
// ... setter for name, adder and remover for books
63+
64+
// the name can be validated by calling the getter
65+
public function getName(): string
66+
{
67+
return $this->name;
68+
}
69+
70+
/**
71+
* @return Book[]|\Generator The books for a given author
72+
*/
73+
public function getBooksForAuthor(Author $author): iterable
74+
{
75+
foreach ($this->books as $book) {
76+
if ($book->isAuthoredBy($author)) {
77+
yield $book;
78+
}
79+
}
80+
}
81+
82+
// neither the method above nor any other specific getter
83+
// could be used to validated all nested books
84+
// this object needs to be traversed to call the iterator
85+
public function getIterator()
86+
{
87+
return $this->books->getIterator();
88+
}
5789
}
5890
5991
.. code-block:: yaml
6092
6193
# src/AppBundle/Resources/config/validation.yml
62-
AppBundle\Entity\Book:
94+
AppBundle\Entity\BookCollection:
6395
constraints:
64-
- Symfony\Component\Validator\Constraints\Traverse: ~
96+
- Traverse: ~
6597
6698
.. code-block:: xml
6799
@@ -71,8 +103,8 @@ configure the ``Traverse`` constraint on the ``Book`` class.
71103
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
72104
xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping https://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
73105
74-
<class name="AppBundle\Entity\Book">
75-
<constraint name="Symfony\Component\Validator\Constraints\Traverse"/>
106+
<class name="AppBundle\Entity\BookCollection">
107+
<constraint name="Traverse"/>
76108
</class>
77109
</constraint-mapping>
78110
@@ -84,15 +116,23 @@ configure the ``Traverse`` constraint on the ``Book`` class.
84116
use Symfony\Component\Validator\Constraints as Assert;
85117
use Symfony\Component\Validator\Mapping\ClassMetadata;
86118
87-
class Book
119+
class BookCollection
88120
{
121+
// ...
122+
89123
public static function loadValidatorMetadata(ClassMetadata $metadata)
90124
{
91125
$metadata->addConstraint(new Assert\Traverse());
92126
}
93127
}
94128
129+
If a public getter exists to return the inner books collection like
130+
``getBooks(): Collection``, the :doc:`/reference/constraints/Valid` constraint
131+
can be used on the ``$books`` property instead.
132+
95133
Options
96134
-------
97135

136+
The ``groups`` option is not available for this constraint.
137+
98138
.. include:: /reference/constraints/_payload-option.rst.inc

0 commit comments

Comments
 (0)