Php Symfony2 KnpMenuBundle:即使菜单项不在该菜单上,也将其设置为活动菜单项

Php Symfony2 KnpMenuBundle:即使菜单项不在该菜单上,也将其设置为活动菜单项,php,symfony,symfony-2.1,knpmenubundle,Php,Symfony,Symfony 2.1,Knpmenubundle,我创建了我的菜单生成器,它可以正常工作。 我的路线之一是 /database 但这有一条儿童路线: database/view/{id} 我不想将视图路由放入菜单项中,因为没有ID它将无法工作 但我希望当用户在视图上时,数据库路由处于活动状态 我该怎么做 用这个小技巧解决了这个问题: 在添加所有子菜单之后,返回我添加的菜单之前,在菜单编辑器中 $request = $this->container->get('request'); $routeName = $re

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

/database
但这有一条儿童路线:

database/view/{id}
我不想将视图路由放入菜单项中,因为没有ID它将无法工作

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


我该怎么做

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

在添加所有子菜单之后,返回我添加的菜单之前,在菜单编辑器中

$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;
        }

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

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


如果您不需要,可以跳过参数。

我已经绞尽脑汁研究这个问题好几天了,我想我找到了最干净的解决方案,通过使用路由配置和自定义投票者来解决这个问题。因为这是关于Symfony路由组件的,所以我假设您使用的是Symfony框架,或者您对Symfony有足够的了解,可以让它为您自己工作

创建自定义投票者



AppBundle:默认值:注释
第|条其他_菜单_项目
上述配置将与以下菜单项匹配:

$menu->addChild('article', [ // <-- matched name of the menu item
    'label' => 'Articles',
    'route' => 'article_index',
]);
$menu->addChild('article',[//'Articles',
“路线”=>“文章索引”,
]);
$menu->addChild('Item name',['route'=>'Item\u route'])
时,将值
['extras']['routes'][0]='Item\u route'
添加到当前子级

因此,您需要将路由添加到
['extra']['routes']=[]
数组中,以将其添加到子级

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

  • 我建议这样做。将合并“附加”数组(无需在
    “路由”
    中复制当前的
    “路由”
    ):

  • ->setExtra(key,value)
    'extras'
    数组中,整个值将替换为key(出于某种原因,您不需要访问route中指定的routes路径时,它可能很有用):

  • ->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',
        ]
    ]);
    

  • 谢谢你发布这个!感谢您发布这篇文章,它很有魅力,但我发现它非常冗长,如果您必须在一个链接下定义多个路由,例如删除、添加、编辑、信息URL,是否可以在yml文件中定义它们?@m453h,我不知道,但我认为您不应该太担心冗长。并非所有内容都属于yml文件。:)MenuBuilder类中的
    $category
    变量是什么?@Trix,您希望它是什么,这只是一个示例,在我的例子中,我有一个带有slug的category实体。
    # 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>
    
    /**
     * @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',
    ]);
    
    $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',
            ],
        ],
    ]);
    
    $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',
        ]
    );
    
    $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',
        ]
    ]);