Skip to content

Commit 4e2b98e

Browse files
committed
[Validator] Allow to define a reusable set of constraints
1 parent df3759b commit 4e2b98e

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed

reference/constraints.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ Validation Constraints Reference
6262
constraints/Isbn
6363
constraints/Issn
6464

65+
constraints/Compound
6566
constraints/Callback
6667
constraints/Expression
6768
constraints/All

reference/constraints/Compound.rst

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
Compound
2+
========
3+
4+
To the contrary to the other constraints, this constraint cannot be used on its own.
5+
Instead, it allows you to create your own set of reusable constraints, representing
6+
rules to use consistently across your application, by extending the constraint.
7+
8+
========== ===================================================================
9+
Applies to :ref:`class <validation-class-target>` or :ref:`property or method <validation-property-target>`
10+
Options - `groups`_
11+
- `payload`_
12+
Class :class:`Symfony\\Component\\Validator\\Constraints\\Compound`
13+
Validator :class:`Symfony\\Component\\Validator\\Constraints\\CompoundValidator`
14+
========== ===================================================================
15+
16+
Basic Usage
17+
-----------
18+
19+
Suppose that you have different places where a user password must be validated,
20+
you can create your own named set or requirements to be reused consistently everywhere:
21+
22+
.. configuration-block::
23+
24+
.. code-block:: php
25+
26+
// src/Validator/Constraints/MatchesPasswordRequirements.php
27+
namespace App\Validator\Constraints;
28+
29+
use Symfony\Component\Validator\Compound;
30+
31+
/**
32+
* @Annotation
33+
*/
34+
class MatchesPasswordRequirements extends Compound
35+
{
36+
protected function getConstraints(array $options): array
37+
{
38+
return [
39+
new NotBlank(),
40+
new Type('string'),
41+
new Length(['min' => 12]),
42+
new NotCompromisedPassword(),
43+
];
44+
}
45+
}
46+
47+
You can now use it anywhere you need it:
48+
49+
.. configuration-block::
50+
51+
.. code-block:: php-annotations
52+
53+
// src/Entity/User.php
54+
namespace App\DTO;
55+
56+
use App\Validator\Constraints\MatchesPasswordRequirements;
57+
58+
class RegisterUser
59+
{
60+
/**
61+
* @MatchesPasswordRequirements()
62+
*/
63+
public $password;
64+
}
65+
66+
.. code-block:: yaml
67+
68+
# config/validator/validation.yaml
69+
App\DTO\RegisterUser:
70+
properties:
71+
password:
72+
- App\Validator\Constraints\MatchesPasswordRequirements: ~
73+
74+
.. code-block:: xml
75+
76+
<!-- config/validator/validation.xml -->
77+
<?xml version="1.0" encoding="UTF-8" ?>
78+
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
79+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
80+
xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping https://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
81+
82+
<class name="App\DTO\RegisterUser">
83+
<property name="password">
84+
<constraint name="App\Validator\Constraints\MatchesPasswordRequirements"/>
85+
</property>
86+
</class>
87+
</constraint-mapping>
88+
89+
.. code-block:: php
90+
91+
// src/Entity/User.php
92+
namespace App\DTO;
93+
94+
use App\Validator\ConstraintsMatches\MatchesPasswordRequirements;
95+
use Symfony\Component\Validator\Mapping\ClassMetadata;
96+
97+
class RegisterUser
98+
{
99+
public static function loadValidatorMetadata(ClassMetadata $metadata)
100+
{
101+
$metadata->addPropertyConstraint('password', new MatchesPasswordRequirements());
102+
}
103+
}
104+
105+
Options
106+
-------
107+
108+
.. include:: /reference/constraints/_groups-option.rst.inc
109+
110+
.. include:: /reference/constraints/_payload-option.rst.inc

reference/constraints/map.rst.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ Financial and other Number Constraints
8383
Other Constraints
8484
~~~~~~~~~~~~~~~~~
8585

86+
* :doc:`Compound </reference/constraints/Compound>`
8687
* :doc:`Callback </reference/constraints/Callback>`
8788
* :doc:`Expression </reference/constraints/Expression>`
8889
* :doc:`All </reference/constraints/All>`

validation/custom_constraint.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,12 @@ then your validator is already registered as a service and :doc:`tagged </servic
181181
with the necessary ``validator.constraint_validator``. This means you can
182182
:ref:`inject services or configuration <services-constructor-injection>` like any other service.
183183

184+
Create a reusable set of constraints
185+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
186+
187+
In case you need to apply some common set of constraints in different places
188+
consistently across your application, you can extend the :doc:`Compound constraint</reference/constraints/Compound>`.
189+
184190
Class Constraint Validator
185191
~~~~~~~~~~~~~~~~~~~~~~~~~~
186192

0 commit comments

Comments
 (0)