首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

Yii2 AdminLTE 左側選單子項高亮失效:根因分析與最佳修復方案(繼承覆寫 isItemActive)

     編輯:PHP 相關知識

同一問題的標準化解決方案:繼承 dmstr Menu 而非修改廠商代碼

本文針對 Yii2 + AdminLTE + rbac-admin 場景,系統分析 dmstr\widgets\Menu::isItemActive() 預設「全路由匹配」導致子路由不高亮、父選單不展開的問題,提供繼承覆寫的最佳實踐方案,確保升級安全。

問題現象

  • 選單項:['label'=>'角色管理', 'url'=>['role/index'], 'items'=>[['label'=>'新增', 'url'=>['role/create']]]]
  • 訪問 /role/create → 父項「角色管理」不高亮、子選單不自動展開。

根因:預設匹配邏輯過於嚴格


// vendor/dmstr/yii2-adminlte-asset/Menu.php
protected function isItemActive($item)
{
    if (isset($item['url']) && is_array($item['url']) && isset($item['url'][0])) {
        $route = (array)$item['url'][0];      // ['role/index']
        $current = (array)Yii::$app->controller->getRoute(); // ['role/create']
        // 逐段嚴格比對:模塊、控制器、動作
        if ($route[0] !== $current[0]) return false;
        if (isset($route[1]) && $route[1] !== $current[1]) return false;
        if (isset($route[2]) && $route[2] !== $current[2]) return false;
        return true;
    }
    return false;
}

因 role/create 與 role/index 動作段不同,判定為非激活。

最佳修復:繼承並覆寫 isItemActive()

  1. 建立 backend/components/Menu.php
  2. 繼承 dmstr\widgets\Menu
  3. 僅比對「模塊 + 控制器」,忽略動作
<?php
namespace backend\components;

use dmstr\widgets\Menu as BaseMenu;
use Yii;

class Menu extends BaseMenu
{
    protected function isItemActive($item)
    {
        if (!isset($item['url']) || !is_array($item['url']) || !isset($item['url'][0])) {
            return false;
        }

        $menuRoute = (array)$item['url'][0];           // 選單配置路由
        $currentRoute = (array)Yii::$app->controller->getRoute(); // 當前路由

        // 僅比對前兩段:模塊、控制器
        if ($menuRoute[0] !== $currentRoute[0]) return false; // 模塊不同
        if (isset($menuRoute[1], $currentRoute[1]) && $menuRoute[1] !== $currentRoute[1]) {
            return false; // 控制器不同
        }

        return true; // 同一控制器下所有 action 視為激活
    }
}

視圖中引入自定義 Menu

<?php
use backend\components\Menu;
use mdm\admin\components\MenuHelper;

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

進階:跨控制器的父子關係處理

若「權限分配」屬於 permission/index,但需隸屬「角色管理」分組,可在回調中動態標記:

$callback = function ($menu) {
    $route = Yii::$app->controller->getRoute();
    $permissionRoutes = ['permission/index', 'permission/assign', 'permission/revoke'];
    if (in_array($route, $permissionRoutes)) {
        foreach ($menu as &$item) {
            if (($item['url'][0] ?? '') === 'role/index') {
                $item['active'] = true; // 強制激活父項
            }
        }
    }
    return $menu;
};

echo Menu::widget([
    'items' => MenuHelper::getAssignedMenu(Yii::$app->user->id, null, $callback),
]);

驗證清單

  • ✅ /role/create、/role/update/1、/role/view/1 → 「角色管理」高亮、展開
  • ✅ /permission/index → 「權限管理」高亮(或按上述邏輯歸屬角色管理)
  • ✅ 刷新、瀏覽器前進後退、多標籤頁狀態一致
  • ✅ composer update 後無衝突(未修改 vendor 目錄)

總結

通過繼承覆寫單一受保護方法,將激活判定粒度從「動作級」放寬至「控制器級」,完美解決子路由高亮問題,代碼量極小、維護成本極低、升級零風險。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved