layui+ThinkPHP6权限管理后台实战:RBAC角色菜单按钮控制
简介这是一套基于 layui2.5.6 前端组件库与 ThinkPHP6.0.2 后端框架搭建的权限管理后台源码面向需要快速构建企业级管理系统的 PHP 开发者也适合初学者理解前后端协同开发流程。资源包共 1098 个文件约 6.1MB以 481 个 php 业务与框架代码、139 个 js 脚本、36 个 html 页面、30 个 css 样式为主另含图片、字体、配置与依赖锁文件完整覆盖前端界面、后端逻辑与工程配置。项目内置 RBAC 权限控制模型可实现用户角色分配与权限校验并通过 .env 管理数据库等环境配置借助 Composer 统一依赖版本目录结构清晰、便于二次开发。目前已有 2283 人学习下载读者可据此掌握权限后台的搭建思路、模块组织方式与前后端协作要点并在此基础上扩展自己的业务功能。1. 接手一个后台项目最怕权限菜单全是硬编码前阵子帮朋友看一个后台系统需求很明确角色不同左侧菜单不一样按钮级别的操作也要控住。他之前那套是用纯前端路由表写死的加一个角色就得改一次代码运维同事已经快疯了。后来我翻到这个基于 layui2.5.6 加 ThinkPHP6.0.2 的权限管理后台才算把「角色—菜单—按钮」这条链路真正跑通。它适合两类人一类是刚接触 TP6 想找个完整后台练手的另一类是手里有老 layui 项目、想低成本补上 RBAC 权限的。整套东西不花哨但胜在结构清楚改起来不玄学。2. 技术选型与目录结构为什么是 layui 配 TP62.1 前后端各管一摊的边界这个项目最舒服的一点是它没有强行上前后端分离。layui 负责页面渲染和交互TP6 负责数据、权限判定和接口输出两边通过模板变量和少量 ajax 对接。对于权限后台这种以表格、表单为主的场景这种组合反而比 Vue 接口来得快——菜单树、角色分配这些页面用 layui 的 tree 和 table 组件直接就能拼出来不用再单独维护一套前端工程。TP6 这边用的是标准的 MVC 分层但权限相关的逻辑被单独抽了出来。常见做法是在应用目录下建一个admin模块控制器只做参数接收和视图返回真正的权限校验放在中间件和自定义的 Auth 服务里。这样做的直接好处是以后要加一个「运营」角色只需要在数据库里配好规则代码一行不用动。2.2 目录结构长什么样下面是我按这个项目实际跑起来后的结构整理的和官方骨架基本一致只是多了权限相关的几个目录project/ ├── app/ │ ├── admin/ # 后台模块 │ │ ├── controller/ # 控制器Index、User、Role、Menu、Node │ │ ├── middleware/ # 权限中间件 CheckAuth │ │ └── view/ # layui 模板文件 │ ├── common/ # 公共模块 │ │ ├── model/ # User、Role、Menu、Node 模型 │ │ └── service/ # Auth 权限服务类 │ └── provider.php # 容器绑定 ├── config/ │ ├── database.php # 数据库配置 │ └── app.php # 应用配置 ├── public/ │ ├── static/ │ │ ├── layui/ # layui2.5.6 静态资源 │ │ └── admin/ # 后台自定义 css/js │ └── index.php # 入口文件 ├── route/ │ └── route.php # 路由定义 └── vendor/ # composer 依赖提示layui 的静态资源建议放在public/static/layui下模板里用__STATIC__常量引用换域名或加 CDN 时只改一处。2.3 权限数据表的设计思路RBAC 的核心就四张表用户表、角色表、菜单/节点表、用户角色关联表。这个项目在此基础上多了一张角色节点关联表用来控制「某个角色能看到哪些菜单、能点哪些按钮」。字段设计上节点表里有一个is_menu字段区分是菜单还是按钮还有一个pid做无限级分类。这样前端渲染菜单树和后端校验按钮权限用的是同一份数据。-- 节点表菜单 按钮 CREATE TABLE node ( id int unsigned NOT NULL AUTO_INCREMENT, pid int unsigned NOT NULL DEFAULT 0 COMMENT 父级ID, title varchar(50) NOT NULL COMMENT 名称, name varchar(50) NOT NULL COMMENT 控制器/方法标识, is_menu tinyint(1) NOT NULL DEFAULT 0 COMMENT 1菜单 0按钮, sort int NOT NULL DEFAULT 0, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 角色节点关联表 CREATE TABLE role_node ( role_id int unsigned NOT NULL, node_id int unsigned NOT NULL, PRIMARY KEY (role_id,node_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;参数说明name字段存的是控制器/方法这种格式比如User/index中间件校验时直接拿当前请求的控制器和方法去比对比存 URL 更稳改路由也不会失效。is_menu为 1 的节点才会出现在左侧菜单里为 0 的只用于按钮级校验。3. 核心模块拆解登录、鉴权、菜单渲染一条龙3.1 登录与 session 写入登录逻辑在app/admin/controller/Login.php里流程很直白接收账号密码查用户表验证密码写 session返回跳转地址。TP6 默认用 session 存登录态对于后台这种同域场景完全够用。public function doLogin() { $username $this-request-post(username); $password $this-request-post(password); $user UserModel::where(username, $username)-find(); if (!$user || md5($password . $user[salt]) ! $user[password]) { return json([code 0, msg 账号或密码错误]); } // 写入 session后续中间件靠这个判断 session(admin_id, $user[id]); session(admin_name, $user[username]); return json([code 1, msg 登录成功, url /admin/index]); }逻辑说明密码用了md5 salt的方式虽然现在看不算最强但在这个项目定位下够用改造成password_hash也很容易。关键是 session 里只存了用户 ID 和用户名没有把权限数据塞进去——权限每次请求实时查避免改了角色还要重新登录才生效。3.2 权限中间件 CheckAuth这是整个后台的闸门。所有后台控制器都挂上这个中间件请求进来先判断有没有登录再判断当前控制器/方法有没有在角色的节点列表里。public function handle($request, \Closure $next) { $adminId session(admin_id); if (!$adminId) { return redirect(/admin/login); } // 超级管理员直接放行 if ($adminId 1) { return $next($request); } $controller $request-controller(); $action $request-action(); $node strtolower($controller . / . $action); // 查当前用户角色对应的所有节点 $auth new AuthService(); $nodes $auth-getNodesByAdmin($adminId); if (!in_array($node, $nodes)) { return json([code 0, msg 无权限操作]); } return $next($request); }参数说明$request-controller()和$request-action()是 TP6 自带的拿到的是当前请求的控制器和方法名。getNodesByAdmin会先查用户角色再查角色关联的节点最后返回一个name字段的数组。这里有个细节节点名统一转小写比对避免大小写导致的玄学问题。3.3 菜单树的递归渲染左侧菜单不是写死的而是根据当前登录用户的权限动态生成。后端把节点查出来递归拼成树前端用 layui 的element组件渲染。public function getMenuTree($adminId) { $auth new AuthService(); $nodes $auth-getMenusByAdmin($adminId); // 只取 is_menu1 的 return $this-buildTree($nodes, 0); } private function buildTree($list, $pid) { $tree []; foreach ($list as $item) { if ($item[pid] $pid) { $children $this-buildTree($list, $item[id]); if ($children) { $item[children] $children; } $tree[] $item; } } return $tree; }逻辑说明buildTree是一个标准的无限级递归传入父级 ID找出所有子节点再对每个子节点继续递归。前端拿到这个树后用 layui 的layui.element.render(nav)就能渲染出可折叠的侧边栏。按钮级权限则是在模板里用{if in_array(User/del, $nodes)}这种方式控制显示后端中间件再兜底一次。4. 跑起来环境、配置、初始化三步走4.1 环境要求与依赖安装这个项目对环境的门槛不高PHP 7.1 以上、MySQL 5.7 以上、Composer 装好就行。TP6.0.2 本身要求 PHP 7.1.0layui2.5.6 是纯静态资源不挑环境。# 1. 进入项目目录 cd project # 2. 安装 PHP 依赖 composer install # 3. 复制环境配置文件 cp .env.example .env注意如果composer install卡住先检查 PHP 的proc_open和proc_get_status有没有被禁用TP6 的某些依赖会用到。4.2 数据库配置与导入打开.env文件改数据库连接信息。TP6 支持在.env里覆盖config/database.php的配置改这里比直接改配置文件更安全不会被 git 提交上去。[DATABASE] TYPE mysql HOSTNAME 127.0.0.1 DATABASE admin_db USERNAME root PASSWORD your_password HOSTPORT 3306 CHARSET utf8mb4 DEBUG true参数说明DEBUG true在开发阶段打开能看到详细的 SQL 和错误堆栈上线后记得改成false不然报错页面会暴露表结构。数据库建好后把项目根目录下的admin_db.sql导入里面包含了建表语句和一条默认管理员数据。4.3 入口与伪静态TP6 的入口文件在public/index.php所以 Web 服务器的根目录要指向public不是项目根目录。Nginx 下配一个伪静态把请求都转发到入口文件。location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s$1 last; } }配置完成后访问http://你的域名/admin/login用默认账号登录。如果页面样式全丢检查public/static/layui目录是否存在以及模板里的__STATIC__常量有没有被正确替换。5. 避坑与常见问题那几次翻车记录5.1 登录后一直跳回登录页现象输入正确账号密码提示登录成功但跳转后又回到登录页。原因TP6 的 session 默认是文件存储如果runtime目录没有写权限session 写不进去。解决给runtime目录 755 权限或者检查config/session.php里的存储路径是否可写。5.2 菜单渲染出来但点击没反应现象左侧菜单能显示但点击后右侧 iframe 不加载内容。原因layui 的element组件需要layui.use(element, function(){...})初始化如果 JS 报错导致初始化中断菜单就只是静态 HTML。解决打开浏览器控制台看有没有layui is not defined检查 layui 的引入路径是否正确。5.3 按钮权限前端隐藏了但接口还能调现象模板里用{if}隐藏了删除按钮但直接请求删除接口依然成功。原因只做了前端隐藏中间件没有覆盖到该控制器。解决确认所有后台控制器都挂上了CheckAuth中间件TP6 里可以在app/admin/middleware.php里全局注册也可以在每个控制器里单独protected $middleware [CheckAuth::class];。5.4 修改角色权限后不生效现象在角色管理里勾选了新菜单但用户刷新页面还是旧菜单。原因权限数据查的是 session 里的用户 ID但角色节点关联表更新后没有清缓存。解决这个项目没有用缓存所以直接刷新即可如果自己加了缓存记得在保存角色权限时删掉对应的缓存 key。5.5 数据库导入报外键错误现象导入 SQL 时提示Cannot add or update a child row。原因建表顺序不对关联表先于主表创建。解决按user→role→node→role_node的顺序导入或者临时关闭外键检查SET FOREIGN_KEY_CHECKS0;。6. 二次开发从改一个菜单到加一套新模块6.1 加一个新菜单的完整流程假设要加一个「文章管理」模块步骤是先在node表插入一条is_menu1的记录name填Article/index再插入两个按钮节点name分别填Article/add和Article/delpid指向菜单节点然后去角色管理里给对应角色勾上这几个节点最后建Article控制器和对应模板。整个过程不用改权限中间件的代码这就是 RBAC 的好处。6.2 把权限校验从中间件下沉到服务层如果项目变大中间件里查一次、模板里查一次会有重复查询。我一般会把当前用户的节点列表在中间件里查出来后塞到$request对象里控制器和模板直接取避免重复查库。// 中间件里 $request-nodes $nodes; // 控制器里 $nodes $this-request-nodes; // 模板里 {if in_array(Article/del, $request-nodes)}这样一次请求只查一次权限数据性能上会好很多。改的时候注意$request是对象别当成数组用。6.3 验证改造是否成功的三个检查点改完权限相关代码后我习惯按这三步验一遍第一用超级管理员登录看所有菜单和按钮是否正常第二用一个普通角色登录看菜单是否只显示勾选的直接访问未授权接口是否返回无权限第三改一次角色权限不重新登录刷新页面看是否立即生效。这三步走完基本不会翻车。6.4 一个容易忽略的细节节点 name 的大小写TP6 的$request-controller()返回的是驼峰格式比如UserGroup而数据库里存的可能是usergroup。如果不统一转小写权限校验就会失败。我一般在中间件里统一strtolower数据库里也存小写两边对齐。从那以后我每次加新节点都强制走一遍「插入节点 → 分配角色 → 清缓存 → 双角色验证」的流程再也没出现过权限对不上的情况。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

