在php后台项目中,动态权限分配指的是把角色能看的菜单、能操作的接口放到数据库里管理,管理员可以随时自定义,不用修改程序代码。下面介绍一种清晰易懂的实现思路。

一、数据库表设计
实现动态权限,先准备三张核心表:角色表、菜单权限表、角色权限关联表。
- role:存储角色id和名称
- menu:存储菜单id、名称、链接、父级id
- role_menu:存储角色id和菜单id的对应关系
简单结构如下:
CREATE TABLE role ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL ); CREATE TABLE menu ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, url VARCHAR(100), parent_id INT DEFAULT 0 ); CREATE TABLE role_menu ( role_id INT, menu_id INT, PRIMARY KEY(role_id, menu_id) );
二、管理员自定义角色菜单权限
管理员在后台页面看到所有菜单树,勾选某个角色能用的菜单,提交后php接收数据写入role_menu表。
<?php
// 假设提交过来的角色id和菜单id数组
$roleId = intval($_POST['role_id']);
$menuIds = $_POST['menu_ids']; // 数组
// 先删除旧权限
$pdo->prepare('DELETE FROM role_menu WHERE role_id = ?')->execute([$roleId]);
// 插入新权限
$stmt = $pdo->prepare('INSERT INTO role_menu (role_id, menu_id) VALUES (?, ?)');
foreach ($menuIds as $mid) {
$stmt->execute([$roleId, intval($mid)]);
}
echo '权限已更新';
?>
三、用户登录后获取可用菜单
用户登录时把角色id存入session,之后从数据库查出该角色关联的菜单,用于展示后台左侧菜单。
<?php
session_start();
$roleId = $_SESSION['role_id'];
$sql = 'SELECT m.* FROM menu m
JOIN role_menu rm ON m.id = rm.menu_id
WHERE rm.role_id = ?';
$menus = $pdo->prepare($sql);
$menus->execute([$roleId]);
$list = $menus->fetchAll(PDO::FETCH_ASSOC);
// 输出菜单
foreach ($list as $item) {
echo '<li>' . htmlspecialchars($item['name']) . '</li>';
}
?>
四、接口访问前的权限校验
在公共控制器或中间件中,判断当前访问的url是否属于该角色的菜单权限,没有就拦截。
<?php
function checkAuth($pdo, $roleId, $currentUrl) {
$sql = 'SELECT COUNT(*) FROM menu m
JOIN role_menu rm ON m.id = rm.menu_id
WHERE rm.role_id = ? AND m.url = ?';
$stmt = $pdo->prepare($sql);
$stmt->execute([$roleId, $currentUrl]);
return $stmt->fetchColumn() > 0;
}
if (!checkAuth($pdo, $_SESSION['role_id'], $_SERVER['REQUEST_URI'])) {
http_response_code(403);
exit('无权限访问');
}
?>
五、小结
通过把角色和菜单权限放到数据库,并用php在登录和访问时做查询与校验,就能让管理员自定义角色菜单权限。以后加角色或调菜单只改数据,不必动代码,系统更灵活也好维护。