
本文介绍如何在嵌套菜单结构中递归查找指定 menu_link 对应的 menu_access 值,并判断其是否满足某类操作(如 create/update/delete)所需的权限集合。
本文介绍如何在嵌套菜单结构中递归查找指定 menu_link 对应的 menu_access 值,并判断其是否满足某类操作(如 create/update/delete)所需的权限集合。
在 PHP 开发中,尤其是基于角色的权限控制系统(RBAC),常需对深度嵌套的菜单数组进行精准匹配与权限校验。例如,用户请求访问 /dashboard/menu/create 时,系统需先提取路径前缀 dashboard/menu,再递归遍历 user_rules 数组,定位该菜单项的 menu_access 字段(如 "R"),最后比对它是否属于允许执行 create 操作的权限集(如 ['F','W'])。若不匹配,则拒绝访问。为高效实现该逻辑,推荐使用纯函数式、无副作用的递归方案,避免重复初始化配置、冗余条件判断及错误的路径拼接逻辑。以下是一个健壮、可复用的实现:
<?php
function userHasAccess(array $menuRules, array $dataParams, string $paramKey, string $targetLink): bool
{
// 遍历当前层级所有菜单项
foreach ($menuRules as $item) {
// 检查当前项是否匹配目标链接
if (isset($item['menu_link']) && $item['menu_link'] === $targetLink) {
// 若 menu_access 存在且属于指定权限组,则授权通过
if (isset($item['menu_access']) && in_array($item['menu_access'], $dataParams[$paramKey] ?? [], true)) {
return true;
}
}
// 递归检查子菜单(menu_child 存在且为数组)
if (isset($item['menu_child']) && is_array($item['menu_child'])) {
if (userHasAccess($item['menu_child'], $dataParams, $paramKey, $targetLink)) {
return true;
}
}
}
return false;
}
// 权限映射定义:不同操作所需的有效访问码
$dataParams = [
'create' => ['F', 'W'],
'update' => ['F', 'W'],
'delete' => ['F'],
];
// 示例调用:验证用户是否具备对 'dashboard/menu' 执行 'create' 操作的权限
$result = userHasAccess($arrayStr['user_rules'], $dataParams, 'create', 'dashboard/menu');
var_dump($result); // bool(false),因 menu_access = 'R' 不在 ['F','W'] 中
// 其他用例
var_dump(userHasAccess($arrayStr['user_rules'], $dataParams, 'update', 'dashboard/diagnosa')); // true(access='F')
var_dump(userHasAccess($arrayStr['user_rules'], $dataParams, 'delete', 'dashboard/benefit-group')); // true(access='F')
?>✅ 关键设计说明:
- 单一职责:函数只做「是否存在匹配且权限达标」的布尔判断,不返回路径或中间数据,语义清晰;
- 安全健壮:使用 isset() 和 is_array() 显式校验键与类型,避免 Notice 错误;
- 灵活扩展:$dataParams 与 $paramKey 作为参数传入,便于动态切换权限策略(如支持多租户不同规则);
- 短路优化:一旦找到匹配且权限合规的项即刻返回 true,无需遍历剩余分支。
⚠️ 注意事项:
- 实际生产中,建议将 userHasAccess() 封装为服务类方法,并配合缓存(如 APCu)避免高频递归开销;
- URL 解析应统一标准化(如去除末尾斜杠、忽略查询参数),确保 targetLink 与 menu_link 格式一致;
- 若菜单结构极深(>10 层),可考虑迭代替代递归以规避栈溢出风险,但本例典型层级下递归更直观易维护。
综上,该方案以简洁、可靠、可测试的方式解决了多维数组中“按值定位 + 权限校验”的核心需求,是构建安全路由守卫的理想基础组件。
立即学习“PHP免费学习笔记(深入)”;



















