PHP递归搜索多维数组实现菜单访问权限校验方法
多维嵌套菜单递归权限校验实现
核心规则说明
- 存储结构:用户信息+多级菜单权限规则存放在多维数组
$arrayStr中,每个菜单节点固定包含menu_link(菜单链接路径)、menu_access(权限标识)字段,支持任意层级子菜单嵌套 - 操作权限映射:方法内预设权限规则,
create、update操作允许的权限标识为['F','W'],delete操作允许的权限标识为['F'],只读权限R不允许任何写操作 - 校验逻辑:传入待访问的菜单路径、操作类型、用户全量权限数组,递归定位目标菜单节点,读取节点的
menu_access值判断是否在当前操作的允许权限列表中,无权限直接返回false - 拦截示例:用户John Doe仅持有
dashboard/menu菜单的R(只读)权限时,访问https://localhost/dashboard/menu/create地址会被直接拦截,对应校验调用arrRecursiveAccessMap('dashboard/menu', 'create', $arrayStr)返回false
完整方法实现
class PermissionAuth { /** * 递归校验菜单操作权限 * @param string $targetLink 待校验的菜单链接 * @param string $operate 操作类型 支持create/update/delete * @param array $userData 用户全量权限多维数组 * @return bool 有权限返回true,无权限/菜单不存在返回false */ public function arrRecursiveAccessMap(string $targetLink, string $operate, array $userData): bool { // 预设操作-允许权限映射 $opPermissionMap = [ 'create' => ['F', 'W'], 'update' => ['F', 'W'], 'delete' => ['F'] ]; // 非法操作类型直接判定无权限 if (!isset($opPermissionMap[$operate])) { return false; } $currentAllowed = $opPermissionMap[$operate]; foreach ($userData as $node) { // 非数组节点直接跳过(用户基础属性等非菜单配置) if (!is_array($node)) { continue; } // 匹配到目标菜单节点 if (isset($node['menu_link']) && $node['menu_link'] === $targetLink) { return isset($node['menu_access']) && in_array($node['menu_access'], $currentAllowed); } // 存在子菜单则递归向下查找 if (isset($node['children']) && is_array($node['children'])) { $subResult = $this->arrRecursiveAccessMap($targetLink, $operate, $node['children']); // 子节点查到结果直接返回,终止遍历 if (!is_null($subResult)) { return $subResult; } } } // 未找到对应菜单节点,默认无权限 return false; } }
调用测试示例
// 模拟用户John Doe的权限数据 $arrayStr = [ 'user_base' => [ 'name' => 'John Doe', 'uid' => 1001 ], 'menus' => [ [ 'menu_link' => 'dashboard', 'menu_access' => 'R', 'children' => [ [ 'menu_link' => 'dashboard/menu', 'menu_access' => 'R', // 仅只读权限 'children' => [] ] ] ] ] ]; $auth = new PermissionAuth(); // 校验dashboard/menu路径的create操作权限 $checkRes = $auth->arrRecursiveAccessMap('dashboard/menu', 'create', $arrayStr); var_dump($checkRes); // 输出结果:bool(false),符合无权限拦截预期
内容的提问来源于stack exchange,提问作者Denny Septian Panggabean
相关产品推荐
相关产品推荐