AI深度剪辑重塑画面:破解视频查重降权的完整实操指南

AI深度剪辑重塑画面:破解视频查重降权的完整实操指南

做内容这几年,最扎心的时刻就是:平台提示“该内容疑似搬运,已推荐量降权”。你辛苦熬夜做的视频,因为画面重复度高直接被判了低质,申诉都找不到途径。更要命的是,现在各大平台的查重系统越来越聪明&#xf…

2026/10/18 9:01:24 阅读更多 →
基于多模态识别的社区报修巡检系统:毕设从0到1实践解析

基于多模态识别的社区报修巡检系统:毕设从0到1实践解析

每年毕业设计季,总有人纠结同一个问题:选题要新,又不能新到做不出来;要有实际价值,又不能只是一个没有灵魂的管理系统。最近刚陪一个学弟完整走完“基于多模态识别的社区智能报修与设施巡检系统”这个毕设,…

2026/10/18 9:00:23 阅读更多 →
2025届最火的十大AI科研工具解析与推荐:用TaoToken统一Key打通千笔AI、aipasspaper、豆包与kimi

2025届最火的十大AI科研工具解析与推荐:用TaoToken统一Key打通千笔AI、aipasspaper、豆包与kimi

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 9:00:23 阅读更多 →

最新新闻

