ThinkPHP不支持按角色自动隐藏路由,必须前后端协同:前端动态拉取权限路由表并addRoutes,后端所有路由组须显式绑定鉴权中间件(如middleware('check_auth')),且中间件内需用$request->param()取参,避免依赖未解析的路由对象。

ThinkPHP 本身不提供“按角色自动隐藏未授权路由”的内置机制;所谓“隐藏”,必须由前端主动过滤 + 后端严格校验共同完成,缺一不可。后端不校验,前端藏得再深也形同虚设。
前端动态路由必须配合后端权限接口
Element Admin 类项目中,router.addRoutes() 加载的路由表不能硬编码,得从后端 /api/auth/routes(或类似路径)拉取。这个接口返回的应是当前用户角色(如 admin、editor)所允许访问的完整路由列表,含 path、name、meta.roles 等字段。
- 后端接口需根据 token 解析用户角色,查数据库或配置映射表,生成可访问路由清单
- 返回的
path必须与 ThinkPHP 实际定义的路由路径一致(如admin/user/list),否则前端跳转 404 - 不要在前端靠
v-if="hasRole('admin')"控制菜单显隐——它不阻止用户手动输入 URL 访问
后端路由组必须显式绑定鉴权中间件
ThinkPHP 的 Route::group() 不自带权限逻辑,哪怕你写成 Route::group('admin', ...),也不拦未登录用户直接请求 /admin/user/delete。真正起作用的是中间件绑定动作:
Route::group('admin', function () {
Route::get('user/list', 'Admin/User/list');
Route::delete('user/:id', 'Admin/User/delete');
})->middleware('check_auth');
-
check_auth是中间件名,不是类路径;需提前在app/middleware.php或注解中注册 - 中间件内用
$request->param()取参数(如:id),别依赖$this->route—— 路由对象在中间件里不一定已完全解析 - 若需判断当前是否在某个分组下,可用
$request->rule()->getGroup()获取分组名
避免中间件执行顺序反直觉导致漏鉴权
ThinkPHP 中间件是栈式执行:外层路由组的中间件先入、后出。比如嵌套定义:
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
立即学习“PHP免费学习笔记(深入)”;
Route::group('api', function () {
Route::group('v2', function () {
Route::post('article', 'Api/V2/Article/create');
})->middleware('throttle');
})->middleware('auth');
实际执行顺序是:auth → throttle → controller → throttle → auth。这意味着:
-
auth中间件无法感知throttle是否已限流失败(它后于throttle退出) - 若
throttle返回响应中断流程,auth的“退出后逻辑”(如日志记录)不会执行 - 权限叠加时(如 admin + vip),别指望外层中间件能“看到”内层中间件设置的属性,要用
$request->withAttribute()显式透传
最易被忽略的一点:路由缓存开启时('route_check_cache' => true),中间件绑定必须在路由定义阶段完成,运行时动态追加无效;而一旦用了闭包式路由地址,缓存自动失效,性能会掉——别为了图方便在 Route::rule() 里写闭包。


















