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

ThinkPHP RBAC 自動掃描所有模組動作實作方案

     編輯:PHP 綜合知識

實務專案中,RBAC 權限節點(模組/控制器/動作)隨開發迭代頻繁變動,手動維護 think_node 極易遺漏。本文提供一套自動掃描專案所有 Action 類別與 public 方法,批次寫入資料表的方案,實現節點「零手工維護」。

核心思路

  1. 讀取配置 APP_GROUP_LIST 取得所有分組(群組)。
  2. 遍歷各分組 Lib/Action/ 目錄下的 *Action.class.php 檔案。
  3. 實例化各 Action,透過 get_class_methods() 取得所有方法。
  4. 過濾掉 ThinkPHP 內建方法(_initialize、display、success 等)。
  5. 將 專案://分組/模組/方法 結構化寫入 module 表。

資料表結構 module

CREATE TABLE `module` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `name` varchar(45) DEFAULT NULL COMMENT '名稱',
    `app` varchar(45) DEFAULT NULL COMMENT '專案',
    `group` varchar(45) DEFAULT NULL COMMENT '分組',
    `module` varchar(45) DEFAULT NULL COMMENT '模組(控制器)',
    `function` varchar(45) DEFAULT NULL COMMENT '方法(動作)',
    `status` varchar(45) DEFAULT NULL COMMENT '狀態',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

完整實作程式碼

class RbacToolAction extends Action {
    // 入口:掃描並同步節點
    public function fetch_module() {
        $M = M('Module');
        $M->query("TRUNCATE TABLE module"); // 清空重建

        $app    = $this->getAppName();
        $groups = $this->getGroup();
        $data   = array();
        $n      = 0;

        foreach ($groups as $group) {
            $modules = $this->getModule($group);
            foreach ($modules as $module) {
                $module_name = $app . '://' . $group . '/' . $module;
                $functions   = $this->getFunction($module_name);
                foreach ($functions as $function) {
                    $data[$n]['app']      = $app;
                    $data[$n]['group']    = $group;
                    $data[$n]['module']   = $module;
                    $data[$n]['function'] = $function;
                    ++$n;
                }
            }
        }

        $M->addAll($data);
        $this->success('所有分組/模組/方法已成功讀取到 module 表中。');
    }

    // 取得專案名
    protected function getAppName() {
        return APP_NAME;
    }

    // 解析分組列表
    protected function getGroup() {
        return explode(',', C('APP_GROUP_LIST'));
    }

    // 掃描分組下的控制器檔案
    protected function getModule($group) {
        if (empty($group)) return null;
        $group_path = LIB_PATH . 'Action/' . $group;
        if (!is_dir($group_path)) return null;

        $files = glob($group_path . '/*.class.php');
        $modules = array();
        foreach ($files as $file) {
            if (is_dir($file)) continue;
            // 移除 Action.class.php 後綴
            $modules[] = basename($file, 'Action.class.php');
        }
        return $modules;
    }

    // 取得控制器的 public 方法(排除框架內建)
    protected function getFunction($module) {
        if (empty($module)) return null;
        $action = A($module); // ThinkPHP 實例化 Action
        $methods = get_class_methods($action);

        // 框架內建方法黑名單
        $inherents = array(
            '_initialize', '__construct', 'getActionName', 'isAjax',
            'display', 'show', 'fetch', 'buildHtml', 'assign',
            '__set', 'get', '__get', '__isset', '__call',
            'error', 'success', 'ajaxReturn', 'redirect', '__destruct'
        );

        $customer = array();
        foreach ($methods as $func) {
            if (!in_array($func, $inherents)) {
                $customer[] = $func;
            }
        }
        return $customer;
    }
}

使用方式

  1. 將上述程式碼放入任一後台控制器(如 RbacToolAction)。
  2. 在瀏覽器訪問 /RbacTool/fetch_module 執行同步。
  3. 每次新增/修改控制器或方法後,重新執行即可同步更新。

進階優化建議

  • 加入註解解析:結合 ReflectionMethod::getDocComment() 讀取方法上方註解作為節點「名稱/描述」寫入 name 欄位。
  • 增量同步:對比資料庫現有記錄,僅新增/刪除差異,保留手工調整的狀態。
  • 權限保護:此功能極敏感,務必限制僅超級管理員可執行。
  • 命令列模式:改寫為 CLI 指令,納入部署流程自動化(php index.php RbacTool fetch_module)。

原文出處:尛雷博客

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