400G多模光纤:为何8通道50G比4通道100G更早落地

400G多模光纤:为何8通道50G比4通道100G更早落地

简介:IEEE Std 802.3cm-2020 是 IEEE 发布的以太网修订标准,聚焦多模光纤上 400Gb/s 的物理层与管理参数,面向光通信工程师、数据中心网络架构师及 400G 光模块研发人员。标准新增 Clause 150,定义了 400GBASE-SR8 与 400GBASE-SR…

2026/10/18 10:36:45 阅读更多 →
400G多模光纤标准解析:SR8与SR4.2的物理层设计差异与工程实践

400G多模光纤标准解析:SR8与SR4.2的物理层设计差异与工程实践

简介:IEEE Std 802.3cm-2020 是 IEEE 发布的以太网修订标准,聚焦多模光纤上 400Gb/s 的物理层与管理参数,面向光通信工程师、数据中心网络架构师及 400G 光模块研发人员。标准新增 Clause 150,定义了 400GBASE-SR8 与 400GBASE-SR…

2026/10/18 10:36:45 阅读更多 →
Linux Socket 编程实战:从可编译实例到多连接服务

Linux Socket 编程实战:从可编译实例到多连接服务

简介:这份资源面向Linux网络编程初学者与需要夯实Socket基础的开发者,系统梳理了Socket通信的核心原理与常用接口。内容从网络中进程如何唯一标识讲起,说明IP地址、协议与端口三元组的作用,并解释Socket作为特殊文件的设计思想&am…

