1. 程式人生 > >yii2搭建完美后臺並實現rbac許可權控制案例--之左側選單子級無法高亮的問題

yii2搭建完美后臺並實現rbac許可權控制案例--之左側選單子級無法高亮的問題

  1. 新增角色是屬於角色這個選單的,如何在執行新增角色這個操作時讓角色這個選單處於選中狀態呢?
  2. adminlte左側導航的Create,View等action不能定位到index的模組(左側二級導航不能展開定位)
  3. 如果你是按照我們上文的教程來的,那接下來所要說明的問題應該不是問題,先來看看我們當時是怎麼處理左側選單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),]);