Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive Structure in yaml with Symfony2 Treebuilder

Configuration in Symfony is equal to valdiating the configuration. I want to validate my configuration with the 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). 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. 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 "


Base idea:

I want to generate a Symfony2-bundle, which creates a menuStructure in HTML. 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...


Here is a quick example on how the menu.yml should look like:

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..

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. Everything works so far, but i can't configure the 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'). This throws an exception: You have requested a non-existent service "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()..

like image 254
DoomRoman Avatar asked Feb 04 '26 09:02

DoomRoman


1 Answers

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'
like image 134
Damien Ingrand Avatar answered Feb 07 '26 00:02

Damien Ingrand



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!