55The OptionsResolver Component
66=============================
77
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,
1010 validation (type, value), normalization and more.
1111
1212Installation
@@ -23,7 +23,7 @@ Notes on Previous Versions
2323.. versionadded :: 2.6
2424 This documentation was written for Symfony 2.6 and later. If you use an older
2525 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 `_.
2727
2828Usage
2929-----
@@ -50,29 +50,35 @@ check which options are set::
5050 public function sendMail($from, $to)
5151 {
5252 $mail = ...;
53+
5354 $mail->setHost(isset($this->options['host'])
5455 ? $this->options['host']
5556 : 'smtp.example.org');
57+
5658 $mail->setUsername(isset($this->options['username'])
5759 ? $this->options['username']
5860 : 'user');
61+
5962 $mail->setPassword(isset($this->options['password'])
6063 ? $this->options['password']
6164 : 'pa$$word');
65+
6266 $mail->setPort(isset($this->options['port'])
6367 ? $this->options['port']
6468 : 25);
69+
6570 // ...
6671 }
6772 }
6873
6974This 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
7176:phpfunction: `array_replace ` to fix that::
7277
7378 class Mailer
7479 {
7580 // ...
81+
7682 public function __construct(array $options = array())
7783 {
7884 $this->options = array_replace(array(
@@ -85,7 +91,7 @@ options are buried in the business logic of your code. We can use the
8591 }
8692
8793Now 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?
8995
9096.. code-block :: php
9197
@@ -97,14 +103,15 @@ No error will be shown. In the best case, the bug will appear during testing,
97103but the developer will spend time looking for the problem. In the worst case,
98104the bug might not appear until it's deployed to the live system.
99105
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::
102108
103109 use Symfony\Component\OptionsResolver\Options;
104110
105111 class Mailer
106112 {
107113 // ...
114+
108115 public function __construct(array $options = array())
109116 {
110117 $resolver = new OptionsResolver();
@@ -137,6 +144,7 @@ code::
137144 class Mailer
138145 {
139146 // ...
147+
140148 public function sendMail($from, $to)
141149 {
142150 $mail = ...;
@@ -154,6 +162,7 @@ It's a good practice to split the option configuration into a separate method::
154162 class Mailer
155163 {
156164 // ...
165+
157166 public function __construct(array $options = array())
158167 {
159168 $resolver = new OptionsResolver();
@@ -165,10 +174,10 @@ It's a good practice to split the option configuration into a separate method::
165174 protected function configureOptions(OptionsResolver $resolver)
166175 {
167176 $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,
172181 'encryption' => null,
173182 ));
174183 }
@@ -197,12 +206,13 @@ Required Options
197206
198207If an option must be set by the caller, pass that option to
199208: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 ::
201210
202211 // ...
203212 class Mailer
204213 {
205214 // ...
215+
206216 protected function configureOptions(OptionsResolver $resolver)
207217 {
208218 // ...
@@ -211,8 +221,8 @@ For example, let's make the ``host`` option required::
211221 }
212222
213223.. 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 .
216226
217227If you omit a required option, a
218228:class: `Symfony\\ Component\\ OptionsResolver\\ Exception\\ MissingOptionsException `
@@ -230,6 +240,7 @@ one required option::
230240 class Mailer
231241 {
232242 // ...
243+
233244 protected function configureOptions(OptionsResolver $resolver)
234245 {
235246 // ...
@@ -277,6 +288,7 @@ been set::
277288 class Mailer
278289 {
279290 // ...
291+
280292 protected function configureOptions(OptionsResolver $resolver)
281293 {
282294 // ...
@@ -321,6 +333,7 @@ correctly. To validate the types of the options, call
321333 class Mailer
322334 {
323335 // ...
336+
324337 protected function configureOptions(OptionsResolver $resolver)
325338 {
326339 // ...
@@ -330,8 +343,8 @@ correctly. To validate the types of the options, call
330343 }
331344
332345For 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.
335348
336349If you pass an invalid option now, an
337350:class: `Symfony\\ Component\\ OptionsResolver\\ Exception\\ InvalidOptionsException `
@@ -349,9 +362,7 @@ to add additional allowed types without erasing the ones already set.
349362
350363.. versionadded :: 2.6
351364 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::
355366
356367 $resolver->setAllowedTypes(array('port' => array('null', 'int')));
357368
@@ -368,6 +379,7 @@ to verify that the passed option contains one of these values::
368379 class Mailer
369380 {
370381 // ...
382+
371383 protected function configureOptions(OptionsResolver $resolver)
372384 {
373385 // ...
@@ -421,9 +433,11 @@ option. You can configure a normalizer by calling
421433 class Mailer
422434 {
423435 // ...
436+
424437 protected function configureOptions(OptionsResolver $resolver)
425438 {
426439 // ...
440+
427441 $resolver->setNormalizer('host', function ($options, $value) {
428442 if ('http://' !== substr($value, 0, 7)) {
429443 $value = 'http://'.$value;
@@ -468,7 +482,7 @@ Default Values that Depend on another Option
468482~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
469483
470484Suppose 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
472486to set the port to ``465 `` if SSL is used and to ``25 `` otherwise.
473487
474488You 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::
499513.. caution ::
500514
501515 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.
503517
504518.. note ::
505519
@@ -587,6 +601,7 @@ be included in the resolved options if it was actually passed to
587601 class Mailer
588602 {
589603 // ...
604+
590605 protected function configureOptions(OptionsResolver $resolver)
591606 {
592607 // ...
@@ -640,6 +655,8 @@ let you find out which options are defined::
640655 // ...
641656 class GoogleMailer extends Mailer
642657 {
658+ // ...
659+
643660 protected function configureOptions(OptionsResolver $resolver)
644661 {
645662 parent::configureOptions($resolver);
@@ -674,10 +691,10 @@ can change your code to do the configuration only once per class::
674691
675692 public function __construct(array $options = array())
676693 {
677- // Are we a Mailer, a GoogleMailer, ... ?
694+ // What type of Mailer is this, a Mailer, a GoogleMailer, ... ?
678695 $class = get_class($this);
679696
680- // Did we call configureOptions() before for this class?
697+ // Was configureOptions() executed before for this class?
681698 if (!isset(self::$resolversByClass[$class])) {
682699 self::$resolversByClass[$class] = new OptionsResolver();
683700 $this->configureOptions(self::$resolversByClass[$class]);
0 commit comments