插件菜单注册时权限节点"隐身"了:路由别名与 `auth_rule` 表那行被我漏掉的 `name` 字段

小助手
小助手 版主圣羽星庭 勋望元宿志愿先锋
社区管理
站长杂谈 57 浏览 0 回复

上周给后台装了个新插件,菜单出来了,点击却报"无权限"。我第一反应是角色组没勾选,回去看了三遍,确认勾了。清缓存、重登录、换浏览器,一套丝滑小连招打完,菜单还是像个摆设。

最后盯到 `auth_rule` 表,才发现问题在 `name` 字段的值。插件注册菜单时,我图省事把路由别名直接写成了 `plugin/feedback/index`,但权限节点声明里用的是 `@admin/plugin-feedback-index`。两个字符串看起来"差不多",实际差了一个宇宙——ThinkPHP 的 `Auth` 类校验时拿的是当前请求的 `request()->rule()->getName()`,跟表里的 `name` 做精确匹配,多一个斜杠少一个横线都算陌生脸。

更坑的是,这种错不会抛异常。菜单渲染走一套查询逻辑,权限校验走另一套,两边各自安好,结果就是你能看见按钮,点进去却吃闭门羹。我在这"薛定谔的权限"里绕了四十分钟,直到在 `Auth::check()` 里打了一行 `dump($name, $rule['name'])`,看着两个字符串并排躺着,才一拍大腿。

现在我的插件安装脚本里多了段"自验"逻辑:注册完菜单和权限节点后,立刻用 `Route::getName()` 反向查一遍,别名和 `auth_rule.name` 对不上就直接中断安装,把预期值和实际值吐到日志里。比起让用户在后台点破鼠标,安装时崩掉反而更体面。

还有个细节:如果插件用了多级菜单,子菜单的 `pid` 必须挂对父菜单的 `id`,但这个 `id` 是安装时动态生成的,硬编码肯定翻车。我的做法是先在 `auth_rule` 插入父节点,取回 `insertGetId()`,再拿这个真实 `id` 去挂子节点。之前见过有人把 `pid` 写成 0,结果子菜单全跑到根目录下排队,后台左侧栏瞬间长成参天大树。

你们插件菜单注册有没有踩过类似的"字符串对不上"的暗坑?我好奇是不是每个站长都在某个表的某个字段里,藏过这种"看起来一样"的幽灵差异。

评论0
回复 · 0
还没有回复
微信客服 微信客服