實務專案中,RBAC 權限節點(模組/控制器/動作)隨開發迭代頻繁變動,手動維護 think_node 極易遺漏。本文提供一套自動掃描專案所有 Action 類別與 public 方法,批次寫入資料表的方案,實現節點「零手工維護」。
APP_GROUP_LIST 取得所有分組(群組)。Lib/Action/ 目錄下的 *Action.class.php 檔案。get_class_methods() 取得所有方法。_initialize、display、success 等)。專案://分組/模組/方法 結構化寫入 module 表。moduleCREATE 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;
}
}
RbacToolAction)。/RbacTool/fetch_module 執行同步。ReflectionMethod::getDocComment() 讀取方法上方註解作為節點「名稱/描述」寫入 name 欄位。php index.php RbacTool fetch_module)。原文出處:尛雷博客