55The OptionsResolver Component
66=============================
77
8- The OptionsResolver component is `array_replace() ` on steroids.
8+ The OptionsResolver component is :phpfunction: `array_replace ` on steroids.
9+ It allows you to create an options system with required options, defaults,
10+ validation (type, value), normalization and more.
911
1012Installation
1113------------
@@ -20,8 +22,8 @@ Notes on Previous Versions
2022
2123.. versionadded :: 2.6
2224 This documentation was written for Symfony 2.6 and later. If you use an older
23- version, please read the corresponding documentation using the version
24- drop-down on the upper right .
25+ version, please ` read the Symfony 2.5 documentation `_. For a list of changes,
26+ see the ` CHANGELOG `_ .
2527
2628Usage
2729-----
@@ -48,29 +50,35 @@ check which options are set::
4850 public function sendMail($from, $to)
4951 {
5052 $mail = ...;
53+
5154 $mail->setHost(isset($this->options['host'])
5255 ? $this->options['host']
5356 : 'smtp.example.org');
57+
5458 $mail->setUsername(isset($this->options['username'])
5559 ? $this->options['username']
5660 : 'user');
61+
5762 $mail->setPassword(isset($this->options['password'])
5863 ? $this->options['password']
5964 : 'pa$$word');
65+
6066 $mail->setPort(isset($this->options['port'])
6167 ? $this->options['port']
6268 : 25);
69+
6370 // ...
6471 }
6572 }
6673
6774This boilerplate is hard to read and repetitive. Also, the default values of the
68- options are buried in the business logic of your code. We can use
75+ options are buried in the business logic of your code. Use the
6976:phpfunction: `array_replace ` to fix that::
7077
7178 class Mailer
7279 {
7380 // ...
81+
7482 public function __construct(array $options = array())
7583 {
7684 $this->options = array_replace(array(
@@ -83,27 +91,27 @@ options are buried in the business logic of your code. We can use
8391 }
8492
8593Now all four options are guaranteed to be set. But what happens if the user of
86- the ``Mailer `` class does a mistake?
94+ the ``Mailer `` class makes a mistake?
8795
8896.. code-block :: php
8997
9098 $mailer = new Mailer(array(
9199 'usernme' => 'johndoe',
92100 ));
93101
94- No error will be shown. In the best case, the bug will be appear during testing.
95- The developer will possibly spend a lot of time looking for the problem. In the
96- worst case, however, the bug won't even appear and will be deployed to the live
97- system.
102+ No error will be shown. In the best case, the bug will appear during testing,
103+ but the developer will spend time looking for the problem. In the worst case,
104+ the bug might not appear until it's deployed to the live system.
98105
99- Let's use the :class: `Symfony\\ Component\\ OptionsResolver\\ OptionsResolver `
100- class to fix this problem::
106+ Fortunately, the :class: `Symfony\\ Component\\ OptionsResolver\\ OptionsResolver `
107+ class helps you to fix this problem::
101108
102109 use Symfony\Component\OptionsResolver\Options;
103110
104111 class Mailer
105112 {
106113 // ...
114+
107115 public function __construct(array $options = array())
108116 {
109117 $resolver = new OptionsResolver();
@@ -136,6 +144,7 @@ code::
136144 class Mailer
137145 {
138146 // ...
147+
139148 public function sendMail($from, $to)
140149 {
141150 $mail = ...;
@@ -153,6 +162,7 @@ It's a good practice to split the option configuration into a separate method::
153162 class Mailer
154163 {
155164 // ...
165+
156166 public function __construct(array $options = array())
157167 {
158168 $resolver = new OptionsResolver();
@@ -164,10 +174,10 @@ It's a good practice to split the option configuration into a separate method::
164174 protected function configureOptions(OptionsResolver $resolver)
165175 {
166176 $resolver->setDefaults(array(
167- 'host' => 'smtp.example.org',
168- 'username' => 'user',
169- 'password' => 'pa$$word',
170- 'port' => 25,
177+ 'host' => 'smtp.example.org',
178+ 'username' => 'user',
179+ 'password' => 'pa$$word',
180+ 'port' => 25,
171181 'encryption' => null,
172182 ));
173183 }
@@ -196,12 +206,13 @@ Required Options
196206
197207If an option must be set by the caller, pass that option to
198208:method: `Symfony\\ Component\\ OptionsResolver\\ OptionsResolver::setRequired `.
199- For example, let's make the ``host `` option required::
209+ For example, to make the ``host `` option required, you can do ::
200210
201211 // ...
202212 class Mailer
203213 {
204214 // ...
215+
205216 protected function configureOptions(OptionsResolver $resolver)
206217 {
207218 // ...
@@ -210,8 +221,8 @@ For example, let's make the ``host`` option required::
210221 }
211222
212223.. versionadded :: 2.6
213- Before Symfony 2.6, `setRequired() ` accepted only arrays. Since then, single
214- 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 .
215226
216227If you omit a required option, a
217228:class: `Symfony\\ Component\\ OptionsResolver\\ Exception\\ MissingOptionsException `
@@ -229,6 +240,7 @@ one required option::
229240 class Mailer
230241 {
231242 // ...
243+
232244 protected function configureOptions(OptionsResolver $resolver)
233245 {
234246 // ...
@@ -268,14 +280,15 @@ retrieve the names of all required options::
268280
269281If you want to check whether a required option is still missing from the default
270282options, you can use :method: `Symfony\\ Component\\ OptionsResolver\\ OptionsResolver::isMissing `.
271- The difference to :method: `Symfony\\ Component\\ OptionsResolver\\ OptionsResolver::isRequired `
272- is that this method will return false for required options that have already
283+ The difference between this and :method: `Symfony\\ Component\\ OptionsResolver\\ OptionsResolver::isRequired `
284+ is that this method will return false if a required option has already
273285been set::
274286
275287 // ...
276288 class Mailer
277289 {
278290 // ...
291+
279292 protected function configureOptions(OptionsResolver $resolver)
280293 {
281294 // ...
@@ -320,6 +333,7 @@ correctly. To validate the types of the options, call
320333 class Mailer
321334 {
322335 // ...
336+
323337 protected function configureOptions(OptionsResolver $resolver)
324338 {
325339 // ...
@@ -329,8 +343,8 @@ correctly. To validate the types of the options, call
329343 }
330344
331345For each option, you can define either just one type or an array of acceptable
332- types. You can pass any type for which an ``is_<type>() `` method is defined.
333- 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.
334348
335349If you pass an invalid option now, an
336350:class: `Symfony\\ Component\\ OptionsResolver\\ Exception\\ InvalidOptionsException `
@@ -348,9 +362,7 @@ to add additional allowed types without erasing the ones already set.
348362
349363.. versionadded :: 2.6
350364 Before Symfony 2.6, `setAllowedTypes() ` and `addAllowedTypes() ` expected
351- the values to be given as an array mapping option names to allowed types:
352-
353- .. code-block :: php
365+ the values to be given as an array mapping option names to allowed types::
354366
355367 $resolver->setAllowedTypes(array('port' => array('null', 'int')));
356368
@@ -360,13 +372,14 @@ Value Validation
360372Some options can only take one of a fixed list of predefined values. For
361373example, suppose the ``Mailer `` class has a ``transport `` option which can be
362374one of ``sendmail ``, ``mail `` and ``smtp ``. Use the method
363- :method: `Symfony\\ Component\\ OptionsResolver\\ OptionsResolver::setAllowedValues ` to verify
364- that the passed option contains one of these values::
375+ :method: `Symfony\\ Component\\ OptionsResolver\\ OptionsResolver::setAllowedValues `
376+ to verify that the passed option contains one of these values::
365377
366378 // ...
367379 class Mailer
368380 {
369381 // ...
382+
370383 protected function configureOptions(OptionsResolver $resolver)
371384 {
372385 // ...
@@ -420,9 +433,11 @@ option. You can configure a normalizer by calling
420433 class Mailer
421434 {
422435 // ...
436+
423437 protected function configureOptions(OptionsResolver $resolver)
424438 {
425439 // ...
440+
426441 $resolver->setNormalizer('host', function ($options, $value) {
427442 if ('http://' !== substr($value, 0, 7)) {
428443 $value = 'http://'.$value;
@@ -467,12 +482,12 @@ Default Values that Depend on another Option
467482~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
468483
469484Suppose you want to set the default value of the ``port `` option based on the
470- 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
471486to set the port to ``465 `` if SSL is used and to ``25 `` otherwise.
472487
473- You can implement this feature by passing a closure as default value of the
474- ``port `` option. The closure receives the options as argument. Based on these
475- options, you can return the desired default value::
488+ You can implement this feature by passing a closure as the default value of
489+ the ``port `` option. The closure receives the options as argument. Based on
490+ these options, you can return the desired default value::
476491
477492 use Symfony\Component\OptionsResolver\Options;
478493
@@ -498,7 +513,7 @@ options, you can return the desired default value::
498513.. caution ::
499514
500515 The argument of the callable must be type hinted as ``Options ``. Otherwise,
501- the callable is considered as the default value of the option.
516+ the callable itself is considered as the default value of the option.
502517
503518.. note ::
504519
@@ -546,8 +561,10 @@ Options without Default Values
546561~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
547562
548563In some cases, it is useful to define an option without setting a default value.
549- Mostly, you will need this when you want to know whether an option was passed
550- or not. If you set a default value for that option, this is not possible::
564+ This is useful if you need to know whether or not the user *actually * set
565+ an option or not. For example, if you set the default value for an option,
566+ it's not possible to know whether the user passed this value or if it simply
567+ comes from the default::
551568
552569 // ...
553570 class Mailer
@@ -584,6 +601,7 @@ be included in the resolved options if it was actually passed to
584601 class Mailer
585602 {
586603 // ...
604+
587605 protected function configureOptions(OptionsResolver $resolver)
588606 {
589607 // ...
@@ -637,6 +655,8 @@ let you find out which options are defined::
637655 // ...
638656 class GoogleMailer extends Mailer
639657 {
658+ // ...
659+
640660 protected function configureOptions(OptionsResolver $resolver)
641661 {
642662 parent::configureOptions($resolver);
@@ -671,10 +691,10 @@ can change your code to do the configuration only once per class::
671691
672692 public function __construct(array $options = array())
673693 {
674- // Are we a Mailer, a GoogleMailer, ... ?
694+ // What type of Mailer is this, a Mailer, a GoogleMailer, ... ?
675695 $class = get_class($this);
676696
677- // Did we call configureOptions() before for this class?
697+ // Was configureOptions() executed before for this class?
678698 if (!isset(self::$resolversByClass[$class])) {
679699 self::$resolversByClass[$class] = new OptionsResolver();
680700 $this->configureOptions(self::$resolversByClass[$class]);
@@ -693,14 +713,14 @@ Now the :class:`Symfony\\Component\\OptionsResolver\\OptionsResolver` instance
693713will be created once per class and reused from that on. Be aware that this may
694714lead to memory leaks in long-running applications, if the default options contain
695715references to objects or object graphs. If that's the case for you, implement a
696- method ``clearDefaultOptions () `` and call it periodically::
716+ method ``clearOptionsConfig () `` and call it periodically::
697717
698718 // ...
699719 class Mailer
700720 {
701721 private static $resolversByClass = array();
702722
703- public static function clearDefaultOptions ()
723+ public static function clearOptionsConfig ()
704724 {
705725 self::$resolversByClass = array();
706726 }
@@ -713,3 +733,5 @@ options in your code.
713733
714734.. _Packagist : https://packagist.org/packages/symfony/options-resolver
715735.. _Form component : http://symfony.com/doc/current/components/form/introduction.html
736+ .. _CHANGELOG : https://github.com/symfony/symfony/blob/master/src/Symfony/Component/OptionsResolver/CHANGELOG.md#260
737+ .. _`read the Symfony 2.5 documentation` : http://symfony.com/doc/2.5/components/options_resolver.html
0 commit comments