后台菜单权限判断需后端动态生成:先查role_menu表获取当前角色ID对应菜单ID列表,再关联menu表过滤is_visible=1的菜单,最后用PHP递归组装树形结构;前端仅渲染,不参与权限逻辑。

PHP后台菜单权限怎么判断当前用户能看哪些菜单
菜单权限不是靠“隐藏HTML”实现的,核心是:后端生成菜单前,先查数据库确认当前用户角色拥有的菜单ID列表,再过滤出可显示项。前端只负责渲染,不参与权限逻辑。
常见错误是把 $_SESSION['role'] 硬编码成 'admin' 或 'editor' 后用 switch 判断,这导致菜单和权限表脱节,加个新菜单就得改PHP代码——不可维护。
- 必须有一张
menu表(含id、name、url、parent_id、sort) - 必须有一张
role_menu中间表,记录角色ID与菜单ID的多对多关系 - 登录后把用户角色ID存进
$_SESSION['role_id'],别存角色名 - 查询时用一次 JOIN 或子查询拿到该角色所有启用的菜单,再用 PHP 递归组装树形结构
怎么用PDO查出带层级的菜单并过滤权限
不要在PHP里循环查N次数据库。用一条SQL把有权限的菜单全拉出来,再用PHP分组建树。注意:菜单表要有 is_visible 字段控制是否出现在导航栏,权限表只管“能否访问”,菜单表才管“要不要显示”。
示例SQL(假设当前用户角色ID为 2):
立即学习“PHP免费学习笔记(深入)”;
SELECT m.id, m.name, m.url, m.parent_id, m.sort FROM menu m INNER JOIN role_menu rm ON m.id = rm.menu_id WHERE rm.role_id = 2 AND m.is_visible = 1 ORDER BY m.sort
查完用类似下面的PHP逻辑建树(不依赖框架):
$menus = $pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC);
$menuTree = [];
$map = [];
foreach ($menus as $item) {
$map[$item['id']] = $item + ['children' => []];
}
foreach ($menus as $item) {
if ($item['parent_id'] == 0) {
$menuTree[] = &$map[$item['id']];
} else {
$map[$item['parent_id']]['children'][] = &$map[$item['id']];
}
}
用户点击菜单URL时,后端怎么拦截无权访问的请求
菜单可见 ≠ 接口可调用。菜单权限只是导航控制,真正的操作权限必须在每个控制器/方法开头校验。不能只靠前端跳转地址做判断。
- 每个需要保护的页面(如
/admin/user/list.php)开头加载权限检查函数 - 检查逻辑复用:根据当前URL路径匹配
menu.url,再查role_menu确认该角色是否拥有此菜单ID - 如果没权限,直接
http_response_code(403)+ 显示“无权限”页面,不要重定向到首页(会掩盖问题) - 避免用
strpos($_SERVER['REQUEST_URI'], '/admin/') === 0这类模糊匹配,要精确比对完整url字段值
为什么用角色ID关联菜单比用字符串角色名更可靠
用 role_name = 'content_editor' 做条件,一旦运营改了角色名,所有权限就断了;而 role_id = 5 是主键,不会变。数据库设计上,role_menu.role_id 必须是外键,指向 role.id,否则删角色时菜单权限残留。
另一个实际坑点:管理员角色常被设为“拥有全部菜单”,但别在代码里写死 if ($roleId == 1) return true;。应该让管理员也走 role_menu 查询——这样未来想给管理员临时禁用某个菜单,只需删中间表一条记录,不用动代码。
菜单权限真正难的不是读取,而是当运营人员在后台增删菜单、调整角色权限时,如何保证 menu.id 和 role_menu.menu_id 始终一致。上线前务必用测试账号跑一遍新增菜单 → 分配给角色 → 登录验证的全流程。



















