Рекурсивная структура в Ямле с Symfony2 TreeBuilder
-
21-12-2019 - |
Вопрос
в Symfony равно Valdiation конфигурации.
Я хочу подтвердить свою конфигурацию с TreeBuilder. В приведении YML я даю вполне пример того, как будет выглядеть конфигурация (в будущем, дерево будет еще больше, чем сейчас). Но чтобы сделать это, мне нужно, чтобы создать структуру.
Теперь вы могли бы помочь мне, создать TreeBuilder? Я перепробовал все с арайнодом и прототипами, но это не будет работать. Я получаю исключения, такие как
"fatalerroreException: Ошибка: Ошибка: Вызов undefined Метод Symfony \ Компонент \ Config \ Определение \ Builder \ Nodebuilder :: Prototype () в /var/www/menu_bundle/src/my/menubundle/dependententsinection/configuration.php line 29"
Базовая идея:
Я хочу создать Symfony2-Bundle, что создает мерутраструктуру в HTML. Для генерации HTML-кода мне нужно потянуть yaml-configuration в объектной структуре, это работает, но проверка с Symfony не работает ...
Вот быстрый пример о том, как должен выглядеть меню.
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
.
Теперь я хочу настроить Treebuilder в Symfony2, но это не будет работать ..
После нескольких времен попыток, это моя последняя версия:
$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();
.
Я создал объекты для меню и меню. Все работает так далеко, но я не могу настроить TreeBuilder. Что я ищу, это способ повторно использовать часть (меню -: имя, маршрут и дети) в TreeBuilder, но все, что я нашел до сих пор, не мог мне помочь ... Все остальное работает, моя единственная проблема в том, что я не могу настроить TreeBuilder, и я не могу получить конфигурацию из YML с $ This-> Container-> Get («Menu.name»). Это бросает исключение: вы запросили несуществующую службу «Меню .Name».
До сих пор я попробовал некоторую конфигурацию с прототипом («массив»), но PHPSTRM говорит, что каждый раз он не может найти касально, как ребенок прототипа или -> прототипа () -> детей () - > Scalarnode () ..
Решение
Я знаю, что этот вопрос даты вопроса от Januari 2014, однако при ищете решение сообщения об ошибке «Вызов неопределенному методу Symfony \ Component \ Confign \ diance \ Builder \ Arraynodefinition :: 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] состояния:
В общем: после определения узла вызов для завершения () приводит к работе в иерархии.
В моем собственном случае то, что мне неясно, было то, что в порядкеретении Arraynode как определение генеракодицетагкода, поскольку основное определение 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();
.
Надеюсь, это поможет другим исправить проблему быстрее, чем я.
Другие советы
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'