Symfony2 KnpMenuBundle:设置一个菜单项,即使它不在该菜单上

问题描述 投票:4回答:4

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

/database

但这有一条儿童路线:

database/view/{id}

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

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

我怎样才能做到这一点?

php symfony symfony-2.1 knpmenubundle
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;
        }

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


5
投票

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

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

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


1
投票

我已经在这个问题上绞尽脑汁待了几天,我想通过使用我的路由配置和自定义选民,我想出了解决这个问题的最干净的解决方案。由于这是关于Symfony Routing组件,我假设你正在使用Symfony框架或者有足够的Symfony知识来使它适合自己。

Create a custom Voter

<?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>

请注意,这些尚未经过全面测试。如果我要改进的话,发表评论。

Configuring the menu keys

一旦您创建了自定义选民并将其添加到配置的匹配器,您就可以通过将_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',
]);

0
投票

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

所以你需要将['extra']['routes'] = []数组的路由添加到child。

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

  1. 我推荐这种方式。 'extras'数组将合并(无需复制'route'中的当前'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', ] ]);
© www.soinside.com 2019 - 2024. All rights reserved.