记一次权限管理(RBAC)
简易版
1 用户表 角色表 权限表

2.管理员表
CREATE TABLE `administrator` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `phone` varchar(255) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, `isactive` varchar(255) DEFAULT NULL, `created_at` datetime DEFAULT NULL, `updated_at` datetime DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
3.角色表
CREATE TABLE `roles` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL COMMENT '角色名称', `description` varchar(255) DEFAULT NULL COMMENT '角色描述', `created_at` datetime DEFAULT CURRENT_TIMESTAMP, `isactive` char(1) DEFAULT NULL, `updated_at` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) ) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
4.用户角色表(多对多)
CREATE TABLE `administrator_roles` ( `administrator_id` int(11) NOT NULL, `roles_id` int(11) NOT NULL, PRIMARY KEY (`administrator_id`,`roles_id`), UNIQUE KEY `administrator_id` (`administrator_id`,`roles_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
5.权限表(最重要)
CREATE TABLE `permissions` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100) NOT NULL COMMENT '权限名称,例如 user.create', `display_name` varchar(255) NOT NULL COMMENT '权限显示名称', `description` varchar(255) DEFAULT NULL COMMENT '权限描述', `created_at` datetime DEFAULT CURRENT_TIMESTAMP, `route` varchar(255) DEFAULT NULL, `http_method` varchar(255) DEFAULT NULL COMMENT 'GET/POST/PUT/DELETE', `pid` int(11) DEFAULT NULL, `grade` int(11) DEFAULT NULL, `is_menu` char(1) DEFAULT NULL, `sort` int(11) DEFAULT NULL COMMENT '排序', PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8 COMMENT='权限表';

6.角色权限表 (多对多)
CREATE TABLE `role_permission` ( `role_id` int(11) NOT NULL, `permission_id` int(11) NOT NULL, PRIMARY KEY (`role_id`,`permission_id`), KEY `permission_id` (`permission_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
7.权限管理的实现
用户登录的时候校验过用户之后查询权限
$roles = $Row->administratorRoles()->select(); $allPermissions = []; foreach ($roles as $role) { foreach ($role->RolesPermission()->select() as $permission) { $allPermissions[$permission->id] = $permission->toArray(); } } // 去重后的权限列表 $permissionArray = array_values($allPermissions); // 提取非空 route $routePermissions = array_column(array_filter($permissionArray, function($item) { return !empty($item['route']); }), 'route'); // 存入 Session Session::set('permissions', $routePermissions); Session::set('permission_all', $permissionArray);
$permissionArray 用于左边栏展示
//前端展示
<ul id="nav"> <?php foreach($menus as $menu): ?> <li> <a href="javascript:;"> <i class="iconfont left-nav-li" lay-tips="<?=$menu['description']?>"></i> <cite><?=$menu['description']?></cite> <i class="iconfont nav_right"></i> </a> <?php if (!empty($menu['children'])): ?> <ul class="sub-menu"> <?php foreach($menu['children'] as $sub): ?> <li> <a onclick="xadmin.add_tab('<?= $sub['description'] ?>','<?= $sub['route'] ?>')"> <i class="iconfont"></i> <cite><?= $sub['description'] ?></cite></a> </li> <?php endforeach; ?> </ul> <?php endif; ?> </li> <?php endforeach; ?> </ul>
//php 提供数据 public function index() { $permission=Session::get('permission_all',[]); if(is_array($permission)){ $menus=array_filter($permission, function($p){ return isset($p['is_menu']) && $p['is_menu'] == 'Y'; }); // 构造树形结构 $treeMenus = $this->buildMenuTree($menus); return view('index', ['menus' => $treeMenus]); }else{ return view('index'); } } /** * Left 目录 构造树 * */ public function buildMenuTree($items, $parentId= 0){ $items = array_values($items); $tree = []; foreach ($items as $item) { if ($item['pid'] == $parentId) { $children = $this->buildMenuTree($items, $item['id']); if ($children) { $item['children'] = $children; } $tree[] = $item; } } return $tree; }

$routePermissions 用于用户组权限的编辑
//前端展示 <body> <div class="layui-fluid"> <div class="layui-row"> <form action="" method="post" class="layui-form layui-form-pane"> <div class="layui-form-item"> <label class="layui-form-label" style="font-size: 16px;color: #333;font-weight: bold;">权限管理</label> </div> <div class="permission-container"> <!-- 系统管理模块 --> <?php foreach ($permissionTree as $permission): ?> <div class="permission-module"> <div class="module-header"> <div class="header-content"> <input type="checkbox" name="Permission[<?= $permission['id'] ?>]" value="<?= $permission['id'] ?>" lay-skin="primary" lay-filter="father" data-level="1" lay-ignore> <span class="header-title"><?= $permission['description'] ?? '' ?></span> <i class="layui-icon layui-icon-down"></i> </div> </div> <?php if (!empty($permission['children'])): ?> <div class="module-content"> <?php foreach ($permission['children'] as $child): ?> <div class="permission-group"> <div class="group-header"> <div class="header-content"> <input type="checkbox" lay-skin="primary" lay-filter="father" data-level="2" lay-ignore> <span class="header-title"><?= $child['description'] ?? '' ?></span> <i class="layui-icon layui-icon-down"></i> </div> </div> <div class="group-items"> <input name="Permission[<?= $child['id'] ?>]" lay-skin="primary" type="checkbox" data-level="3" title="<?= $child['display_name'] ?? '' ?>" value="<?= $child['id'] ?>" <?= in_array($child['id'], $checkedIds) ? 'checked' : '' ?> > <?php if (!empty($child['children'])): ?> <?php foreach ($child['children'] as $value): ?> <input name="Permission[<?= $value['id'] ?>]" lay-skin="primary" type="checkbox" data-level="3" title="<?= $value['display_name'] ?? '' ?>" value="<?= $value['id'] ?>" <?= in_array($value['id'], $checkedIds) ? 'checked' : '' ?> > <?php endforeach; ?> <?php endif; ?> </div> </div> <?php endforeach; ?> </div> <?php endif; ?> </div> <?php endforeach; ?> <input type="hidden" name="roleId" value="<?= $roleId ?>"> </div> <div class="layui-form-item" style="margin-top: 20px;text-align: center;"> <button class="layui-btn layui-btn-lg layui-btn-normal" style="width: 120px;" lay-submit="" lay-filter="add">保存设置 </button> </div> </form> </div> </div> <style> .permission-container { background: #fff; border-radius: 5px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); padding: 15px; } .permission-module { margin-bottom: 15px; border: 1px solid #e6e6e6; border-radius: 4px; overflow: hidden; } .module-header { background: #f8f8f8; padding: 12px 15px; border-bottom: 1px solid #e6e6e6; } .header-content { display: flex; align-items: center; cursor: pointer; } .header-content .layui-form-checkbox { margin-right: 10px; } .header-title { flex: 1; } .header-content .layui-icon { font-size: 14px; color: #999; transition: transform 0.3s; } .module-content { padding: 10px 15px; background: #fff; } .permission-group { margin-bottom: 10px; border: 1px solid #f0f0f0; border-radius: 3px; } .group-header { padding: 8px 15px; background: #fbfbfb; } .group-items { padding: 10px 15px 10px 40px; display: flex; flex-wrap: wrap; gap: 15px; } .permission-module.active .module-header .layui-icon, .permission-group.active .group-header .layui-icon { transform: rotate(180deg); } </style> <script> layui.use(['form', 'layer', 'jquery'], function () { var $ = layui.jquery; var form = layui.form; var layer = layui.layer; // 初始化折叠状态 $('.module-content').hide(); $('.group-items').hide(); // 模块折叠/展开 - 点击标题区域时触发 $('.module-header .header-content').on('click', function (e) { // 如果点击的是复选框,则不处理 if ($(e.target).is('input[type="checkbox"]') || $(e.target).closest('.layui-form-checkbox').length) { return; } var module = $(this).closest('.permission-module'); module.toggleClass('active'); module.find('.module-content').slideToggle(200); $(this).find('.layui-icon').toggleClass('layui-icon-down layui-icon-up'); }); // 分组折叠/展开 - 点击标题区域时触发 $('.group-header .header-content').on('click', function (e) { // 如果点击的是复选框,则不处理 if ($(e.target).is('input[type="checkbox"]') || $(e.target).closest('.layui-form-checkbox').length) { return; } var group = $(this).closest('.permission-group'); group.toggleClass('active'); group.find('.group-items').slideToggle(200); $(this).find('.layui-icon').toggleClass('layui-icon-down layui-icon-up'); }); $(document).ready(function () { // 遍历所有 group(data-level=2 的父容器) $('.permission-group').each(function () { updateGroupStatus($(this)); }); // 遍历所有 module(data-level=1 的父容器) $('.permission-module').each(function () { // 传一个该模块下任意一个三级的元素进去用于查找最近父级 var $anyCheckbox = $(this).find('input[data-level=3]').first(); if ($anyCheckbox.length) { updateParentModuleStatus($anyCheckbox); } }); // 可选:刷新 Layui checkbox 样式(不加 lay-ignore 的会变) form.render(); }); // 监听一级(data-level=1)checkbox $('input[data-level=1]').on('change', function () { var checked = this.checked; $(this).closest('.permission-module') .find('input[type="checkbox"]') .prop('checked', checked) .prop('indeterminate', false); form.render(); // 刷新 Layui 样式(只对没加 lay-ignore 的有效) }); // 监听二级(data-level=2)checkbox $('input[data-level=2]').on('change', function () { var checked = this.checked; var $group = $(this).closest('.permission-group'); $group.find('.group-items input[type="checkbox"]') .prop('checked', checked); // 更新一级模块状态 updateParentModuleStatus($(this)); form.render(); }); // 子级 checkbox 变动 form.on('checkbox', function (data) { if (!data.elem.hasAttribute('lay-filter')) { var $group = $(data.elem).closest('.permission-group'); var $module = $(data.elem).closest('.permission-module'); // 更新组头(level 2)状态 updateGroupStatus($group); // 更新模块头(level 1)状态 updateParentModuleStatus($(data.elem)); form.render(); } }); // 更新组头状态(全选、半选、全不选) function updateGroupStatus($group) { var $checkboxes = $group.find('.group-items input[type="checkbox"]'); var $groupHeader = $group.find('input[data-level=2]')[0]; var total = $checkboxes.length; var checked = $checkboxes.filter(':checked').length; if (checked === 0) { $groupHeader.checked = false; $groupHeader.indeterminate = false; } else if (checked === total) { $groupHeader.checked = true; $groupHeader.indeterminate = false; } else { $groupHeader.checked = false; $groupHeader.indeterminate = true; } } // 更新模块头状态(全选、半选、全不选) function updateParentModuleStatus($elem) { var $module = $elem.closest('.permission-module'); var $moduleHeader = $module.find('input[data-level=1]')[0]; var $allLevel3 = $module.find('input[data-level=3]'); var total = $allLevel3.length; var checked = $allLevel3.filter(':checked').length; if (checked === 0) { $moduleHeader.checked = false; $moduleHeader.indeterminate = false; } else if (checked === total) { $moduleHeader.checked = true; $moduleHeader.indeterminate = false; } else { $moduleHeader.checked = false; $moduleHeader.indeterminate = true; } } //监听提交 form.on('submit(add)', function (data) { //因为使用了lay-ignore layui的部分功能被禁用需要手动找补 $('input[data-level=1]').each(function () { const $this = $(this); if (this.indeterminate) { this.checked = true; } if (this.checked) { data.field[$this.attr('name')] = $this.val(); } }); $.post('/role/permissionsEdit',data.field,function (res){ if(res.code == 200){ layer.msg(res.msg, {icon: 1}); }else{ layer.msg(res.msg, {icon: 2}); } },'json') return false; }); }); </script> </body> </html>
//php提供数据 public function RolesPermission(Request $request) { $roleId = request()->get('id', null); if ($roleId) { //用户组所有用的权限 $ownedPermissionIds = Db::name('role_permission') ->where('role_id', $roleId) ->column('permission_id'); $allPermissions = permissions::order('sort')->select()->toArray(); //所有权限目录展示 $permissionTree = $this->buildPermissionTree($allPermissions); return view('roles/Permission', [ 'permissionTree' => $permissionTree, 'checkedIds' => $ownedPermissionIds, 'roleId' => $roleId, ]); } } function buildPermissionTree(array $permissions) { $map = []; $tree = []; // 初始化所有节点,添加 children 数组 foreach ($permissions as $item) { $item['children'] = []; $map[$item['id']] = $item; } // 遍历所有节点,按 pid 挂到父节点的 children 上 foreach ($map as $id => &$node) { if ($node['pid'] == 0) { // 根节点 $tree[] = &$node; } else { // 子节点,挂到父节点上 if (isset($map[$node['pid']])) { $map[$node['pid']]['children'][] = &$node; } } } return $tree; }

更新权限
public function RolePermissionEdit(Request $request) { $roleId = request()->post('roleId', null); $Permissions = request()->post('Permission', null); $PermissionId = array_values($Permissions); if ($roleId) { try { Db::transaction(function () use ($roleId, $PermissionId) { Db::name('role_permission')->where('role_id', $roleId)->delete(); $insertData = []; foreach ($PermissionId as $pid) { $insertData[] = [ 'role_id' => $roleId, 'permission_id' => $pid, ]; } if (!empty($insertData)) { Db::name('role_permission')->insertAll($insertData); } }); return json([ 'code' => 200, 'msg' => '权限修改成功' ]); } catch (\Exception $e) { return json([ 'code' => 400, 'msg' => '权限修改失败:' . $e->getMessage() ]); } } else { return json([ 'code' => 400, 'msg' => '用户组不存在' ]); } }
浙公网安备 33010602011771号