15

我的配置节点可以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(操作、命令等)的结构约束添加到变量节点(仅当其值为 type 时才应强制执行array)?

4

2 回答 2

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 文档进行规范化

希望它有帮助。最良好的问候。

于 2013-04-14T18:35:25.513 回答
7

It is possible to use a variable node type in combination with some custom validation logic:

<?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;
}

This will succesfully process:

my_bundle:
    source: foo

# and

my_bundle:
    source: [foo, bar]

but it won't process:

my_bundle:
    source: 1

# or

my_bundle
    source: ~

Of course, you won't get the nice validation rules a normal configuration node will provide you and you won't be able to use those validation rules on the array (or string) passed but you will be able to validate the passed data in the closure used.

于 2013-04-13T18:07:23.407 回答