Вложенное меню с параметрами в Symfony и KNPmenu

Я борюсь с Symfony2 и Knpmenu, чтобы создать меню, которое обрабатывает:

  • панировочные сухари
  • маршрутизация с динамическими параметрами
  • рендеринг отдельных меню, начинающихся с разных детей

Мой файл Menu/Builder.php выглядит так (дополнительные биты, такие как navbar, pull-nav и т. д., являются частью расширения mopa_bootstrap, которое обрабатывает рендеринг с использованием классов начальной загрузки):

namespace My\AppBundle\Menu;

use Knp\Menu\FactoryInterface;

class Builder
{
    public function mainMenu(FactoryInterface $factory, array $options)
    {
        $menu = $factory->createItem(
            'root', array(
                'navbar' => true,
                'pull-right' => true,
            )
        );

        // Main Menu -> Config
        // no link here, it's just a placeholder
        $dropdown = $menu->addChild(
            'Config', array(
                'dropdown' => true,
                'caret' => true,
            )
        );

        // Menu -> Config -> User
        $dropdown2 = $dropdown ->addChild(
            'User', array(
                'route' => 'user',
            )
        );

        // Secondary Menu -> Edit (but child of Menu -> Config -> User)
        $dropdown2->addChild(
            'Edit',
            array(
                'route' => 'user_edit',
                'routeParameters' => array('name' => $options['id']),
            )
        );

Идея состоит в том, чтобы иметь главное меню, которое печатает только первые два уровня, и отдельное меню, которое отображается в другом месте, чтобы пользователи могли перемещаться между режимами редактирования/удаления/любыми представлениями этого конкретного просматриваемого элемента.

Чего я пытаюсь достичь, так это иметь единую структуру, таким образом, для обработки родительской структуры, не только для того, чтобы родители-знаки были активны в меню, но и для того, чтобы иметь возможность обрабатывать работающую структуру хлебных крошек.

ВResources/views/base.html.twig вызываю главное меню так:

{{ mopa_bootstrap_menu('MyAppBundle:Builder:mainMenu', {depth: 2}) }}

А в идеале такое подменю:

{% set id = app.request.attributes.get('id') %}
{% if app.request.attributes.get('_route') starts with 'user_' %}
    {% set menu = knp_menu_get('MyAppBundle:Builder:mainMenu', ['User'], {'id': id }) %}
    {{ knp_menu_render(menu) }}
{% endif %}

Тем не мение:

  1. knpmenu возвращает ошибку при рендеринге главного меню, так как $options['id'] не определено
  2. Я все еще не могу отобразить вторичное меню (поэтому, передав параметр «Пользователь») - страница просто возвращает черный вывод в этом блоке

Правилен ли этот подход? Я использую "knplabs/knp-menu": "2.0.*@dev" и "symfony/symfony": "2.5.*"


person cellulosa    schedule 01.07.2014    source источник


Ответы (1)


Как оказалось, использование этого метода позволило получить эффективный доступ к $request и добавить условие в файл MenuBuilder.php, чтобы запрашивать под-подэлементы только при определенных условиях.

Окончательный код выглядит так:

// Menu/MenuBuilder.php

namespace My\AppBundle\Menu;

use Knp\Menu\FactoryInterface;
use Symfony\Component\HttpFoundation\Request;

class MenuBuilder
{
    private $factory;

    /**
     * @param FactoryInterface $factory
     */
    public function __construct(FactoryInterface $factory)
    {
        $this->factory = $factory;
    }

    public function createMainMenu(Request $request)
    {
        $menu = $this->factory->createItem(
            'root', array(
                'navbar' => true,
                'pull-right' => true,
            )
        );

    // Main Menu -> Config
    // no link here, it's just a placeholder
    $dropdown = $menu->addChild(
        'Config', array(
            'dropdown' => true,
            'caret' => true,
        )
    );

    // Menu -> Config -> User
    $dropdown2 = $dropdown ->addChild(
        'User', array(
            'route' => 'user',
        )
    );

    // Secondary Menu -> Edit (but child of Menu -> Config -> User)
    // Skip this part if we are not in the relevant page, thus to avoid errors
    if (false !== strpos($request->get('_route'), 'user_') && $request->get('id')):
    $dropdown2->addChild(
        'Edit',
        array(
            'route' => 'user_edit',
            'routeParameters' => array('id' => $request->get('id')),
        )
    );
    endif;

И файл конфигурации служб:

// Resources/config/services.yml

services:
    my_app.menu_builder:
        class: My\AppBundle\Menu\MenuBuilder
        arguments: ["@knp_menu.factory"]

    my_app.menu.main:
        class: Knp\Menu\MenuItem
        factory_service: my_app.menu_builder
        factory_method: createMainMenu
        arguments: ["@request"]
        scope: request
        tags:
            - { name: knp_menu.menu, alias: main }

И затем шаблон Resources/views/base.html.twig:

// Main menu
{% set menu = knp_menu_get('main', ['Config', 'Users'], {'id': id }) %}
{{ knp_menu_render(menu) }}

// Secondary menu
{% if app.request.attributes.get('_route') starts with 'user_' %}
    {% set menu = knp_menu_get('main', ['Config', 'Users'], {'id': id }) %}
    {{ mopa_bootstrap_menu(menu, {'automenu': 'navbar'}) }}
{% endif %}

Решение, кажется, работает, но если у вас есть лучший подход, пожалуйста, дайте мне знать!

person cellulosa    schedule 01.07.2014