22

基本上我想在我的配置中允许任意(但不是空)数量的键值对billings,在节点下,即定义一个关联数组

我的Configurator.php(部分)中有这个:

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

然后,在我的config.yml

my_bundle:
    billings:
        monthly : Monthly
        bimonthly : Bimonthly

但是,输出$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();
    }

}

...我得到的是按数字排列的数组索引,而不是关联的:

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

出于好奇(如果这有帮助),我正在尝试将此数组作为服务参数注入(来自这个伟大捆绑包的注释: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;
    }
} 
4

4 回答 4

24

您应该添加useAttributeAsKey('name')到您的计费节点配置中Configurator.php

更多关于useAttributeAsKey()你的信息可以阅读Symfony API 文档

更改计费节点配置后,应如下所示:

->arrayNode('billings')
    ->isRequired()
    ->requiresAtLeastOneElement()
    ->useAttributeAsKey('name')
    ->prototype('scalar')->end()
->end()
于 2012-06-07T06:20:46.303 回答
2

您可以添加如下内容:

->arrayNode('billings')
    ->useAttributeAsKey('whatever')
    ->prototype('scalar')->end()

之后键会神奇地出现。

见:https ://github.com/symfony/symfony/issues/12304

于 2014-10-23T16:45:36.097 回答
2

我最近不得不设置一些嵌套数组配置。

需求是

  • 具有自定义键的第一级数组(描述实体路径)
  • 这些数组中的每一个都必须有一个或多个任意标签作为键,并带有布尔值。

要实现这样的配置,您必须使用级联prototype()方法。

所以,下面的配置:

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

可以使用以下配置获得:

$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;

从扩展类内部转储 $config 会得到以下输出:

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

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

瞧!

于 2016-05-10T14:02:22.337 回答
0

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;
}
于 2017-12-01T08:40:09.020 回答