2014-02-25 3 views
2

Symfony의 구성은 구성을 valdiating하는 것과 같습니다. treebuilder를 사용하여 구성을 확인하고 싶습니다. yml-example에서는 config-tree가 어떻게 보이는지에 대한 예를 보여줍니다 (앞으로 트리가 더 커질 것입니다). 하지만 이렇게하려면 구조를 만들어야합니다.
이제 Treebuilder를 만들 수 있습니까? arrayNode 및 프로토 타입으로 모든 것을 시도했지만 작동하지 않습니다. 나는 예외를받습니다Symfony2 Treebuilder를 사용하는 yaml의 재귀 구조

"/ var/www/menu_bundle/src/my/MenuBundle/DependencyInjection/Configuration의 FatalErrorException : 오류 : 정의되지 않은 메소드 Symfony \ Component \ Config \ Definition \ Builder \ NodeBuilder :: prototype() .PHP 라인 29 "


자료 아이디어 :

내가 HTML에 menuStructure을 만드는 Symfony2 - 번들을 생성하고 싶습니다. HTML 코드를 생성하려면 객체 구조체에 yaml-configuration을 가져와야합니다.이 코드는 작동하지만 symfony로 유효성 검사를하지 않으면 작동하지 않습니다 ...


다음은 간단한 예제입니다. 같은 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 

지금 내가 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를 구성 할 수 없습니다. 내가 찾고있는 것은 treebuilder에서 일부 (menuItem- : 이름, 경로 및 하위)를 재사용하는 방법이지만 지금까지 찾은 모든 것이 나를 도울 수는 없습니다 ... 다른 모든 기능, 내 유일한 문제는 Treebuilder를 구성 할 수없고 $ this-> container-> get ('menu.name')을 사용하여 yml 구성을 가져올 수 없다는 것입니다. 예외가 발생합니다 : 존재하지 않는 서비스 "menu.name"을 요청했습니다.

지금까지 프로토 타입 ('배열')로 일부 구성을 시도했지만 phpStorm은 매번 프로토 타입 또는 prototype() -> children()의 자식으로 scalarNode를 찾을 수 없다고 말합니다. -> scalarNode() ..

+1

안녕하세요, stackoverflow에 오신 것을 환영합니다. [KnpMenuBundle] (https://github.com/KnpLabs/KnpMenuBundle)을 사용해 볼 수 있습니다. 단지 몇 센트. 지금까지 시도한 내용을 포함하도록 질문을 편집하십시오. ** 구체적인 문제 **가 지금 당신에게 있습니다. "* 작동하지 않습니다 *"stackoverflow에 대한 유효한 질문이 아닙니다. – nifr

+0

@nifr 내가 시도한 것과 내가 한 일에 대한 정보를 추가했습니다. ;-) – DoomRoman

답변

0

이 질문은 januari 2014에서 알 수 있습니다. 그러나 "StackOverflow 정의되지 않은 메서드 호출은 정의되지 않은 메서드 Symfony \ Component \ Config \ Definition \ Builder \ ArrayNodeDefinition :: arrayNode()"에 대한 해결책을 찾고있을 때 나타났습니다. 검색 결과에

허용되는 대답은 실제로 오류 메시지의 원인을 언급하지 않습니다. 각 노드가 end() 호출로 종료해야하기 때문에

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

이 잘못된 다음과 같이

원래 포스터에 의해 주어진 예입니다. [1] 상태에서 [문서]으로 : 내 자신의 경우

In general: after defining a node, a call to end() takes you one step up in the hierarchy.

, 무엇을, 나에게 불분명 것은 arrayNode의 defition에 기본 children() 정의와 arrayNode() 정의가 모두 종료해야한다는 사실이었다.

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

는 희망이 다른 사람이 빨리 나보다 문제를 해결하는 데 도움이됩니다 다음과 같이

따라서 위의 예는 올바른 것입니다.

1

은 당신이 할 수있는 일은 당신의 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(); 

는 그런 다음 서비스에이 변수를 전달해야합니다. 매우 간단한 클래스 :

class AdminMenu 
{ 

    protected $menu; 

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

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


} 

서비스 중.

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

마지막으로 당신의 bundleAdminExtension 클래스에서 XML

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

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

, 어떤 컨트롤러 당신이 원하는 :

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

모든 :)

편집 : 여기 내 설정의 모습입니다

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'