简体   繁体   English

使用Symfony2 Treebuilder在yaml中进行递归结构

[英]Recursive Structure in yaml with Symfony2 Treebuilder

Configuration in Symfony is equal to valdiating the configuration. Symfony中的配置等同于验证配置。 I want to validate my configuration with the treebuilder. 我想用treebuilder验证我的配置。 In the yml-example, i give a quite example of how the config-tree will look like (in future, the tree will be even bigger than now). 在yml-example中,我给出了一个很好的示例,说明了config-tree的样子(将来,该树将比现在更大)。 But to do this, i need a to create a structure. 但是要做到这一点,我需要创建一个结构。
Now Could you help me, to create the treebuilder? 现在您能帮我创建树构建器吗? I've tried everything with arrayNode and prototypes, but it won't work. 我已经使用arrayNode和原型尝试了所有方法,但无法正常工作。 I get exceptions like 我收到类似的异常

"FatalErrorException: Error: Call to undefined method Symfony\\Component\\Config\\Definition\\Builder\\NodeBuilder::prototype() in /var/www/menu_bundle/src/my/MenuBundle/DependencyInjection/Configuration.php line 29 " “ FatalErrorException:错误:调用/var/www/menu_bundle/src/my/MenuBundle/DependencyInjection/Configuration.php第29行中未定义的方法Symfony \\ Component \\ Config \\ Definition \\ Builder \\ NodeBuilder :: prototype()


Base idea: 基本思路:

I want to generate a Symfony2-bundle, which creates a menuStructure in HTML. 我想生成一个Symfony2-bundle,它在HTML中创建一个menuStructure。 For generateing the HTML-Code, i need to pull the yaml-configuration in to an object-structure, this works, but the validating with symfony doesn't work... 为了生成HTML代码,我需要将yaml-configuration放入对象结构中,这可行,但是用symfony进行验证不起作用...


Here is a quick example on how the menu.yml should look like: 这是有关menu.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

Now i want to configure the Treebuilder in Symfony2, but it won't work.. 现在,我想在Symfony2中配置Treebuilder,但是它不起作用。

After a few times of trying, this is my last version: 经过几次尝试,这是我的最新版本:

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

I have build the objects for Menu and MenuItems. 我已经建立了Menu和MenuItems的对象。 Everything works so far, but i can't configure the treebuilder. 到目前为止一切正常,但是我无法配置treebuilder。 What I'm searching for, is a way to reuse a part (menuItem-: name, route and children) in the treebuilder, but everything I found so far, couldn't help me... Everything else works, my only problem is, that I can't configure the Treebuilder and I can't get the config out of the yml with $this->container->get('menu.name'). 我正在寻找的是一种在树构建器中重用零件(menuItem-:名称,路线和子节点)的方法,但是到目前为止,我发现的所有内容都无济于事……其他所有方法都可以解决,这是我唯一的问题是,我无法配置Treebuilder,也无法使用$ this-> container-> get('menu.name')从yml中获取配置。 This throws an exception: You have requested a non-existent service "menu.name". 这将引发异常:您请求的服务“ menu.name”不存在。

So far, I've tried some Configuration with prototype('array'), but phpStorm says everytime, it can't find a scalarNode as a child of prototype or of ->prototype()->children()->scalarNode().. 到目前为止,我已经尝试了一些带有prototype('array')的Configuration,但是phpStorm每次都说它找不到scalarNode作为prototype的子代或-> prototype()-> children()-> scalarNode( )..

what you can do is to configure your rootNode this way: 您可以执行以下操作来配置rootNode:

    $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 在您的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 在bundleAdminExtension类中

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

I know this question dates from januari 2014, however when looking for a solution to the error message "Call to undefined method Symfony\\Component\\Config\\Definition\\Builder\\ArrayNodeDefinition::arrayNode()" this StackOverflow question came up in the search results. 我知道这个问题可以追溯到2014年1月,但是在寻找错误消息“调用未定义的方法Symfony \\ Component \\ Config \\ Definition \\ Builder \\ ArrayNodeDefinition :: arrayNode()”的解决方案时,搜索结果中出现了这个StackOverflow问题。

The accepted answer doesn't actually mention the reason of the error message. 接受的答案实际上并未提及错误消息的原因。

The example given by the original poster is as follows: 原始张贴者给出的示例如下:

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

This is incorrect because each node must be ended with an end() call. 这是不正确的,因为每个节点都必须以end()调用end() As the [documentation][1] states: 如[文档] [1]所述:

In general: after defining a node, a call to end() takes you one step up in the hierarchy. 通常,在定义节点之后,对end()的调用使您在层次结构中上了一步。

In my own case, what was unclear to me, was the fact that in an arrayNode defition both the arrayNode() definition as the underlying children() definition must be ended. 在我自己的情况下,我不清楚的是,在arrayNode定义中,必须将arrayNode()定义作为基础children()定义都结束。

So the above example would be correct as follows: 因此,上面的示例将是正确的,如下所示:

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

Hopefully this will help others fix the problem quicker than I did. 希望这可以帮助其他人比我更快地解决问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM