Recursiva Estrutura em yaml com Symfony2 Treebuilder
-
21-12-2019 - |
Pergunta
Configuração no Symfony é igual a valdiating a configuração.Eu quero validar a minha configuração com o treebuilder.No yml-exemplo, eu dou um exemplo bastante de como a config-árvore será parecido (no futuro, a árvore vai ser ainda maior do que agora).Mas, para isso, eu preciso de um para criar uma estrutura.
Agora você Poderia me ajudar, para criar o treebuilder?Já tentei de tudo com arrayNode e protótipos, mas ele não vai funcionar.Eu exceções como chegar
"FatalErrorException:Erro:Chamada indefinido método Symfony\Component\Config\Definition\Construtor odeBuilder::protótipo() em /var/www/menu_bundle/src/my/MenuBundle/DependencyInjection/Configuration.php linha 29 "
Ideia Base:
Eu quero gerar um Symfony2-bundle, o que cria uma estrutura em HTML.Para generateing Código HTML, eu preciso puxar o yaml-configuração para um objeto-estrutura, isso funciona, mas a validar com o symfony não funciona...
Aqui está um exemplo rápido de como menu.yml deve se parecer:
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
Agora eu quero configurar o Treebuilder no Symfony2, mas ele não vai funcionar..
Depois de alguns momentos de tentar, esta é a minha última versão:
$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();
Eu tenho construir os objetos para o Menu e os itens dos menus.Tudo funciona tão longe, mas eu não posso configurar o treebuilder.O que eu estou procurando, é uma maneira de reutilizar uma parte (menuItem-:nome de rota, e as crianças) no treebuilder, mas tudo que eu encontrei até agora, não poderia me ajudar...Tudo o resto funciona, o meu único problema é que eu não posso configurar o Treebuilder e eu não consigo ter a configuração fora do yml com $this->contentor->get('menu.nome').Isso lança uma exceção:Você solicitou um serviço inexistente "no menu.o nome".
Até então, eu tentei de alguma Configuração com o protótipo('matriz'), mas phpStorm diz sempre, ele não pode encontrar uma scalarNode como uma criança de protótipo ou de>protótipo()->filhos()->scalarNode()..
Solução
Eu sei que esta pergunta datas de januari de 2014, no entanto, quando à procura de uma solução para a mensagem de erro "Chamada indefinido método Symfony\Component\Config\Definition\Construtor\ArrayNodeDefinition::arrayNode()" este StackOverflow pergunta veio nos resultados da pesquisa.
Aceito a resposta, na verdade, não mencionar o motivo da mensagem de erro.
O exemplo dado pelo autor é o seguinte:
$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();
Isso é incorreto, porque cada nó deve ser terminada com um end()
chamada.Como o [documentação][1], afirma:
Em geral:após a definição de um nó, uma chamada para terminar() leva você a um passo acima na hierarquia.
No meu caso, o que ficou claro para mim, foi o fato de que, em um arrayNode defition tanto o arrayNode()
definição subjacente children()
definição tem de ser encerrado.
Para o exemplo acima seria correcto da seguinte forma:
$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();
Esperemos que isto irá ajudar os outros a resolver o problema mais rápido do que eu fiz.
Outras dicas
o que você pode fazer é configurar o seu nó raiz (rootNode) desta forma:
$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();
Então você quer passar para essa variável para um serviço.Muito simples de classe :
class AdminMenu
{
protected $menu;
public function setMenu($menu)
{
$this->menu = $menu;
}
public function getMenu()
{
return $this->menu;
}
}
Em você services.xml
<parameter key="wf.admin_menu.class">Acme\AdminBundle\Library\AdminMenu</parameter>
<service id="wf.admin_menu" class="%wf.admin_menu.class%">
</service>
Em seu bundleAdminExtension classe
$myServiceDefintion = $container->getDefinition('wf.admin_menu');
$myServiceDefintion->addMethodCall('setMenu', array($config['menu']));
Finalmente, em qualquer controlador que você deseja:
$menu = $this->container->get('wf.admin_menu');
Isso é tudo :)
Editar :Aqui está o que a minha config parece
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'