Skip to content

Commit 2c3d526

Browse files
committed
Merge pull request #1721 from richardmiller/adding_detail_to_config_tree
Adding some information on normalisation and appending sections in a con...
2 parents 6bd02b2 + 2da7c96 commit 2c3d526

File tree

1 file changed

+163
-0
lines changed

1 file changed

+163
-0
lines changed

components/config/definition.rst

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,168 @@ For all nodes:
212212
``cannotBeOverwritten()``
213213
don’t let other configuration arrays overwrite an existing value for this node
214214

215+
Appending sections
216+
------------------
217+
218+
If you have a complex configuration to validate then the tree can grow to
219+
be large and you may want to split it up into sections. You can do this by
220+
making a section a separate node and then appending it into the main tree
221+
with ``append()``::
222+
223+
public function getConfigTreeBuilder()
224+
{
225+
$treeBuilder = new TreeBuilder();
226+
$rootNode = $treeBuilder->root('database');
227+
228+
$rootNode
229+
->arrayNode('connection')
230+
->children()
231+
->scalarNode('driver')
232+
->isRequired()
233+
->cannotBeEmpty()
234+
->end()
235+
->scalarNode('host')
236+
->defaultValue('localhost')
237+
->end()
238+
->scalarNode('username')->end()
239+
->scalarNode('password')->end()
240+
->booleanNode('memory')
241+
->defaultFalse()
242+
->end()
243+
->end()
244+
->append($this->addParametersNode())
245+
->end()
246+
;
247+
248+
return $treeBuilder;
249+
}
250+
251+
public function addParametersNode()
252+
{
253+
$builder = new TreeBuilder();
254+
$node = $builder->root('parameters');
255+
256+
$node
257+
->isRequired()
258+
->requiresAtLeastOneElement()
259+
->useAttributeAsKey('name')
260+
->prototype('array')
261+
->children()
262+
->scalarNode('name')->isRequired()->end()
263+
->scalarNode('value')->isRequired()->end()
264+
->end()
265+
->end()
266+
;
267+
268+
return $node;
269+
}
270+
271+
This is also useful to help you avoid repeating yourself if you have sections
272+
of the config that are repeated in different places.
273+
274+
Normalization
275+
-------------
276+
277+
When the config files are processed they are first normalized, they are then
278+
merged and then the tree is used to validate the resulting array. The normalization
279+
is to remove some of the differences that result from different configuration formats,
280+
mainly the differences between Yaml and XML.
281+
282+
The separator used in keys is typically ``_`` in Yaml and ``-`` in XML. For
283+
example, ``auto_connect`` in Yaml and ``auto-connect``. The normalization would
284+
make both of these ``auto_connect``.
285+
286+
Another difference between Yaml and XML is in the way arrays of values may
287+
be represented. In Yaml you may have:
288+
289+
.. code-block:: yaml
290+
291+
twig:
292+
extensions: ['twig.extension.foo', 'twig.extension.bar']
293+
294+
and in XML:
295+
296+
.. code-block:: xml
297+
298+
<twig:config>
299+
<twig:extension>twig.extension.foo</twig:extension>
300+
<twig:extension>twig.extension.bar</twig:extension>
301+
</twig:config>
302+
303+
This difference can be removed in normalization by pluralizing the key used
304+
in XML. You can specify that you want a key to be pluralized in this way with
305+
``fixXmlConfig()``::
306+
307+
$rootNode
308+
->fixXmlConfig('extension')
309+
->children()
310+
->arrayNode('extensions')
311+
->prototype('scalar')->end()
312+
->end()
313+
->end()
314+
;
315+
316+
If it is an irregular pluralization you can specify the plural to use as
317+
a second argument::
318+
319+
$rootNode
320+
->fixXmlConfig('child', 'children')
321+
->children()
322+
->arrayNode('children')
323+
->end()
324+
;
325+
326+
As well as fixing this it ensures that single xml elements are still turned into an array.
327+
So you may have:
328+
329+
.. code-block:: xml
330+
331+
<connection>default</connection>
332+
<connection>extra</connection>
333+
334+
and sometimes only:
335+
336+
.. code-block:: xml
337+
338+
<connection>default</connection>
339+
340+
By default ``connection`` would be an array in the first case and a string
341+
in the second making it difficult to validate. You can ensure it is always
342+
an array with with ``fixXmlConfig``.
343+
344+
You can further control the normalization process if you need to. For example
345+
you may want to allow a string to be set and used as a particular key or several
346+
keys to be set explicitly. So that, if everything apart from id is optional in this
347+
config:
348+
349+
.. code-block:: yaml
350+
351+
connection:
352+
name: my_mysql_connection
353+
host: localhost
354+
driver: mysql
355+
username: user
356+
password: pass
357+
358+
you can allow the following as well:
359+
360+
.. code-block:: yaml
361+
362+
connection: my_mysql_connection
363+
364+
By changing a string value into an associative array with ``name`` as the key::
365+
366+
$rootNode
367+
->arrayNode('connection')
368+
->beforeNormalization()
369+
->ifString()
370+
->then(function($v) { return array('name'=> $v); })
371+
->end()
372+
->scalarValue('name')->isRequired()
373+
// ...
374+
->end()
375+
;
376+
215377
Validation rules
216378
----------------
217379

@@ -278,3 +440,4 @@ Otherwise the result is a clean array of configuration values::
278440
$processor = new Processor();
279441
$configuration = new DatabaseConfiguration;
280442
$processedConfiguration = $processor->processConfiguration($configuration, $configs);
443+

0 commit comments

Comments
 (0)