Skip to content

Commit c5cfa5b

Browse files
committed
[W] components/options_resolver
1 parent 20b272d commit c5cfa5b

File tree

1 file changed

+293
-0
lines changed

1 file changed

+293
-0
lines changed

components/options_resolver.rst

Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
.. index::
2+
single: Options Resolver
3+
single: Components; OptionsResolver
4+
5+
The OptionsResolver Component
6+
=============================
7+
8+
The OptionsResolver Component helps you at configuring objects with option
9+
arrays. It supports default values, option constraints and lazy options.
10+
11+
.. versionadded:: 2.1
12+
The OptionsResolver Component is new in Symfony2.1, it can be found in the
13+
Form component in older versions.
14+
15+
Installation
16+
------------
17+
18+
You can install the component in several different ways:
19+
20+
* Use the official Git repository (https://github.com/symfony/OptionsResolver
21+
* :doc:`Install it via Composer</components/using_components>` (``symfony/options-resolver`` on `Packagist`_)
22+
23+
Usage
24+
-----
25+
26+
Imagine we have a ``Person`` class which has 2 options: ``firstName`` and
27+
``lastName``. We are going to handles these options with the OptionsResolver
28+
Component.
29+
30+
First of all, we create some basic skeleton::
31+
32+
class Person
33+
{
34+
protected $options;
35+
36+
public function __construct(array $options = array())
37+
{
38+
}
39+
}
40+
41+
Now, we should handle the ``$options`` parameter with the OptionsResolver
42+
class. We just instantiate a
43+
:class:`Symfony\\Component\\OptionsResolver\\OptionsResolver` class and let it
44+
resolve the options by calling
45+
:method:`Symfony\\Component\\OptionsResolver::resolve`::
46+
47+
use Symfony\Component\OptionsResolver\OptionsResolver;
48+
49+
// ...
50+
public function __construct(array $options = array())
51+
{
52+
$resolver = new OptionsResolver();
53+
54+
$this->options = $resolver->resolve($options);
55+
}
56+
57+
The ``$options`` property is an instance of
58+
:class:`Symfony\\Component\\OptionsResolver\\Options`, which implements
59+
:phpclass:`ArrayAccess`, :phpclass:`Iterator` and :phpclass:`Countable`. That
60+
means you can handle it as a normal array::
61+
62+
// ...
63+
public function getFirstName()
64+
{
65+
return $this->options['firstName'];
66+
}
67+
68+
public function getFullName()
69+
{
70+
$name = $this->options['firstName'];
71+
72+
if (isset($this->options['lastName'])) {
73+
$name .= ' '.$this->options['lastName'];
74+
}
75+
76+
return $name;
77+
}
78+
79+
Let's use the class::
80+
81+
$person = new Person(array(
82+
'firstName' => 'Wouter',
83+
'lastName' => 'de Jong',
84+
));
85+
86+
echo $person->getFirstName();
87+
88+
As you see, you get a
89+
:class:`Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException`
90+
which tells you that the options ``firstName`` and ``lastName`` not exists.
91+
You need to configure the ``OptionsResolver`` first, so it knows which options
92+
should be resolved.
93+
94+
.. tip::
95+
96+
To check if an option exists, you can use the
97+
:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isKnown` isser.
98+
99+
A best practise is to put the configuration in a method (e.g.
100+
``setDefaultOptions``). You call this method in the constructor to configure
101+
the ``OptionsResolver`` class::
102+
103+
use Symfony\Component\OptionsResolver\OptionsResolver;
104+
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
105+
106+
class Person
107+
{
108+
protected $options;
109+
110+
public function __construct(array $options = array())
111+
{
112+
$resolver = new OptionsResolver();
113+
$this->setDefaultOptions($resolver);
114+
115+
$this->options = $resolver->resolve($options);
116+
}
117+
118+
protected function setDefaultOptions(OptionsResolverInterface $resolver)
119+
{
120+
// ... configure the resolver, you will learn this in the sections below
121+
}
122+
}
123+
124+
Required Options
125+
----------------
126+
127+
The ``firstName`` option is required; the class can't work without that
128+
option. You can set the required options by calling
129+
:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setRequired`::
130+
131+
// ...
132+
protected function setDefaultOptions(OptionsResolverInterface $resolver)
133+
{
134+
$resolver->setRequired(array('firstName'));
135+
}
136+
137+
You are now able to use the class without errors::
138+
139+
$person = new Person(array(
140+
'firstName' => 'Wouter',
141+
));
142+
143+
echo $person->getFirstName(); // 'Wouter'
144+
145+
If you don't pass a required option, an
146+
:class:`Symfony\\Component\\OptionsResolver\\Exception\\MissingOptionsException`
147+
will be thrown.
148+
149+
To determine if an option is required, you can use the
150+
:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isRequired`
151+
method.
152+
153+
Optional Options
154+
----------------
155+
156+
Sometimes, an option can be optional (e.g. the ``lastName`` option in the
157+
``Person`` class). You can configure these options by calling
158+
:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setOptional`::
159+
160+
// ...
161+
protected function setDefaultOptions(OptionsResolverInterface $resolver)
162+
{
163+
// ...
164+
165+
$resolver->setOptional(array('lastName'));
166+
}
167+
168+
Set Default Values
169+
------------------
170+
171+
Most of the optional options have a default value. You can configure these
172+
options by calling
173+
:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setDefaults`::
174+
175+
// ...
176+
protected function setDefaultOptions(OptionsResolverInterface $resolver)
177+
{
178+
// ...
179+
180+
$resolver->setDefaults(array(
181+
'age' => 0,
182+
));
183+
}
184+
185+
The default age will be ``0`` now. When the user specifies an age, it gets
186+
replaced. You don't need to configure ``age`` as an optional option. The
187+
``OptionsResolver`` already knows that options with a default value are
188+
optional.
189+
190+
The ``OptionsResolver`` component also has an
191+
:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::replaceDefaults`
192+
method. This can be used to override the previous default value. The closure
193+
that is passed has 2 parameters:
194+
195+
* ``$options`` (an :class:`Symfony\\Component\\OptionsResolver\\Options`
196+
instance), with all the default options
197+
* ``$value``, the previous set default value
198+
199+
Default values that depend on another option
200+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
201+
202+
If you add a ``gender`` option to the ``Person`` class, it should get a
203+
default value which guess the gender based on the first name. You can do that
204+
easilly by using a Closure as default value::
205+
206+
use Symfony\Component\OptionsResolver\Options;
207+
208+
// ...
209+
protected function setDefaultOptions(OptionsResolverInterface $resolver)
210+
{
211+
// ...
212+
213+
$resolver->setDefaults(array(
214+
'gender' => function (Options $options) {
215+
if (GenderGuesser::isMale($options['firstName'])) {
216+
return 'male';
217+
}
218+
219+
return 'female';
220+
},
221+
));
222+
}
223+
224+
Configure allowed values
225+
------------------------
226+
227+
Not all values are valid values for options. For instance, the ``gender``
228+
option can only be ``female`` or ``male``. You can configure these allowed
229+
values by calling
230+
:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setAllowedValues`::
231+
232+
// ...
233+
protected function setDefaultOptions(OptionsResolverInterface $resolver)
234+
{
235+
// ...
236+
237+
$resolver->setAllowedValues(array(
238+
'gender' => array('male', 'female'),
239+
));
240+
}
241+
242+
There is also a
243+
:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::addAllowedValues`
244+
method, which you can use if you want to add an allowed value to the previous
245+
setted allowed values.
246+
247+
Configure allowed Types
248+
~~~~~~~~~~~~~~~~~~~~~~~
249+
250+
You can also specify allowed types. For instance, the ``firstName`` option can
251+
be anything, but it must be a string. You can configure these types by calling
252+
:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setAllowedTypes`::
253+
254+
// ...
255+
protected function setDefaultOptions(OptionsResolverInterface $resolver)
256+
{
257+
// ...
258+
259+
$resolver->setAllowedTypes(array(
260+
'firstName' => 'string',
261+
));
262+
}
263+
264+
There is also a
265+
:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::addAllowedTypes`
266+
method, which you can use to add an allowed type to the previous allowed types.
267+
268+
Normalize the Options
269+
---------------------
270+
271+
Some values needs to be normalized before you can use them. For instance, the
272+
``firstName`` should always start with an uppercase letter. To do that, we can
273+
write normalizers. These Closures will be executed after all options are
274+
passed and return the normalized value. You can configure these normalizers by
275+
calling
276+
:method:`Symfony\\Components\\OptionsResolver\\OptionsResolver::setNormalizers`::
277+
278+
// ...
279+
protected function setDefaultOptions(OptionsResolverInterface $resolver)
280+
{
281+
// ...
282+
283+
$resolver->setNormalizers(array(
284+
'firstName' => function (Options $options, $value) {
285+
return ucfirst($value);
286+
},
287+
));
288+
}
289+
290+
You see that the closure also get an ``$options`` parameter. Sometimes, you
291+
need to use the other options for normalizing.
292+
293+
.. _Packagist: https://packagist.org/packages/symfony/options-resolver

0 commit comments

Comments
 (0)