2013-04-10 23 views
15

我的配置節點source可以同時支持stringarray值嗎?讓配置節點在Symfony 2配置中支持字符串和數組?

採購從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(); 

但如何CA我加上source的結構約束(操作,命令等)的變量節點(應該當其值array型只執行)?

回答

19

我認爲你可以通過重構你的擴展來使用配置規範化。

在您的擴展名更改您的代碼來檢查路徑設置

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

希望這是有幫助的。 最好的方面。

+0

還不錯。當'path'和'operations'和'commands'設置時,我應該處理這種情況。 +1給我 – gremo 2013-04-15 11:27:18

6

,能夠組合使用一個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: ~ 

當然,你不會得到很好的驗證規則一個正常的配置ation節點將爲您提供,您將無法在傳遞的數組(或字符串)上使用這些驗證規則,但是您將能夠驗證所使用的閉包中傳遞的數據。

+0

是的,我已經使用過這樣的東西。但是這次陣列節點非常複雜。 – gremo 2013-04-14 08:40:51

+0

我不確定是否有可能。你不能使用JMSDiExtraBundle使用的其他結構嗎? – 2013-04-14 12:48:02