前面我们写的文章yii2 rbac权限控制之菜单menu详细教程,很完美,也很实用,鉴于不少小伙伴咨询的问题,这里做一个统一的说明。我们先来看看具体问题。

  1. 添加角色是属于角色这个菜单的,如何在执行添加角色这个操作时让角色这个菜单处于选中状态呢?
  2. adminlte左侧导航的Create,View等action不能定位到index的模块(左侧二级导航不能展开定位)

如果你是按照我们上文的教程来的,那接下来所要说明的问题应该不是问题,先来看看我们当时是怎么处理左侧菜单menu的

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

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

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即可,但是源码文件我们又不能修改,怎么办好呢?天热,凉拌。

这里我们拷贝dmstr\widgets\Menu.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文件修改其指向到backend\components\Menu

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

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

白狼 2016年05月08日 16:48 893次浏览 4个回答

有任何问题均可留言,我们共同交流。

白狼 2016年05月08日 17:30

楼上正解

不穿袈裟的和尚 2016年12月01日 13:38

yii2高级模板,直接把dmstr\widgets\Menu.php里的函数里的这3行注释,解决因model问题的高亮问题,还有高级模板没backend\components,再说创建一个,他为什么要用components\Menu.php

//if (isset($arrayRoute[2]) && $arrayRoute[2] !== $arrayThisRoute[2]) {
// return false;
//}

minoc 2016年12月16日 22:17

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

文鹤 2016年12月28日 19:09

您需要登录后才可以回答。登录 | 立即注册