1
1
Callback
2
2
========
3
3
4
- The purpose of the Callback assertion is to let you create completely custom
4
+ .. versionadded :: 2.4
5
+ The ``Callback `` constraint was simplified in Symfony 2.4. For usage
6
+ examples with older Symfony versions, see the corresponding versions of this
7
+ documentation page.
8
+
9
+ The purpose of the Callback constraint is to create completely custom
5
10
validation rules and to assign any validation errors to specific fields on
6
11
your object. If you're using validation with forms, this means that you can
7
12
make these custom errors display next to a specific field, instead of simply
@@ -20,15 +25,15 @@ can do anything, including creating and assigning validation errors.
20
25
+----------------+------------------------------------------------------------------------+
21
26
| Applies to | :ref: `class <validation-class-target >` |
22
27
+----------------+------------------------------------------------------------------------+
23
- | Options | - `methods `_ |
28
+ | Options | - `callback `_ |
24
29
+----------------+------------------------------------------------------------------------+
25
30
| Class | :class: `Symfony\\ Component\\ Validator\\ Constraints\\ Callback ` |
26
31
+----------------+------------------------------------------------------------------------+
27
32
| Validator | :class: `Symfony\\ Component\\ Validator\\ Constraints\\ CallbackValidator ` |
28
33
+----------------+------------------------------------------------------------------------+
29
34
30
- Setup
31
- -----
35
+ Configuration
36
+ -------------
32
37
33
38
.. configuration-block ::
34
39
@@ -37,21 +42,25 @@ Setup
37
42
# src/Acme/BlogBundle/Resources/config/validation.yml
38
43
Acme\BlogBundle\Entity\Author :
39
44
constraints :
40
- - Callback :
41
- methods : [isAuthorValid]
45
+ - Callback : validate
42
46
43
47
.. code-block :: php-annotations
44
48
45
49
// src/Acme/BlogBundle/Entity/Author.php
46
50
namespace Acme\BlogBundle\Entity;
47
51
48
52
use Symfony\Component\Validator\Constraints as Assert;
53
+ use Symfony\Component\Validator\ExecutionContextInterface;
49
54
50
- /**
51
- * @Assert\Callback(methods={"isAuthorValid"})
52
- */
53
55
class Author
54
56
{
57
+ /**
58
+ * @Assert\Callback
59
+ */
60
+ public function validate(ExecutionContextInterface $context)
61
+ {
62
+ // ...
63
+ }
55
64
}
56
65
57
66
.. code-block :: xml
63
72
xsi : schemaLocation =" http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd" >
64
73
65
74
<class name =" Acme\BlogBundle\Entity\Author" >
66
- <constraint name =" Callback" >
67
- <option name =" methods" >
68
- <value >isAuthorValid</value >
69
- </option >
70
- </constraint >
75
+ <constraint name =" Callback" >validate</constraint >
71
76
</class >
72
77
</constraint-mapping >
73
78
83
88
{
84
89
public static function loadValidatorMetadata(ClassMetadata $metadata)
85
90
{
86
- $metadata->addConstraint(new Assert\Callback(array(
87
- 'methods' => array('isAuthorValid'),
88
- )));
91
+ $metadata->addConstraint(new Assert\Callback('validate'));
89
92
}
90
93
}
91
94
@@ -98,133 +101,171 @@ those errors should be attributed::
98
101
99
102
// ...
100
103
use Symfony\Component\Validator\ExecutionContextInterface;
101
-
104
+
102
105
class Author
103
106
{
104
107
// ...
105
108
private $firstName;
106
-
107
- public function isAuthorValid (ExecutionContextInterface $context)
109
+
110
+ public function validate (ExecutionContextInterface $context)
108
111
{
109
112
// somehow you have an array of "fake names"
110
- $fakeNames = array();
111
-
113
+ $fakeNames = array(/* ... */ );
114
+
112
115
// check if the name is actually a fake name
113
116
if (in_array($this->getFirstName(), $fakeNames)) {
114
- $context->addViolationAt('firstname ', 'This name sounds totally fake!', array(), null);
117
+ $context->addViolationAt('firstName ', 'This name sounds totally fake!', array(), null);
115
118
}
116
119
}
117
120
}
118
121
119
- Options
120
- -------
122
+ Static Callbacks
123
+ ----------------
121
124
122
- methods
123
- ~~~~~~~
125
+ You can also use the constraint with static methods. Since static methods don't
126
+ have access to the object instance, they receive the object as first argument::
124
127
125
- **type **: ``array `` **default **: ``array() `` [:ref: `default option <validation-default-option >`]
128
+ public static function validate($object, ExecutionContextInterface $context)
129
+ {
130
+ // somehow you have an array of "fake names"
131
+ $fakeNames = array(/* ... */);
126
132
127
- This is an array of the methods that should be executed during the validation
128
- process. Each method can be one of the following formats:
133
+ // check if the name is actually a fake name
134
+ if (in_array($object->getFirstName(), $fakeNames)) {
135
+ $context->addViolationAt('firstName', 'This name sounds totally fake!', array(), null);
136
+ }
137
+ }
129
138
130
- 1) **String method name **
139
+ External Callbacks and Closures
140
+ -------------------------------
131
141
132
- If the name of a method is a simple string (e.g. ``isAuthorValid ``), that
133
- method will be called on the same object that's being validated and the
134
- ``ExecutionContextInterface `` will be the only argument (see the above example).
142
+ If you want to execute a static callback method that is not located in the class
143
+ of the validated object, you can configure the constraint to invoke an array
144
+ callable as supported by PHP's :phpfunction: `call_user_func ` function. Suppose
145
+ your validation function is `Vendor\Package\Validator::validate() `::
135
146
136
- 2) ** Static array callback **
147
+ namespace Vendor\Package;
137
148
138
- Each method can also be specified as a standard array callback:
149
+ use Symfony\Component\Validator\ExecutionContextInterface;
139
150
140
- .. configuration-block ::
151
+ class Validator
152
+ {
153
+ public function validate($object, ExecutionContextInterface $context)
154
+ {
155
+ // ...
156
+ }
157
+ }
141
158
142
- .. code-block :: yaml
159
+ You can then use the following configuration to invoke this validator::
143
160
144
- # src/Acme/BlogBundle/Resources/config/validation.yml
145
- Acme\BlogBundle\Entity\Author :
146
- constraints :
147
- - Callback :
148
- methods :
149
- - [Acme\BlogBundle\MyStaticValidatorClass, isAuthorValid]
161
+ .. configuration-block ::
150
162
151
- .. code-block :: php-annotations
163
+ .. code-block :: yaml
152
164
153
- // src/Acme/BlogBundle/Entity/Author.php
154
- use Symfony\Component\Validator\Constraints as Assert;
165
+ # src/Acme/BlogBundle/Resources/config/validation.yml
166
+ Acme\BlogBundle\Entity\Author :
167
+ constraints :
168
+ - Callback : [Vendor\Package\Validator, validate]
155
169
156
- /**
157
- * @Assert\Callback(methods={
158
- * { "Acme\BlogBundle\MyStaticValidatorClass", "isAuthorValid"}
159
- * })
160
- */
161
- class Author
162
- {
163
- }
170
+ .. code-block :: php-annotations
164
171
165
- .. code-block :: xml
172
+ // src/Acme/BlogBundle/Entity/Author.php
173
+ namespace Acme\BlogBundle\Entity;
166
174
167
- <!-- src/Acme/BlogBundle/Resources/config/validation.xml -->
168
- <?xml version =" 1.0" encoding =" UTF-8" ?>
169
- <constraint-mapping xmlns =" http://symfony.com/schema/dic/constraint-mapping"
170
- xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
171
- xsi : schemaLocation =" http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd" >
175
+ use Symfony\Component\Validator\Constraints as Assert;
176
+ use Symfony\Component\Validator\ExecutionContextInterface;
172
177
173
- <class name =" Acme\BlogBundle\Entity\Author" >
174
- <constraint name =" Callback" >
175
- <option name =" methods" >
176
- <value >
177
- <value >Acme\BlogBundle\MyStaticValidatorClass</value >
178
- <value >isAuthorValid</value >
179
- </value >
180
- </option >
181
- </constraint >
182
- </class >
183
- </constraint-mapping >
178
+ /**
179
+ * @Assert\Callback({"Vendor\Package\Validator", "validate"})
180
+ */
181
+ class Author
182
+ {
183
+ }
184
184
185
- .. code-block :: php
185
+ .. code-block :: xml
186
186
187
- // src/Acme/BlogBundle/Entity/Author.php
187
+ <!-- src/Acme/BlogBundle/Resources/config/validation.xml -->
188
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
189
+ <constraint-mapping xmlns =" http://symfony.com/schema/dic/constraint-mapping"
190
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
191
+ xsi : schemaLocation =" http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd" >
192
+
193
+ <class name =" Acme\BlogBundle\Entity\Author" >
194
+ <constraint name =" Callback" >
195
+ <value >Vendor\Package\Validator</value >
196
+ <value >validate</value >
197
+ </constraint >
198
+ </class >
199
+ </constraint-mapping >
188
200
189
- use Symfony\Component\Validator\Mapping\ClassMetadata;
190
- use Symfony\Component\Validator\Constraints\Callback;
201
+ .. code-block :: php
191
202
192
- class Author
203
+ // src/Acme/BlogBundle/Entity/Author.php
204
+ namespace Acme\BlogBundle\Entity;
205
+
206
+ use Symfony\Component\Validator\Mapping\ClassMetadata;
207
+ use Symfony\Component\Validator\Constraints as Assert;
208
+
209
+ class Author
210
+ {
211
+ public static function loadValidatorMetadata(ClassMetadata $metadata)
193
212
{
194
- public $name;
195
-
196
- public static function loadValidatorMetadata(ClassMetadata $metadata)
197
- {
198
- $metadata->addConstraint(new Callback(array(
199
- 'methods' => array(
200
- array('Acme\BlogBundle\MyStaticValidatorClass', 'isAuthorValid'),
201
- ),
202
- )));
203
- }
213
+ $metadata->addConstraint(new Assert\Callback(array(
214
+ 'Vendor\Package\Validator',
215
+ 'validate'
216
+ )));
204
217
}
218
+ }
205
219
206
- In this case, the static method ``isAuthorValid `` will be called on the
207
- ``Acme\BlogBundle\MyStaticValidatorClass `` class. It's passed both the original
208
- object being validated (e.g. ``Author ``) as well as the ``ExecutionContextInterface ``::
220
+ .. note ::
209
221
210
- namespace Acme\BlogBundle;
211
-
212
- use Symfony\Component\Validator\ExecutionContextInterface;
213
- use Acme\BlogBundle\Entity\Author;
214
-
215
- class MyStaticValidatorClass
222
+ The Callback constraint does *not * support global callback functions or
223
+ It is *not * possible to specify a global function or a :term: `service `
224
+ method as callback. To validate using a service, you should
225
+ :doc: `create a custom validation constraint</cookbook/validation/custom_constraint> `
226
+ and add that new constraint to your class.
227
+
228
+ When configuring the constraint via PHP, you can also pass a closure to the
229
+ constructor of the Callback constraint::
230
+
231
+ // src/Acme/BlogBundle/Entity/Author.php
232
+ namespace Acme\BlogBundle\Entity;
233
+
234
+ use Symfony\Component\Validator\Mapping\ClassMetadata;
235
+ use Symfony\Component\Validator\Constraints as Assert;
236
+
237
+ class Author
238
+ {
239
+ public static function loadValidatorMetadata(ClassMetadata $metadata)
216
240
{
217
- public static function isAuthorValid(Author $author, ExecutionContextInterface $context)
218
- {
241
+ $callback = function ($object, ExecutionContextInterface $context) {
219
242
// ...
220
- }
243
+ };
244
+
245
+ $metadata->addConstraint(new Assert\Callback($callback));
221
246
}
247
+ }
248
+
249
+ Options
250
+ -------
251
+
252
+ callback
253
+ ~~~~~~~~
254
+
255
+ **type **: ``string ``, ``array `` or ``Closure `` [:ref: `default option<validation-default-option> `]
256
+
257
+ The callback option accepts three different formats for specifying the
258
+ callback method:
259
+
260
+ * A **string ** containing the name of a concrete or static method.
261
+
262
+ * An array callable with the format ``array('<Class>', '<method>') ``.
263
+
264
+ * A closure.
222
265
223
- .. tip ::
266
+ Concrete callbacks receive an :class: `Symfony\\ Component\\ Validator\\ ExecutionContextInterface `
267
+ instance as only argument.
224
268
225
- If you specify your ``Callback `` constraint via PHP, then you also have
226
- the option to make your callback either a PHP closure or a non-static
227
- callback. It is *not * currently possible, however, to specify a :term: `service `
228
- as a constraint. To validate using a service, you should
229
- :doc: `create a custom validation constraint </cookbook/validation/custom_constraint >`
230
- and add that new constraint to your class.
269
+ Static or closure callbacks receive the validated object as first argument
270
+ and the :class: `Symfony\\ Component\\ Validator\\ ExecutionContextInterface `
271
+ instance as second argument.
0 commit comments