Skip to content

Commit d29eceb

Browse files
committed
Merge pull request symfony#2547 from WouterJ/refactor_optionsresolver
Refactored OptionsResolver docs to have a better example
2 parents cfa7e4c + 2f46475 commit d29eceb

File tree

1 file changed

+69
-52
lines changed

1 file changed

+69
-52
lines changed

components/options_resolver.rst

+69-52
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ You can install the component in 2 different ways:
1919
Usage
2020
-----
2121

22-
Imagine you have a ``Person`` class which has 2 options: ``firstName`` and
23-
``lastName``. These options are going to be handled by the OptionsResolver
22+
Imagine you have a ``Mailer`` class which has 2 options: ``host`` and
23+
``password``. These options are going to be handled by the OptionsResolver
2424
Component.
2525

26-
First, create the ``Person`` class::
26+
First, create the ``Mailer`` class::
2727

28-
class Person
28+
class Mailer
2929
{
3030
protected $options;
3131

@@ -56,34 +56,28 @@ The ``$options`` property is an instance of
5656
means you can handle it just like a normal array::
5757

5858
// ...
59-
public function getFirstName()
59+
public function getHost()
6060
{
61-
return $this->options['firstName'];
61+
return $this->options['host'];
6262
}
6363

64-
public function getFullName()
64+
public function getPassword()
6565
{
66-
$name = $this->options['firstName'];
67-
68-
if (isset($this->options['lastName'])) {
69-
$name .= ' '.$this->options['lastName'];
70-
}
71-
72-
return $name;
66+
return $this->options['password'];
7367
}
7468

7569
Now, try to actually use the class::
7670

77-
$person = new Person(array(
78-
'firstName' => 'Wouter',
79-
'lastName' => 'de Jong',
71+
$mailer = new Mailer(array(
72+
'host' => 'smtp.example.org',
73+
'password' => 'pa$$word',
8074
));
8175

82-
echo $person->getFirstName();
76+
echo $mailer->getPassword();
8377

8478
Right now, you'll receive a
8579
:class:`Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException`,
86-
which tells you that the options ``firstName`` and ``lastName`` do not exist.
80+
which tells you that the options ``host`` and ``password`` do not exist.
8781
This is because you need to configure the ``OptionsResolver`` first, so it
8882
knows which options should be resolved.
8983

@@ -100,7 +94,7 @@ the ``OptionsResolver`` class::
10094
use Symfony\Component\OptionsResolver\OptionsResolver;
10195
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
10296

103-
class Person
97+
class Mailer
10498
{
10599
protected $options;
106100

@@ -121,23 +115,23 @@ the ``OptionsResolver`` class::
121115
Required Options
122116
----------------
123117

124-
Suppose the ``firstName`` option is required: the class can't work without
125-
it. You can set the required options by calling
118+
The ``host`` option is required: the class can't work without it. You can set
119+
the required options by calling
126120
:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setRequired`::
127121

128122
// ...
129123
protected function setDefaultOptions(OptionsResolverInterface $resolver)
130124
{
131-
$resolver->setRequired(array('firstName'));
125+
$resolver->setRequired(array('host'));
132126
}
133127

134128
You are now able to use the class without errors::
135129

136-
$person = new Person(array(
137-
'firstName' => 'Wouter',
130+
$mailer = new Mailer(array(
131+
'host' => 'smtp.example.org',
138132
));
139133

140-
echo $person->getFirstName(); // 'Wouter'
134+
echo $person->getHost(); // 'smtp.example.org'
141135

142136
If you don't pass a required option, a
143137
:class:`Symfony\\Component\\OptionsResolver\\Exception\\MissingOptionsException`
@@ -150,16 +144,16 @@ method.
150144
Optional Options
151145
----------------
152146

153-
Sometimes, an option can be optional (e.g. the ``lastName`` option in the
154-
``Person`` class). You can configure these options by calling
147+
Sometimes, an option can be optional (e.g. the ``password`` option in the
148+
``Mailer`` class). You can configure these options by calling
155149
:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setOptional`::
156150

157151
// ...
158152
protected function setDefaultOptions(OptionsResolverInterface $resolver)
159153
{
160154
// ...
161155

162-
$resolver->setOptional(array('lastName'));
156+
$resolver->setOptional(array('password'));
163157
}
164158

165159
Set Default Values
@@ -175,12 +169,12 @@ options by calling
175169
// ...
176170

177171
$resolver->setDefaults(array(
178-
'age' => 0,
172+
'username' => 'root',
179173
));
180174
}
181175

182-
The default age will be ``0`` now. When the user specifies an age, it gets
183-
replaced. You don't need to configure ``age`` as an optional option. The
176+
The default username will be ``root`` now. When the user specifies an age, it
177+
gets replaced. You don't need to configure ``root`` as an optional option. The
184178
``OptionsResolver`` already knows that options with a default value are
185179
optional.
186180

@@ -196,8 +190,8 @@ that is passed has 2 parameters:
196190
Default Values that depend on another Option
197191
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
198192

199-
Suppose you add a ``gender`` option to the ``Person`` class, whose default
200-
value you guess based on the first name. You can do that easily by using a
193+
Suppose you add a ``port`` option to the ``Mailer`` class, whose default
194+
value you guess based on the host. You can do that easily by using a
201195
Closure as the default value::
202196

203197
use Symfony\Component\OptionsResolver\Options;
@@ -208,12 +202,12 @@ Closure as the default value::
208202
// ...
209203

210204
$resolver->setDefaults(array(
211-
'gender' => function (Options $options) {
212-
if (GenderGuesser::isMale($options['firstName'])) {
213-
return 'male';
205+
'port' => function (Options $options) {
206+
if (in_array($options['host'], array('127.0.0.1', 'localhost')) {
207+
return 80;
214208
}
215209
216-
return 'female';
210+
return 25;
217211
},
218212
));
219213
}
@@ -226,9 +220,9 @@ Closure as the default value::
226220
Configure allowed Values
227221
------------------------
228222

229-
Not all values are valid values for options. For instance, the ``gender``
230-
option can only be ``female`` or ``male``. You can configure these allowed
231-
values by calling
223+
Not all values are valid values for options. Suppose the ``Mailer`` class has
224+
a ``transport`` option, it can only be one of ``sendmail``, ``mail`` or
225+
``smtp``. You can configure these allowed values by calling
232226
:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setAllowedValues`::
233227

234228
// ...
@@ -237,7 +231,7 @@ values by calling
237231
// ...
238232

239233
$resolver->setAllowedValues(array(
240-
'gender' => array('male', 'female'),
234+
'transport' => array('sendmail', 'mail', 'smtp'),
241235
));
242236
}
243237

@@ -249,8 +243,8 @@ set allowed values.
249243
Configure allowed Types
250244
~~~~~~~~~~~~~~~~~~~~~~~
251245

252-
You can also specify allowed types. For instance, the ``firstName`` option can
253-
be anything, but it must be a string. You can configure these types by calling
246+
You can also specify allowed types. For instance, the ``port`` option can
247+
be anything, but it must be an integer. You can configure these types by calling
254248
:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setAllowedTypes`::
255249

256250
// ...
@@ -259,14 +253,13 @@ be anything, but it must be a string. You can configure these types by calling
259253
// ...
260254

261255
$resolver->setAllowedTypes(array(
262-
'firstName' => 'string',
256+
'port' => 'integer',
263257
));
264258
}
265259

266-
Possible types are the one associated with the ``is_*`` php functions or a
260+
Possible types are the ones associated with the ``is_*`` php functions or a
267261
class name. You can also pass an array of types as the value. For instance,
268-
``array('null', 'string')`` allows ``firstName`` to be ``null`` or a
269-
``string``.
262+
``array('null', 'string')`` allows ``port`` to be ``null`` or a ``string``.
270263

271264
There is also an
272265
:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::addAllowedTypes`
@@ -276,7 +269,7 @@ Normalize the Options
276269
---------------------
277270

278271
Some values need to be normalized before you can use them. For instance, the
279-
``firstName`` should always start with an uppercase letter. To do that, you can
272+
``host`` should always start ``http://``. To do that, you can
280273
write normalizers. These Closures will be executed after all options are
281274
passed and return the normalized value. You can configure these normalizers by
282275
calling
@@ -288,13 +281,37 @@ calling
288281
// ...
289282

290283
$resolver->setNormalizers(array(
291-
'firstName' => function (Options $options, $value) {
292-
return ucfirst($value);
284+
'host' => function (Options $options, $value) {
285+
if ('http://' !== substr($value, 0, 7)) {
286+
$value = 'http://'.$value;
287+
}
288+
289+
return $value;
293290
},
294291
));
295292
}
296293

297294
You see that the closure also get an ``$options`` parameter. Sometimes, you
298-
need to use the other options for normalizing.
295+
need to use the other options for normalizing::
296+
297+
// ...
298+
protected function setDefaultOptions(OptionsResolverInterface $resolver)
299+
{
300+
// ...
301+
302+
$resolver->setNormalizers(array(
303+
'host' => function (Options $options, $value) {
304+
if (!in_array(substr($value, 0, 7), array('http://', 'https://')) {
305+
if ($options['ssl']) {
306+
$value = 'https://'.$value;
307+
} else {
308+
$value = 'http://'.$value;
309+
}
310+
}
311+
312+
return $value;
313+
},
314+
));
315+
}
299316

300317
.. _Packagist: https://packagist.org/packages/symfony/options-resolver

0 commit comments

Comments
 (0)