使用 ArrayNodeDefinition::addDefaultChildrenIfNoneSet() 的奇怪行为
weird behaviour using ArrayNodeDefinition::addDefaultChildrenIfNoneSet()
我在 Silex 框架中使用 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()
当没有设置 versions
时,我得到默认的 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()
见http://symfony.com/doc/current/components/config/definition.html#optional-sections
另一种方法:
// 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()
我在 Silex 框架中使用 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()
当没有设置 versions
时,我得到默认的 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()
见http://symfony.com/doc/current/components/config/definition.html#optional-sections
另一种方法:
// 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()