Symfony中的配置等于验证配置。我想用treebuilder验证我的配置。在yml示例中,我给出了一个配置树的样子的例子(将来,树会比现在更大)。但要做到这一点,我需要一个创建一个结构。
现在你能帮我,创建树构建器吗?我已经尝试了arrayNode和原型的所有内容,但它不起作用。我得到例外,如

"FatalErrorException:错误:调用/var/www/menu_bundle/src/my/MenuBundle/DependencyInjection/Configuration中的未定义方法Symfony\Component\Config\Definition\Builder odeBuilder::prototype()。php第29行"


基本理念:

我想生成一个Symfony2-bundle,它在HTML中创建了一个menuStructure。为了生成HTML代码,我需要将yaml配置拉入对象结构,这可以工作,但使用symfony进行验证不起作用。..


这是一个关于如何菜单的快速示例。yml应该看起来像:

my_menu_structure:
    menu:
        name: test
        cssClass: blubb
        children:
            child:
                name: item1
                route: route1
                position: 0
                  child:
                    name: item11
                    route: route11
                    position: 0
              child:
                  name: item2
                  route: route2
                  position: 1

现在我想在Symfony2中配置Treebuilder,但它不起作用。.

经过几次尝试,这是我的最后一个版本:

    $treeBuilder = new TreeBuilder();
    $rootNode = $treeBuilder->root('my_menu');
        $rootNode
            ->children()
            ->arrayNode('menu')
            ->scalarNode('cssClass')
            ->defaultValue(array())
            ->prototype('array')
                ->scalarNode('name')
                ->scalarNode('route')
                ->scalarNode('Position')
                ->prototype('array')

        ->end()
        ->end()
        ->end();

我已经构建了Menu和MenuItems的对象。到目前为止一切正常,但我无法配置treebuilder。我正在寻找的是一种重用零件的方法(menuItem-:名字,路线和孩子)在树屋里,但到目前为止我发现的所有东西都帮不了我。..其他一切都有效,我唯一的问题是,我无法配置Treebuilder,并且我无法使用$this->container->get('menu.name')。这会引发异常:您已经请求了一项不存在的服务"menu.name"。

到目前为止,我已经尝试了prototype('array')的一些配置,但是phpStorm每次都说,它无法找到一个scalarNode作为prototype或->prototype()->children()->scalarNode()的子项。.

有帮助吗?

解决方案

我知道这个问题是从2014年1月开始的,但是当寻找错误消息"Call to undefined method Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition::arrayNode()"的解决方案时,这个StackOverflow问题出现在搜索结果中。

接受的答案实际上并没有提到错误消息的原因。

原海报给出的例子如下:

$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('my_menu');
$rootNode
        ->children()
        ->arrayNode('menu')
        ->scalarNode('cssClass')
        ->defaultValue(array())
        ->prototype('array')
            ->scalarNode('name')
            ->scalarNode('route')
            ->scalarNode('Position')
            ->prototype('array')

    ->end()
    ->end()
    ->end();

这是不正确的,因为每个节点必须以 end() 打电话。正如[文件][1]所述:

一般说来:定义节点后,调用end()将使您在层次结构中提升一步。

在我自己的情况下,我不清楚的是,在arrayNode中,两者都是 arrayNode() 定义为基础 children() 定义必须结束。

所以上面的例子将是正确的,如下所示:

$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('my_menu');
$rootNode
    ->children()
        ->scalarNode('cssClass')->end()
        ->arrayNode('menu')
            ->prototype('array')
                ->scalarNode('name')->end()
                ->scalarNode('route')->end()
                ->scalarNode('Position')->end()
            ->end()
        ->end()
    ->end()
->end();

希望这能帮助其他人比我更快地解决问题。

其他提示

what you can do is to configure your rootNode this way:

    $rootNode
        ->children()
            ->arrayNode('menu')
            ->isRequired()
            ->prototype('array')
                ->children()
                ->scalarNode('label')->isRequired()->end()
                ->scalarNode('class')->end() // I added an optional class parameter
                //others parameters
                    ->arrayNode('sub_menu')
                        ->prototype('array')
                        ->children()
                            ->scalarNode('label')->isRequired()->end()
                            ->scalarNode('route')->end()
                            ->scalarNode('class')->end()
                            // add as many parameters as you want for your children
                        ->end()
                    ->end()
                ->end()
            ->end()
            ->end()
        ->end();

Then you want to pass this variable to a service. Very simple class :

class AdminMenu
{

    protected $menu;

    public function setMenu($menu)
    {
        $this->menu = $menu;
    }

    public function getMenu()
    {
        return $this->menu;
    }


}

In you services.xml

    <parameter key="wf.admin_menu.class">Acme\AdminBundle\Library\AdminMenu</parameter>

    <service id="wf.admin_menu" class="%wf.admin_menu.class%">
    </service>

In your bundleAdminExtension class

    $myServiceDefintion = $container->getDefinition('wf.admin_menu');
    $myServiceDefintion->addMethodCall('setMenu', array($config['menu']));

Finally, in any controller you want:

 $menu = $this->container->get('wf.admin_menu');

That's all :)

Edit : Here's what my config looks like

my_bundle_admin:
  menu:
    unique_key:
      label : 'Level1-1'
      class : ''
      sub_menu:
        sub_unique_key1:
          label: 'Level2-1'
          route: 'my_route'
        sub_unique_key2:
          label: 'Level2-2'
          route: 'my_route'
    unique_key_2:
      label : 'Level1-2'
      sub_menu :
        sub_unique_key1:
          label : 'Level2-1'
          route : 'my_route'
        sub_unique_key2:
          label : 'Level2-2'
          route : 'my_route'
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top