使用ArrayNodeDefinition :: addDefaultChildrenIfNoneSet()的奇怪行为

I'm using Symfony Config Component in Silex framework and I need to have an array of data which holds an array of versions :

some_data:
    # some config...
    versions:
        - 1.1
        - 1.2-beta
        ...

Here's a glimpse at the config tree builder :

$node = $treeBuilder->root('some_data');

$node
    ->children()
        // some nodes...
        ->arrayNode('versions')
            ->addDefaultChildrenIfNoneSet()
            ->validate()
                ->ifTrue(function ($v) {
                    return !empty($v);
                })
                ->then(function ($v) {
                    $array = array_values(array_unique($v));
                    sort($array, SORT_NATURAL | SORT_FLAG_CASE);

                    return $array;
                })
            ->end()
            ->prototype('scalar')->defaultValue('1')->end()
        ->end()
    ->end()
->end()

When no versions are set I got default 1, alright. But when I add some other versions and then try to delete default value 1, it always comes back after processing config.

Does someone understand what I am doing wrong ? Is it an expected behaviour ?

It seems that addDefaultChildrenIfNoneSet() acts as a validation and while processing configuration both addDefaultChildrenIfNoneSet() and ->validate() result are merged.

To avoid this behaviour just add performNoDeepMerging() to the node :

$node = $treeBuilder->root('some_data');

$node
    ->children()
        // some nodes...
        ->arrayNode('versions')
            ->addDefaultChildrenIfNoneSet()
            ->performNoDeepMerging() // This is the fix
            ->validate()
                ->ifTrue(function ($v) {
                    return !empty($v);
                })
                ->then(function ($v) {
                    $array = array_values(array_unique($v));
                    sort($array, SORT_NATURAL | SORT_FLAG_CASE);

                    return $array;
                })
            ->end()
            ->prototype('scalar')->defaultValue('1')->end()
        ->end()
    ->end()
->end()

see http://symfony.com/doc/current/components/config/definition.html#optional-sections

another ways to do it :

// add a default value on the array, not on the prototype :
$node
    ->children()
        // some nodes...
        ->arrayNode('versions')
            ->validate()
                ->ifTrue(function ($v) {
                    return !empty($v);
                })
                ->then(function ($v) {
                    $array = array_values(array_unique($v));
                    sort($array, SORT_NATURAL | SORT_FLAG_CASE);

                    return $array;
                })
            ->end()
            ->prototype('scalar')->end()
            ->defaultValue(['1']) // this is a fix
        ->end()
    ->end()
->end()

// or just use one validation rule
$node
    ->children()
        // some nodes...
        ->arrayNode('versions')
            ->validate()
                ->always(function ($v) { // another fix
                    if (empty($v)) {
                        return ['1'];
                    }

                    $array = array_values(array_unique($v));
                    sort($array, SORT_NATURAL | SORT_FLAG_CASE);

                    return $array;
                })
            ->end()
            ->prototype('scalar')->end()
        ->end()
    ->end()
->end()