限时 5折! 详情
yii2 左侧菜单子级无法高亮的问题
8 2848 2016-05-08

前面我们写的文章yii2 rbac权限控制之菜单menu详细教程,很完美,也很实用,鉴于不少小伙伴咨询的问题,这里做一个统一的说明。我们先来看看具体问题。添加角色是属于角色这个菜单的,如何在执行添加角色这个操作时让角色这个菜单处于选中状态呢?adminlte左侧导航的Create,View等action不能定位到index的模块(左侧二级导航不能展开定位)如果你是按照我们上文的教程来的,那接下来所要说明的问题应该不是问题,先来看看我们当时是怎么处理左侧菜单menu的

use mdmadmincomponentsMenuHelper; 
<?php 
$callback = function($menu){ 
    //鉴于篇幅有限,这里的代码省略,源码见于原文
}; 
//这里我们对一开始写的菜单menu进行了优化
echo dmstrwidgetsMenu::widget( [ 
    "options" => ["class" => "sidebar-menu"], 
    "items" => MenuHelper::getAssignedMenu(Yii::$app->user->id, null, $callback), 
] ); ?>

看到这里,我们不妨打开文件 dmstrwidgetsMenu 看看这里是怎么实现左侧菜单选中这一困扰众多同学的问题。

protected function isItemActive($item)
{
    if (isset($item["url"]) && is_array($item["url"]) && isset($item["url"][0])) {
        //......
        if ($arrayRoute[0] !== $arrayThisRoute[0]) {
            return false;
        }
        if (isset($arrayRoute[1]) && $arrayRoute[1] !== $arrayThisRoute[1]) {
            return false;
        }
        if (isset($arrayRoute[2]) && $arrayRoute[2] !== $arrayThisRoute[2]) {
            return false;
        }
        //......
        return true;
    }
    return false;
}

看吧,看上面的代码,也就是说左侧菜单激活的情况是当前路由完全等于菜单路由时菜单才进行激活。鉴于我们一开始谈到的不少小伙伴疑惑的两个问题,我们这里只需要稍稍调整下代码,判断控制到controller而非action即可,但是源码文件我们又不能修改,怎么办好呢?天热,凉拌。这里我们拷贝dmstrwidgetsMenu.php 文件到 backend\components\Menu.php,然后按照下面的方法修改 isItemActive 方法即可

protected function isItemActive($item)
{
    if (isset($item["url"]) && is_array($item["url"]) && isset($item["url"][0])) {
        //......
        //改写了路由的规则,是否高亮判断到controller而非action
        $routeCount = count($arrayRoute);
        if ($routeCount == 2) {
            if ($arrayRoute[0] !== $arrayThisRoute[0]) {
                return false;
            }
        } elseif ($routeCount == 3) {
            if ($arrayRoute[0] !== $arrayThisRoute[0]) {
                return false;
            }
            if (isset($arrayRoute[1]) && $arrayRoute[1] !== $arrayThisRoute[1]) {
                return false;
            }
        } else {
            return false;
        }
        // if ($arrayRoute[0] !== $arrayThisRoute[0]) {
        //     return false;
        // }
        // if (isset($arrayRoute[1]) && $arrayRoute[1] !== $arrayThisRoute[1]) {
        //     return false;
        // }
        // if (isset($arrayRoute[2]) && $arrayRoute[2] !== $arrayThisRoute[2]) {
        //     return false;
        // }

        //......

        return true;
    }
    return false;
}

如此一来,菜单高亮的问题解决了。
但是紧接着,让我们来看看另外一个需求:多控制器的怎么激活菜单的问题。
关于多控制器的激活,什么意思呢?我来阐述两句。
比如说我们现在要访问的菜单,其路由是/test/index,如果正常激活菜单的话,当我们访问/test/的时候,其对应的左侧菜单自然会处于激活状态,这是木有问题的。但是,我们想要的一种效果是,当访问/test2/(注意哦,这里是test2另外一个控制器)的时候我们也想要激活当前菜单/test/index怎么办好呢?
我们来看看如何处理这个问题。配置test的菜单的[数据]项 (菜单列表->找到对应的菜单项->修改->[数据])这里,填写如下内容 {"multi-controller":"test2"} 或者 {"multi-controller":["test2", "test3"]},有些人可能看不懂,这里为啥要这么写。我们自己定制的规则,仅做参考。
看不懂的请先移步 yii2 rbac权限控制之菜单menu详细教程感受我们memu的强大之处。修改你的isItemActive方法,该方法位于我们上文谈到的 backend\components\Menu.php文件内,具体可参考如下

protected function isItemActive($item)
{
    if (isset($item["url"]) && is_array($item["url"]) && isset($item["url"][0])) {

        //......
        //multi-controller 多controller激活 高亮状态
        if (isset($item["options"]) && isset($item["options"]["multi-controller"]) && $item["options"]["multi-controller"]) {
            if (is_array($item["options"]["multi-controller"]) && in_array($arrayThisRoute[0], $item["options"]["multi-controller"])) {
                return true;
            } 
            if (is_string($item["options"]["multi-controller"]) && $arrayThisRoute[0] === $item["options"]["multi-controller"]) {
                return true;
            }
        }

        //改写了路由的规则,是否高亮判断到controller而非action
        $routeCount = count($arrayRoute);
        if ($routeCount == 2) {
            if ($arrayRoute[0] !== $arrayThisRoute[0]) {
                return false;
            }
        } elseif ($routeCount == 3) {
            if ($arrayRoute[0] !== $arrayThisRoute[0]) {
                return false;
            }
            if (isset($arrayRoute[1]) && $arrayRoute[1] !== $arrayThisRoute[1]) {
                return false;
            }
        } else {
            return false;
        }

        //......

        return true;
    }
    return false;
}

大功告成,现在我们左侧的菜单引用的Menu文件修改其指向到backendcomponents\Menu

use backendcomponentsMenu;
echo Menu::widget([
    "options" => ["class" => "sidebar-menu"],
    "items" => MenuHelper::getAssignedMenu(Yii::$app->user->id, null, $callback),
]); 

快去试试看我们的问题解决没有吧。

  • 8 个回答
  • 如果路由是指向mdules,高亮的就不是controller,而是modules下的全部高亮了

    最佳答案
  • 有任何问题均可留言,我们共同交流。

  • 楼上正解

  • yii2高级模板,直接把 dmstrwidgetsMenu.php里的函数里的这3行注释,解决因model问题的高亮问题,还有高级模板没backend\components,再说创建一个,他为什么要用components\Menu.php //if (isset($arrayRoute[2]) && $arrayRoute[2] !== $arrayThisRoute[2]) { // return false; //}

  • 白狼哥,为什么要做多控制器的激活啊?当访问/test2/*的时候我们也想要激活当前菜单/test/index是为了做什么呢?

  • $arrayRoute和$arrayThisRoute分别指的是啥呢?

  • 由于 yii2-adminlte-asset 更新的问题,menu子菜单高亮各位参考这一版

  • 有些文章说明的不够详细,也许是狼哥太忙。或者是觉得读者可以自己操作。导致后来观看的读者很多人都摸不着头脑。。。

登录 去赚佣金