5
5
The OptionsResolver Component
6
6
=============================
7
7
8
- The OptionsResolver component is `array_replace() ` on steroids. It
9
- allows you to create an options system with required options, defaults,
8
+ The OptionsResolver component is :phpfunction: `array_replace ` on steroids.
9
+ It allows you to create an options system with required options, defaults,
10
10
validation (type, value), normalization and more.
11
11
12
12
Installation
@@ -23,7 +23,7 @@ Notes on Previous Versions
23
23
.. versionadded :: 2.6
24
24
This documentation was written for Symfony 2.6 and later. If you use an older
25
25
version, please read the corresponding documentation using the version
26
- drop-down on the upper right. For a list of changes, see the `CHANGELOG `_
26
+ drop-down on the upper right. For a list of changes, see the `CHANGELOG `_.
27
27
28
28
Usage
29
29
-----
@@ -50,29 +50,35 @@ check which options are set::
50
50
public function sendMail($from, $to)
51
51
{
52
52
$mail = ...;
53
+
53
54
$mail->setHost(isset($this->options['host'])
54
55
? $this->options['host']
55
56
: 'smtp.example.org');
57
+
56
58
$mail->setUsername(isset($this->options['username'])
57
59
? $this->options['username']
58
60
: 'user');
61
+
59
62
$mail->setPassword(isset($this->options['password'])
60
63
? $this->options['password']
61
64
: 'pa$$word');
65
+
62
66
$mail->setPort(isset($this->options['port'])
63
67
? $this->options['port']
64
68
: 25);
69
+
65
70
// ...
66
71
}
67
72
}
68
73
69
74
This boilerplate is hard to read and repetitive. Also, the default values of the
70
- options are buried in the business logic of your code. We can use the
75
+ options are buried in the business logic of your code. You could use the
71
76
:phpfunction: `array_replace ` to fix that::
72
77
73
78
class Mailer
74
79
{
75
80
// ...
81
+
76
82
public function __construct(array $options = array())
77
83
{
78
84
$this->options = array_replace(array(
@@ -85,7 +91,7 @@ options are buried in the business logic of your code. We can use the
85
91
}
86
92
87
93
Now all four options are guaranteed to be set. But what happens if the user of
88
- the ``Mailer `` class does a mistake?
94
+ the ``Mailer `` class makes a mistake?
89
95
90
96
.. code-block :: php
91
97
@@ -97,14 +103,15 @@ No error will be shown. In the best case, the bug will appear during testing,
97
103
but the developer will spend time looking for the problem. In the worst case,
98
104
the bug might not appear until it's deployed to the live system.
99
105
100
- Let's use the :class: `Symfony\\ Component\\ OptionsResolver\\ OptionsResolver `
101
- class to fix this problem::
106
+ Fortunately, the :class: `Symfony\\ Component\\ OptionsResolver\\ OptionsResolver `
107
+ class helps you to fix this problem::
102
108
103
109
use Symfony\Component\OptionsResolver\Options;
104
110
105
111
class Mailer
106
112
{
107
113
// ...
114
+
108
115
public function __construct(array $options = array())
109
116
{
110
117
$resolver = new OptionsResolver();
@@ -137,6 +144,7 @@ code::
137
144
class Mailer
138
145
{
139
146
// ...
147
+
140
148
public function sendMail($from, $to)
141
149
{
142
150
$mail = ...;
@@ -154,6 +162,7 @@ It's a good practice to split the option configuration into a separate method::
154
162
class Mailer
155
163
{
156
164
// ...
165
+
157
166
public function __construct(array $options = array())
158
167
{
159
168
$resolver = new OptionsResolver();
@@ -165,10 +174,10 @@ It's a good practice to split the option configuration into a separate method::
165
174
protected function configureOptions(OptionsResolver $resolver)
166
175
{
167
176
$resolver->setDefaults(array(
168
- 'host' => 'smtp.example.org',
169
- 'username' => 'user',
170
- 'password' => 'pa$$word',
171
- 'port' => 25,
177
+ 'host' => 'smtp.example.org',
178
+ 'username' => 'user',
179
+ 'password' => 'pa$$word',
180
+ 'port' => 25,
172
181
'encryption' => null,
173
182
));
174
183
}
@@ -197,12 +206,13 @@ Required Options
197
206
198
207
If an option must be set by the caller, pass that option to
199
208
:method: `Symfony\\ Component\\ OptionsResolver\\ OptionsResolver::setRequired `.
200
- For example, let's make the ``host `` option required::
209
+ For example, to make the ``host `` option required, you can do ::
201
210
202
211
// ...
203
212
class Mailer
204
213
{
205
214
// ...
215
+
206
216
protected function configureOptions(OptionsResolver $resolver)
207
217
{
208
218
// ...
@@ -211,8 +221,8 @@ For example, let's make the ``host`` option required::
211
221
}
212
222
213
223
.. versionadded :: 2.6
214
- Before Symfony 2.6, `setRequired() ` accepted only arrays. Since then, single
215
- option names can be passed as well .
224
+ As of Symfony 2.6, `` setRequired() `` accepts both an array of options or a
225
+ single option. Prior to 2.6, you could only pass arrays .
216
226
217
227
If you omit a required option, a
218
228
:class: `Symfony\\ Component\\ OptionsResolver\\ Exception\\ MissingOptionsException `
@@ -230,6 +240,7 @@ one required option::
230
240
class Mailer
231
241
{
232
242
// ...
243
+
233
244
protected function configureOptions(OptionsResolver $resolver)
234
245
{
235
246
// ...
@@ -277,6 +288,7 @@ been set::
277
288
class Mailer
278
289
{
279
290
// ...
291
+
280
292
protected function configureOptions(OptionsResolver $resolver)
281
293
{
282
294
// ...
@@ -321,6 +333,7 @@ correctly. To validate the types of the options, call
321
333
class Mailer
322
334
{
323
335
// ...
336
+
324
337
protected function configureOptions(OptionsResolver $resolver)
325
338
{
326
339
// ...
@@ -330,8 +343,8 @@ correctly. To validate the types of the options, call
330
343
}
331
344
332
345
For each option, you can define either just one type or an array of acceptable
333
- types. You can pass any type for which an ``is_<type>() `` method is defined.
334
- Additionally, you may pass fully qualified class or interface names.
346
+ types. You can pass any type for which an ``is_<type>() `` function is defined
347
+ in PHP. Additionally, you may pass fully qualified class or interface names.
335
348
336
349
If you pass an invalid option now, an
337
350
:class: `Symfony\\ Component\\ OptionsResolver\\ Exception\\ InvalidOptionsException `
@@ -349,9 +362,7 @@ to add additional allowed types without erasing the ones already set.
349
362
350
363
.. versionadded :: 2.6
351
364
Before Symfony 2.6, `setAllowedTypes() ` and `addAllowedTypes() ` expected
352
- the values to be given as an array mapping option names to allowed types:
353
-
354
- .. code-block :: php
365
+ the values to be given as an array mapping option names to allowed types::
355
366
356
367
$resolver->setAllowedTypes(array('port' => array('null', 'int')));
357
368
@@ -368,6 +379,7 @@ to verify that the passed option contains one of these values::
368
379
class Mailer
369
380
{
370
381
// ...
382
+
371
383
protected function configureOptions(OptionsResolver $resolver)
372
384
{
373
385
// ...
@@ -421,9 +433,11 @@ option. You can configure a normalizer by calling
421
433
class Mailer
422
434
{
423
435
// ...
436
+
424
437
protected function configureOptions(OptionsResolver $resolver)
425
438
{
426
439
// ...
440
+
427
441
$resolver->setNormalizer('host', function ($options, $value) {
428
442
if ('http://' !== substr($value, 0, 7)) {
429
443
$value = 'http://'.$value;
@@ -468,7 +482,7 @@ Default Values that Depend on another Option
468
482
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
469
483
470
484
Suppose you want to set the default value of the ``port `` option based on the
471
- encryption chosen by the user of the ``Mailer `` class. More precisely, we want
485
+ encryption chosen by the user of the ``Mailer `` class. More precisely, you want
472
486
to set the port to ``465 `` if SSL is used and to ``25 `` otherwise.
473
487
474
488
You can implement this feature by passing a closure as the default value of
@@ -499,7 +513,7 @@ these options, you can return the desired default value::
499
513
.. caution ::
500
514
501
515
The argument of the callable must be type hinted as ``Options ``. Otherwise,
502
- the callable is considered as the default value of the option.
516
+ the callable itself is considered as the default value of the option.
503
517
504
518
.. note ::
505
519
@@ -587,6 +601,7 @@ be included in the resolved options if it was actually passed to
587
601
class Mailer
588
602
{
589
603
// ...
604
+
590
605
protected function configureOptions(OptionsResolver $resolver)
591
606
{
592
607
// ...
@@ -640,6 +655,8 @@ let you find out which options are defined::
640
655
// ...
641
656
class GoogleMailer extends Mailer
642
657
{
658
+ // ...
659
+
643
660
protected function configureOptions(OptionsResolver $resolver)
644
661
{
645
662
parent::configureOptions($resolver);
@@ -674,10 +691,10 @@ can change your code to do the configuration only once per class::
674
691
675
692
public function __construct(array $options = array())
676
693
{
677
- // Are we a Mailer, a GoogleMailer, ... ?
694
+ // What type of Mailer is this, a Mailer, a GoogleMailer, ... ?
678
695
$class = get_class($this);
679
696
680
- // Did we call configureOptions() before for this class?
697
+ // Was configureOptions() executed before for this class?
681
698
if (!isset(self::$resolversByClass[$class])) {
682
699
self::$resolversByClass[$class] = new OptionsResolver();
683
700
$this->configureOptions(self::$resolversByClass[$class]);
0 commit comments