2012-06-07 11 views
20

Básicamente me gustaría permitir a un arbitrario (pero no vacío) número de pares de valores clave en mi configuración, bajo billings nodo, es decir definir una array asociativo.Permitir pares de valores clave en la configuración semántica Symfony 2 Bundle

tengo esto en mi Configurator.php (parte de):

->arrayNode('billings') 
    ->isRequired() 
    ->requiresAtLeastOneElement() 
    ->prototype('scalar') 
    ->end() 
->end() 

Y luego, en mi config.yml:

my_bundle: 
    billings: 
     monthly : Monthly 
     bimonthly : Bimonthly 

Sin embargo, la salida de $config:

class MyBundleExtension extends Extension 
{ 
    /** 
    * {@inheritDoc} 
    */ 
    public function load(array $configs, ContainerBuilder $container) 
    { 
     $loader = new Loader\YamlFileLoader($container, 
      new FileLocator(__DIR__.'/../Resources/config')); 
     $loader->load('services.yml'); 

     $processor  = new Processor(); 
     $configuration = new Configuration(); 

     $config = $processor->processConfiguration($configuration, $configs); 

     $container->setParameter('my_bundle.billings', $config['billings']); 

     var_dump($config); 
     die(); 
    } 

} 

. .. lo que obtengo es índice de matriz por números, no un uno asociativa:

'billings' => 
    array (size=2) 
     0 => string 'Monthly' (length=7) 
     1 => string 'Bimonthly' (length=9) 

Por curiosidad (y si esto puede ayudar), estoy tratando de inyectar esta matriz como un parámetro de servicio (anotaciones de este gran paquete: JMSDiExtraBundle):

class BillingType extends \Symfony\Component\Form\AbstractType 
{ 

    /** 
    * @var array 
    */ 
    private $billingChoices; 

    /** 
    * @InjectParams({"billingChoices" = @Inject("%billings%")}) 
    * 
    * @param array $billingChoices 
    */ 
    public function __construct(array $billingChoices) 
    { 
     $this->billingChoices = $billingChoices; 
    } 
} 

Respuesta

21

Debe agregar useAttributeAsKey('name') a la configuración de su nodo de facturación en Configurator.php.

Más información sobre useAttributeAsKey() se puede leer en Symfony API Documentation

Después de configuración de nodos cambios de facturación, así debería ser:

->arrayNode('billings') 
    ->isRequired() 
    ->requiresAtLeastOneElement() 
    ->useAttributeAsKey('name') 
    ->prototype('scalar')->end() 
->end() 
+0

Gracias, lo que estoy dando una oportunidad y reportar de vuelta! – gremo

+0

¿Qué ocurre si quiero evitar 'isRequired' y proporcionar una matriz predeterminada en caso de nulo? –

+1

¿Estoy correcto que en '-> useAttributeAsKey ('name')' el 'nombre' tiene un significado especial o al menos se agrega automáticamente a la matriz? – martin

1

Recientemente tuve que configurar alguna configuración matrices anidadas.

necesidades eran

  • Un primer conjunto de nivel con teclas personalizadas (discribing un camino entidad)
  • cada una de esas matrices tenía que tener una o más etiquetas arbitrarias como llaves, con un valor booleano.

Para lograr tal configuración, debe utilizar el método casacade prototype().

Por lo tanto, la siguiente configuración:

my_bundle: 
    some_scalar: my_scalar_value 
    first_level: 
     "AppBundle:User": 
      first_tag: false 
     "AppBundle:Admin": 
      second_tag: true 
      third_tag: false 

se pueden obtener usando la siguiente configuración:

$treeBuilder = new TreeBuilder(); 
$rootNode = $treeBuilder->root('my_bundle'); 
$rootNode 
    ->addDefaultsIfNotSet() # may or may not apply to your needs 
    ->performNoDeepMerging() # may or may not apply to your needs 
    ->children() 
     ->scalarNode('some_scalar') 
      ->info("Some useful tips ..") 
      ->defaultValue('default') 
      ->end() 
     ->arrayNode('first_level') 
      ->info('Useful tips here..') 
      # first_level expects its children to be arrays 
      # with arbitrary key names 
      ->prototype('array') 
       # Those arrays are expected to hold one or more boolean entr(y|ies) 
       # with arbitrary key names 
       ->prototype('boolean') 
        ->defaultFalse()->end() 
       ->end() 
      ->end() 
     ->end() 
    ->end(); 
return $treeBuilder; 

Dumping $ config desde el interior de la clase de extensión da el siguiente resultado:

Array 
(
    [some_scalar] => my_scalar_value 
    [first_level] => Array 
     (
      [AppBundle:User] => Array 
       (
        [first_tag] => 
       ) 

      [AppBundle:Admin] => Array 
       (
        [second_tag] => 1 
        [third_tag] => 
       ) 
     ) 
) 

¡Y listo!

0

Esto es lo que realmente hace useAttributeAsKey:

/** 
* Sets the attribute which value is to be used as key. 
* 
* This is useful when you have an indexed array that should be an 
* associative array. You can select an item from within the array 
* to be the key of the particular item. For example, if "id" is the 
* "key", then: 
* 
*  array(
*   array('id' => 'my_name', 'foo' => 'bar'), 
* ); 
* 
* becomes 
* 
*  array(
*   'my_name' => array('foo' => 'bar'), 
* ); 
* 
* If you'd like "'id' => 'my_name'" to still be present in the resulting 
* array, then you can set the second argument of this method to false. 
* 
* This method is applicable to prototype nodes only. 
* 
* @param string $name   The name of the key 
* @param bool $removeKeyItem Whether or not the key item should be removed 
* 
* @return ArrayNodeDefinition 
*/ 
public function useAttributeAsKey($name, $removeKeyItem = true) 
{ 
    $this->key = $name; 
    $this->removeKeyItem = $removeKeyItem; 

    return $this; 
} 
Cuestiones relacionadas