5

我创建了我的菜单生成器,它可以工作。我的一条路线是

/database

但这有一个子路线:

database/view/{id}

我不想将视图路径放入菜单项,因为没有 ID 它将无法工作。

但是我希望当用户在视图中时数据库路由处于活动状态。

我怎样才能做到这一点?

4

4 回答 4

9

设法用这个小技巧解决了这个问题:

在添加所有子项之后但在返回我添加的菜单之前的 menuBuider 中

$request = $this->container->get('request');
        $routeName = $request->get('_route');
        switch ($routeName)
        {
            case 'battlemamono_database_view_by_name':
            case 'battlemamono_database_view_by_id':
                $database->setCurrent(true);
                break;
        }

这将检查路线并将所需的菜单设置为活动状态。

于 2013-02-06T14:16:14.490 回答
7

它没有记录,但现在这样做的正确方法是(例如):

        $menu->addChild('Category', [
            'route' => 'category_show',
            'routeParameters' => ['slug' => $category->getSlug()],
            'extras' => [
                'routes' => [
                    [
                        'route' => 'thread_show',
                        'parameters' => ['categorySlug' => $category->getSlug()]
                    ],
                ],
            ],
        ]);

如果不需要这些参数,可以跳过它们。

于 2016-08-04T10:22:26.760 回答
2

当 时$menu->addChild('Item name', ['route' => 'item_route']),该值['extras']['routes'][0] = 'item_route'被添加到当前孩子。

因此,您需要将['extra']['routes'] = []数组的路由添加到 child

这很简单。有三种方法可以做到这一点:

  1. 我推荐这种方式。'extras' 数组将被合并(无需复制当前'route'in 'routes'):

    $menu->addChild('Item name', [
        'route' => 'item_route', // The item link in the menu
        'extras' => [
            // Set current (active) if route matches one of the set (including route from key 'route')
            'routes' => [ 
                'item_route_inner_1',
                'item_route_inner_2',
                'item_route_outside_1',
            ],
        ],
    ]);
    
  2. ->setExtra(key, value)'extras'数组中,整个值将被键替换(当由于某种原因您不需要获取路由中指定的路由路径时,它可能很有用):

    $menu->addChild('Point name', [
        'route' => 'point_route', // route point (on click)
    ])
    // In the 'extras' array, the entire value will be replaced by the 'routes' key
    ->setExtra(
        'routes', [ // Set current (active) if route matches one of the set
            'point_route', // Can be removed, if necessary
            'point_route_inner_1',
            'point_route_inner_2',
            'point_route_outside_1',
        ]
    );
    
  3. ->setExtras(['routes'] => value)阵列将'extras'被完全替换。使用非常小心!

    $menu->addChild('Point name', [
        'route' => 'point_route', // route point (on click)
    ])
    // The 'extras' array will be completely replaced
    ->setExtras([
        'routes' => [
            'point_route', // Can be removed, if necessary
            'point_route_inner_1',
            'point_route_inner_2',
            'point_route_outside_1',
        ]
    ]);
    
于 2018-10-08T11:55:07.883 回答
1

几天来,我一直在为这个问题绞尽脑汁,我想我想出了最干净的解决方案,通过使用我的路由配置和自定义投票器来解决这个问题。由于这是关于 Symfony 路由组件的,我假设您正在使用 Symfony 框架或对 Symfony 有足够的了解以使其适合自己。

创建自定义选民

<?php
# src/AppBundle/Menu/RouteKeyVoter.php

namespace AppBundle\Menu;

use Knp\Menu\ItemInterface;
use Knp\Menu\Matcher\Voter\VoterInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * Voter based on routing configuration
 */
class RouteKeyVoter implements VoterInterface
{
    /**
     * @var Request
     */
    private $request;

    public function __construct(Request $request = null)
    {
        $this->request = $request;
    }

    public function setRequest(Request $request)
    {
        $this->request = $request;
    }

    public function matchItem(ItemInterface $item)
    {
        if (null === $this->request) {
            return null;
        }

        $routeKeys = explode('|', $this->request->attributes->get('_menu_key'));

        foreach ($routeKeys as $key) {
            if (!is_string($key) || $key == '') {
                continue;
            }

            // Compare the key(s) defined in the routing configuration to the name of the menu item
            if ($key == $item->getName()) {
                return true;
            }
        }

        return null;
    }
}

在容器中注册选民

# app/config/services.yml

services:
    # your other services...

    app.menu.route_key_voter:
        class: AppBundle\Menu\RouteKeyVoter
        scope: request
        tags:
            - { name: knp_menu.voter }

<!-- xml -->

<service id="app.menu.route_key_voter" class="AppBundle\Menu\RouteKeyVoter">
    <tag name="knp_menu.voter" request="true"/>
</service>

请注意,这些尚未经过全面测试。如果我应该改进一些事情,请发表评论。

配置菜单键

创建自定义 Voter 并将其添加到配置的 Matcher 后,您可以通过将_menu_key默认值添加到路由来配置当前菜单项。可以使用 分隔键|

/**
 * @Route("/articles/{id}/comments",
 *     defaults={
 *         "_menu_key": "article|other_menu_item"
 *     }
 * )
 */
public function commentsAction($id)
{
}

article_comments:
    path:      /articles/{id}/comments
    defaults:
        _controller: AppBundle:Default:comments
        _menu_key:   article|other_menu_item

<route id="article_comments" path="/articles/{id}/comments">
    <default key="_controller">AppBundle:Default:comments</default>
    <default key="_menu_key">article|other_menu_item</default>
</route>

上述配置将匹配以下菜单项:

$menu->addChild('article', [ // <-- matched name of the menu item
    'label' => 'Articles',
    'route' => 'article_index',
]);
于 2017-05-05T21:57:44.903 回答