-
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
Description
Currently, the only way to make an arrayNode a map, rather than a list, is to use useAttributeAsKey, the problem with that method is that it requires you to use an attribute within the array as the key. What if you want to use the array key as the .. array key?
For example
->arrayNode('servers')
->prototype('array')
->children()
->scalarNode('username')
->isRequired()
->end()
->scalarNode('password')
->isRequired()
->end()
->end()
->end()
->end()
with config
something:
servers:
serverA:
username: userA
password: passwordA
serverB:
username: userB
password: passwordB
comes out as
servers [
serverA => [username: userA, password: passwordA],
serverB => [username: userB, password: passwordB],
]
Great! Until.. you merge config across files. If you put serverA in a file and import it, then add serverB, it comes out like -
servers [
serverA => [username: userA, password: passwordA],
0 => [username: userB, password: passwordB],
]
The key for the nodes get lost. This issue is described on https://symfony.com/doc/current/components/config/definition.html
As of writing this, there is an inconsistency: if only one file provides the configuration in question, the keys (i.e. sf_connection and default) are not lost. But if more than one file provides the configuration, the keys are lost as described above.
that's ..not great. Especially if you're relying on referencing that key from somewhere else in your config (i.e. default_server: ..). However, since we've not indicated the arrayNode is a map, I guess this behaviour was undefined (probably odd it kept the string keys in the first place).
You could argue that if the key is important, to put it in the attributes, like
something:
servers:
-
username: userA
password: passwordA
server: serverA
-
username: userB
password: passwordB
server: serverB
with useAttributeAsKey('server'). However, this is not a very efficient way of writing configuration - it's clearly more for XML based processing, not YAML.
One way people have been getting around this is to use useAttributeAsKey with an attribute that doesn't exist, like ->useAttributeAsKey('some_field_that_doesnt_exist') which seems pretty hacky.
Suggest something like
-
adding
->useAsMap()which turns the array into a map internally, or -
breaking
arrayNodeintolistNodeandmapNodetypes (witharrayNodedefaulting tolistNodefor backward compatibility for a while).
Related
- [Configuration] Use of source keys as result keys for prototype nodes #12304
- [Config] Clarify the difference between lists and maps symfony-docs#4509
- [Config] Support for dynamic array node definitions #17436
- https://stackoverflow.com/questions/10924504/allowing-key-value-pairs-in-symfony-2-bundle-semantic-configuration