在Symfony 2配置中使配置节点支持字符串和数组?

时间:2013-04-10 09:39:50

标签: symfony configuration dependency-injection symfony-2.1

我的配置节点source是否支持stringarray值?

string采购:

# Valid configuration 1
my_bundle:
    source: %kernel.root_dir%/../Resources/config/source.json

array采购:

# Valid configuration 2
my_bundle:
    source:
        operations: []
        commands: []

扩展类可以区分它们:

if (is_array($config['source']) {
    // Bootstrap from array
} else {
    // Bootstrap from file
}

我可能会使用这样的东西:

$rootNode->children()
    ->variableNode('source')
        ->validate()
            ->ifTrue(function ($v) { return !is_string($v) && !is_array($v); })
            ->thenInvalid('Configuration value must be either string or array.')
        ->end()
    ->end()
->end();

但是我如何向变量节点添加source(操作,命令等等)的结构约束(只应在其值为array时强制执行) ?

2 个答案:

答案 0 :(得分:20)

我认为您可以通过重构扩展程序来使用配置规范化。

在您的扩展程序中更改代码以检查路径是否已设置

if ($config['path'] !== null) {
    // Bootstrap from file.
} else {
    // Bootstrap from array.
}

并允许用户使用字符串进行配置。

$rootNode
    ->children()
        ->arrayNode('source')
            ->beforeNormalization()
            ->ifString()
                ->then(function($value) { return array('path' => $value); })
            ->end()
            ->children()
                ->scalarNode('foo')
                // ...
            ->end()
        ->end()
    ->end()
;

像这样,您可以允许用户使用可以验证的字符串或数组。

请参阅symfony documentation for normalisation

希望它有用。 最好的。

答案 1 :(得分:7)

可以将variable node类型与一些自定义验证逻辑结合使用:

<?php
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\Exception\InvalidTypeException;

public function getConfigTreeBuilder()
{
    $treeBuilder = new TreeBuilder();
    $rootNode = $treeBuilder->root('my_bundle');

    $rootNode
        ->children()
            ->variableNode('source')
                ->validate()
                    ->ifTrue(function ($v) {
                        return false === is_string($v) && false === is_array($v);
                    })
                    ->thenInvalid('Here you message about why it is invalid')
                ->end()
            ->end()
        ->end();
    ;

    return $treeBuilder;
}

这将成功完成:

my_bundle:
    source: foo

# and

my_bundle:
    source: [foo, bar]

但它不会处理:

my_bundle:
    source: 1

# or

my_bundle
    source: ~

当然,您将无法获得正常配置节点将为您提供的良好验证规则,并且您将无法在传递的数组(或字符串)上使用这些验证规则,但您将能够验证在使用的闭包中传递数据。