2026/10/18 10:36:45 阅读更多 →
微信小程序远程在线诊疗系统:基于SSM的完整设计与实现

微信小程序远程在线诊疗系统:基于SSM的完整设计与实现

简介:面向高校毕业设计场景的微信小程序远程在线诊疗系统完整项目,后端采用Java SSM框架与MySQL数据库,前端为微信开发者工具构建的小程序,并辅以Vue相关后台管理界面。系统内设管理员、用户、医生三类角色,覆盖科室信…

2026/10/18 10:36:45 阅读更多 →
勇士传说横版卷轴游戏:C#动作游戏源码解析与毕业设计实战

勇士传说横版卷轴游戏:C#动作游戏源码解析与毕业设计实战

简介:这份资源是基于C#开发的「勇士传说」横版卷轴游戏完整源码,面向计算机相关专业做毕业设计的学生,以及希望入门Unity 2D游戏开发的学习者。项目以经典横版卷轴玩法为核心,涵盖角色动画、碰撞检测、地图设计、敌人AI与用户输入…

2026/10/18 10:36:45 阅读更多 →
零基础参与开源Python项目:从Fork到首个PR的完整实战指南

零基础参与开源Python项目:从Fork到首个PR的完整实战指南

1. 先搞清楚开源贡献这件事,远不止写代码很多刚接触开源Python项目的人,以为“做贡献”就等于“提PR改源码”。我最初也是这样想的,甚至一度觉得,自己没写出过有设计感的代码,就不配去动别人的仓库。直到后来真正参与进…

2026/10/18 10:35:45 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →