Php 使用ArrayNodeDefinition::AddDefaultChildreniFuneset()的奇怪行为

Php 使用ArrayNodeDefinition::AddDefaultChildreniFuneset()的奇怪行为,php,symfony,yaml,config,Php,Symfony,Yaml,Config,我在Silex framework中使用的是Symfony配置组件,我需要有一个数据数组来保存一个版本数组: some_data: # some config... versions: - 1.1 - 1.2-beta ... 下面是对配置树生成器的简要介绍: $node = $treeBuilder->root('some_data'); $node ->children() // some

我在Silex framework中使用的是Symfony配置组件,我需要有一个数据数组来保存一个版本数组:

some_data:
    # some config...
    versions:
        - 1.1
        - 1.2-beta
        ...
下面是对配置树生成器的简要介绍:

$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()
当没有设置
版本时,我得到了默认的
1
,好的。 但当我添加一些其他版本,然后尝试删除默认值
1
,它总是在处理配置后返回

有人知道我做错了什么吗?
这是一种预期行为吗?

似乎
addDefaultChildrenIfNoneSet()
充当验证,并且在处理配置时,将
addDefaultChildrenIfNoneSet()
->validate()
结果合并

要避免这种行为,只需向节点添加
performNoDeepMerging()

$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()

另一种方法是:

// 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()

似乎
addDefaultChildrenIfNoneSet()
充当验证,在处理配置时,将
addDefaultChildrenIfNoneSet()
->validate()
结果合并

要避免这种行为,只需向节点添加
performNoDeepMerging()

$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()

另一种方法是:

// 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()