简介
本文面向 DouPHP 后台管理系统的架构与实现,聚焦以下目标:
- 解释后台 MVC 架构设计,尤其是控制器基类 BaseController 的设计模式与初始化流程 Init.php 的工作机制。
- 深入解析路由解析器 AdminResolver 的实现原理与中间件链执行顺序(认证、权限、安全等)。
- 梳理从入口 index.php 到最终响应返回的完整请求处理链路。
- 提供扩展后台功能的具体实践:新增控制器、服务层与视图模板的步骤。
- 给出性能优化建议与最佳实践指导。
项目结构
后台模块采用分层清晰的 MVC + 中间件管道架构:
- 入口与调度:admin/index.php 负责引导、异常处理与响应发送;admin/foundation/routing/* 负责路由解析与分发。
- 初始化:admin/init/Init.php 完成会话、配置、视图引擎、模块装配、语言包、主题与工作区变量注入。
- 控制器:admin/controller/* 下的业务控制器统一继承 BaseController,封装视图渲染、AI 工具栏注入、删除/开关响应等通用逻辑。
- 服务层:admin/service/* 承载领域逻辑,控制器通过依赖注入或门面调用。
- 模型:admin/model/* 对应数据访问。
- 路由声明:admin/route/*.php 以声明式方式定义 URL 到控制器方法的映射。
- 中间件:admin/middleware/* 实现安全、认证、权限、CSRF、工作台变量注入等横切关注点。
- 视图:admin/view/* 为 .htm 模板,配合 DouView 引擎渲染。
- 新增 模块化导航配置:admin/nav/*.php 为各功能模块提供独立的菜单定义文件。
graph TB
A["admin/index.php<br/>入口与异常处理"] --> B["Admin\\Init\\Init::boot()<br/>初始化核心对象/视图/模块"]
B --> C["Route::dispatch()<br/>调度"]
C --> D["Admin\\Foundation\\Routing\\Router::dispatch()"]
D --> E["Admin\\Foundation\\Routing\\AdminResolver::resolve()"]
E --> F["中间件栈<br/>security_headers → trust_proxy → auth → permission → csrf → workspace"]
F --> G["Dispatcher 执行控制器方法"]
G --> H["BaseController::view()<br/>合并布局变量/AI工具栏"]
H --> I["DouView 渲染模板"]
I --> J["Response->send()"]
K["模块化导航配置<br/>admin/nav/*.php"] --> L["AdminMenuRegistry<br/>扫描并装配"]
L --> M["AdminNavResolver<br/>计算导航状态"]
M --> N["模板渲染<br/>sidebar.tpl"]
核心组件
- 入口与异常处理:admin/index.php 设置路由委托、写入 route 参数、启动 Init、调度路由、捕获并统一输出错误。
- 初始化:Init.php 按序启动会话、错误报告、时区、常量、核心对象、视图引擎、模块加载、语言包、授权检测、工作区变量注入。
- 路由解析:AdminResolver.php 基于 BackendDeclaredMatcher 匹配 admin/route/*.php 中的 declared 条目,产出 DispatchPlan,组装中间件栈。
- 路由调度:Router.php 将 DispatchPlan 交给 Dispatcher 执行,未命中或方法不允许时重定向至首页并携带提示。
- 控制器基类:BaseController.php 提供 view()、layoutVars()、AI 工具栏注入、删除结果响应、布尔切换响应等通用能力。
- 菜单注册表:AdminMenuRegistry.php 提供声明式的菜单定义,支持核心族和模块族动态装配。
- 导航解析器:AdminNavResolver.php 基于当前路由名计算激活状态,生成统一的导航数据结构。
- 中间件:AuthMiddleware、PermissionMiddleware、CsrfMiddleware、AdminWorkspaceMiddleware 分别承担认证恢复、权限校验、CSRF 校验、工作台变量注入。
- 新增 模块化导航配置:六个独立模块的导航配置文件,提供细粒度的菜单管理能力。
架构总览
后台采用"声明式路由 + 中间件管道 + 声明式菜单"的 MVC 架构:
- 入口将 ?route=... 解析为 Request 的路由字符串,交由 Router 调度。
- AdminResolver 根据声明式路由表匹配模块、动作、路径参数,生成 DispatchPlan。
- 中间件栈按默认顺序执行:安全头、代理信任、认证、权限、CSRF、工作台变量注入。
- AdminMenuRegistry 提供声明式菜单定义,AdminNavResolver 基于当前路由计算激活状态。
- 控制器方法执行后返回 Response(视图/JSON/重定向),由入口统一发送。
- 新增 模块化导航配置系统,通过 glob 扫描 admin/nav/*.php 文件自动装配各模块菜单。
sequenceDiagram
participant Client as "客户端"
participant Entry as "admin/index.php"
participant Init as "Init : : boot()"
participant Route as "Route : : dispatch()"
participant Rtr as "Router : : dispatch()"
participant Res as "AdminResolver : : resolve()"
participant MW as "中间件栈"
participant MenuReg as "AdminMenuRegistry"
participant NavRes as "AdminNavResolver"
participant Ctrl as "控制器方法"
participant View as "DouView"
Client->>Entry : HTTP 请求
Entry->>Init : boot()
Init-->>Entry : 初始化完成
Entry->>Route : dispatch()
Route->>Rtr : dispatch()
Rtr->>Res : resolve(request, container)
Res-->>Rtr : DispatchPlan(含中间件)
Rtr->>MW : 依次执行中间件
MW-->>Ctrl : 放行后执行业务方法
Ctrl->>MenuReg : 获取菜单定义
MenuReg-->>Ctrl : 菜单族数据
Ctrl->>NavRes : 计算导航状态
NavRes-->>Ctrl : $nav 数据结构
Ctrl->>View : 渲染模板/返回响应
View-->>Ctrl : Response
Ctrl-->>Rtr : Response
Rtr-->>Entry : Response
Entry->>Client : send()
详细组件分析
入口与异常处理(admin/index.php)
- 设置路由委托为 Admin\Router,并将 $_GET['route'] 写入 Request 后清理超全局,避免污染。
- 启动 Init 进行系统初始化,随后调用 Route::dispatch() 执行路由。
- 捕获 HttpResponseException、RedirectException、DomainException 以及通用 Exception/Throwable,统一输出 JSON 或后台提示页。
初始化流程(admin/init/Init.php)
- 启动会话、错误报告、时区、后台常量(IS_ADMIN、ADMIN_DIR 等)。
- 启动核心对象、注册守卫、ProviderRegistry、语言契约、插件服务、消息响应器等。
- 计算 ROOT_URL/SITE_URL/HOME_URL/ADMIN_URL/API_URL/PLUGIN_URL,并设置 Request base URL。
- 设置视图引擎 DouView,配置模板目录、编译目录、转义、预处理器,并注入站点信息、主题、语言、CSRF token、工作区变量等。
- 加载模块与语言包,同步 features、module、system、param 等配置。
- 授权检测:读取 cdkey 并设置 app.licensed、pure_mode、partner_authorize 等。
- 注册 WorkspaceBuilder、UpdateBadgeBuilder、ThemeSettingsReader 等服务,供后续中间件与模板使用。
更新 增强了未命中路由的安全处理,在 loadModules 阶段添加了 nav 变量的兜底初始化,确保即使路由未正确派发也能提供安全的默认导航状态。
路由解析器(AdminResolver.php)
- 默认中间件别名栈:security_headers、trust_proxy、auth、permission、csrf、workspace。
- 通过 BackendDeclaredMatcher 匹配 admin/route/*.php 中声明的条目,支持 HTTP 方法与优先级排序。
- 若未命中返回 notFound,方法不允许返回 methodNotAllowed。
- 组装 Request 路由信息(base URL、模块、动作、子路径、参数),并注入 cur 与表单提交目标(create/edit)。
- 构建 MiddlewareRegistry 并组合最终中间件实例链,返回 DispatchPlan。
更新 引入了新的 $nav 变量结构,通过 AdminNavResolver::resolve() 方法解析路由名为统一的导航数据结构,替代了传统的单个变量处理方式。
模块化导航配置系统
AI 模块导航配置
AI 模块提供了完整的 AI 功能菜单结构,包括 AI 生成、模型管理、日志查看和任务管理等子菜单项。
return array(
'title' => 'ai',
'icon' => 'bi-robot',
'items' => array(
array(
'key' => 'ai', 'name' => 'ai', 'link' => 'admin.ai',
'match' => array('admin.ai.*', 'admin.ai_generate.*'),
),
array(
'key' => 'model', 'name' => 'ai_model', 'link' => 'admin.ai.model',
'match' => array('admin.ai.model.*', 'admin.ai.key.*'),
),
array(
'key' => 'log', 'name' => 'ai_log', 'link' => 'admin.ai.log',
'match' => array('admin.ai.log.*'),
),
array(
'key' => 'task', 'name' => 'ai_task', 'link' => 'admin.ai.task',
'match' => array('admin.ai.task.*'),
),
),
);
Book 模块导航配置
Book 模块专注于预约管理系统,包含作品管理、日程安排、规则配置、分类管理和黑名单等功能。
return array(
'title' => 'book',
'icon' => 'bi-book',
'items' => array(
array(
'key' => 'book', 'name' => 'book', 'link' => 'admin.book',
'match' => array('admin.book.*'), 'exclude' => array('admin.book.work.*'),
),
array('key' => 'item', 'name' => 'book_item', 'link' => 'admin.book.item', 'match' => array('admin.book.item.*')),
array('key' => 'schedule', 'name' => 'book_schedule', 'link' => 'admin.book.schedule', 'match' => array('admin.book.schedule.*')),
array(
'key' => 'rule', 'name' => 'book_rule', 'link' => 'admin.book.rule',
'match' => array('admin.book.rule.*', 'admin.book.rule_slot.*'),
),
array('key' => 'class', 'name' => 'book_class', 'link' => 'admin.book.class', 'match' => array('admin.book.class.*')),
array('key' => 'contact', 'name' => 'book_contact', 'link' => 'admin.book.contact', 'match' => array('admin.book.contact.*')),
array('key' => 'blacklist', 'name' => 'book_blacklist', 'link' => 'admin.book.blacklist', 'match' => array('admin.book.blacklist.*')),
array(
'key' => 'set', 'name' => 'book_set', 'link' => 'admin.book.set',
'match' => array('admin.book.set'),
),
),
);
Chat 模块导航配置
Chat 模块提供智能聊天功能,包含会话管理、知识库、套餐订阅、配额管理和使用统计等高级功能。
return array(
'title' => 'chat',
'icon' => 'bi-chat',
'items' => array(
array('key' => 'chat', 'name' => 'chat', 'link' => 'admin.chat', 'match' => array('admin.chat.*')),
array('key' => 'session', 'name' => 'chat_session', 'link' => 'admin.chat.session', 'match' => array('admin.chat.session.*')),
array(
'key' => 'knowledge', 'name' => 'chat_knowledge', 'link' => 'admin.chat.knowledge',
'match' => array('admin.chat.knowledge.*', 'admin.chat_knowledge.category.*'),
),
array('key' => 'package', 'name' => 'chat_package', 'link' => 'admin.chat.package', 'match' => array('admin.chat.package.*')),
array('key' => 'subscription', 'name' => 'chat_subscription', 'link' => 'admin.chat.subscription', 'match' => array('admin.chat.subscription.*')),
array('key' => 'quota', 'name' => 'chat_quota', 'link' => 'admin.chat.quota', 'match' => array('admin.chat.quota.*')),
array('key' => 'usage_log', 'name' => 'chat_usage_log', 'link' => 'admin.chat.usage_log', 'match' => array('admin.chat.usage_log.*')),
array('key' => 'daily_stats', 'name' => 'chat_daily_stats', 'link' => 'admin.chat.daily_stats', 'match' => array('admin.chat.daily_stats.*')),
array('key' => 'task', 'name' => 'chat_task', 'link' => 'admin.chat.task', 'match' => array('admin.chat.task.*')),
),
);
Distribution 模块导航配置
Distribution 模块专注于分销系统,包含分销申请、奖励管理、等级系统和等级日志等功能。
return array(
'title' => 'distribution',
'icon' => 'bi-diagram-3',
'items' => array(
array('key' => 'people', 'name' => 'distribution_apply', 'link' => 'admin.distribution', 'match' => array('admin.distribution.*')),
array('key' => 'reward', 'name' => 'distribution_reward', 'link' => 'admin.distribution.reward', 'match' => array('admin.distribution.reward.*')),
array('key' => 'level', 'name' => 'distribution_level', 'link' => 'admin.distribution.level', 'match' => array('admin.distribution.level.*')),
array('key' => 'level_log', 'name' => 'distribution_level_log_manager', 'link' => 'admin.distribution.level_log', 'match' => array('admin.distribution.level_log.*')),
),
);
User 模块导航配置
User 模块提供用户管理功能,包含会员管理、联系方式、操作日志和等级日志等核心功能。
return array(
'title' => 'user',
'icon' => 'bi-people',
'items' => array(
array(
'key' => 'user', 'name' => 'user', 'link' => 'admin.user',
'match' => array('admin.user.*'),
),
array('key' => 'user_center_placeholder', 'source' => 'user_center'),
array(
'key' => 'contact', 'name' => 'user_contact_manager', 'link' => 'admin.user.contact',
'match' => array('admin.user.contact.*'),
),
array(
'key' => 'log', 'name' => 'user_log_manager', 'link' => 'admin.user.log',
'match' => array('admin.user.log.*'),
),
array(
'key' => 'level_log', 'name' => 'user_level_log_manager', 'link' => 'admin.user.level_log',
'match' => array('admin.user.level_log.*'),
),
),
);
Weixin 模块导航配置
Weixin 模块集成微信功能,包含菜单管理、媒体管理和系统配置等微信相关功能。
return array(
'title' => 'weixin',
'icon' => 'bi-weixin',
'items' => array(
array('key' => 'menu', 'name' => 'weixin_menu', 'link' => 'admin.weixin.menu', 'match' => array('admin.weixin.menu.*')),
array(
'key' => 'media', 'name' => 'weixin_media', 'link' => 'admin.weixin.media',
'match' => array('admin.weixin.media.*', 'admin.weixin_media.*'),
),
array('key' => 'system', 'name' => 'weixin_system', 'link' => 'admin.weixin.system', 'match' => array('admin.weixin.system.*')),
),
);
新增 这是新引入的模块化导航配置系统,为六个核心功能模块提供了独立的菜单定义,支持更清晰的职责分离和更好的可维护性。
菜单注册表(AdminMenuRegistry.php)
- 提供声明式的菜单定义,包含核心族(manager、miniprogram、site_home)和模块族。
- 支持条件判断(when)、路由匹配(match/exclude)、可见性控制等功能。
- 模块族通过 glob 扫描 admin/nav/*.php 文件动态装配,随模块安装/卸载生命周期管理。
- 提供侧栏节点定义(sideNodes)和会员中心入口映射(userCenterFamilies)。
更新 增强了模块化导航配置的扫描和装配机制,现在支持六个核心模块的独立导航配置文件。
导航解析器(AdminNavResolver.php)
- 基于当前路由名计算激活状态,生成统一的导航数据结构。
- 支持段边界通配匹配(如 admin.user.*)、精确匹配、排除规则等。
- 计算子菜单激活项、侧栏节点激活状态、页面级覆盖等。
- 提供 emptyNav() 方法处理未派发场景的默认导航状态。
更新 增强了对模块化导航配置的支持,能够正确处理新增的六个模块的导航状态计算。
数据控制器(DataController.php)
- 继承 BaseController,提供数据管理的完整 CRUD 功能。
- 实现了数据驱动的导航状态计算,通过 navVars() 方法根据记录所属数据组动态确定导航状态。
- 支持 banner、miniprogram 等特殊数据组的导航分组逻辑。
更新 重构了渲染逻辑以支持新的 $nav 变量结构,通过页面级覆盖机制处理复杂的导航场景。
路由调度(Router.php)
- 获取 Request,调用 AdminResolver::resolve 得到 DispatchPlan。
- 未命中或方法不允许时,重定向到后台首页并携带 page_wrong 提示。
- 成功则交由 Dispatcher 运行中间件与控制器,返回 Response。
控制器基类(BaseController.php)
- view():创建 ViewResponse,自动合并 layoutVars() 与 action data,并注入 AI 工具栏与绝对化按钮链接。
- layoutVars():默认注入 flashes、page_actions、page_sub_actions、breadcrumb、cue 等公共变量。
- respondDeleteResult():统一删除结果分流,支持二次确认页面或 302 + flash。
- respondToggle():行内布尔切换,AJAX 返回 JSON,普通请求 302 + flash。
- buildLinkUserCenter():会员中心子导航 ViewModel 构建。
更新 新增了导航兜底变量机制,通过 navFallbackVars() 方法确保向后兼容,同时支持新的 $nav 结构。
中间件机制
- AuthMiddleware:从 Session 恢复管理员登录态,未登录抛异常跳转登录页。
- PermissionMiddleware:校验当前管理员对模块/动作的访问权限,越权重定向至后台首页。
- CsrfMiddleware:校验 CSRF 令牌,支持特定路由豁免与 GET 续跑场景;失败抛出 DomainException 走 message()->respond()。
- AdminWorkspaceMiddleware:在认证与权限通过后注入 global_admin、workspace、unum 等视图变量。
flowchart TD
Start(["进入中间件栈"]) --> SH["SecurityHeadersMiddleware"]
SH --> TP["TrustProxyMiddleware"]
TP --> AUTH["AuthMiddleware<br/>恢复登录态"]
AUTH --> |未登录| REDIR1["重定向到登录页"]
AUTH --> PERM["PermissionMiddleware<br/>校验模块/动作权限"]
PERM --> |无权限| REDIR2["重定向到后台首页"]
PERM --> CSRF["CsrfMiddleware<br/>校验CSRF令牌"]
CSRF --> |失败| MSG["message()->respond()<br/>提示页"]
CSRF --> WS["AdminWorkspaceMiddleware<br/>注入全局变量"]
WS --> End(["放行到控制器"])
示例:后台首页 IndexController
- 继承 BaseController,重写 layoutVars() 注入 cur='index'。
- index() 方法调用 IndexService 维护缓存、同步 root_url、刷新更新角标,并渲染 index.htm。
- clearCache()/closeQuickStart()/deleteInstall() 演示了 service 调用、审计日志、消息响应与重定向。
依赖关系分析
- 入口依赖 Init、Route、异常处理函数与 Response。
- Init 依赖容器、ProviderRegistry、DouView、语言服务、工作区构建器、主题设置读取器等。
- AdminResolver 依赖 BackendDeclaredMatcher、MethodResolver、MiddlewareRegistry、Request、Container。
- 中间件之间通过顺序组合形成管道,彼此职责单一且可插拔。
- 控制器依赖服务层与门面,视图通过 TemplateRendererInterface 解耦。
- 导航系统依赖 AdminMenuRegistry 提供菜单定义,AdminNavResolver 计算激活状态。
- 新增 模块化导航配置依赖文件系统扫描机制,自动发现并加载各模块的导航配置文件。
graph LR
Entry["admin/index.php"] --> Init["Init::boot()"]
Init --> Container["Container/ProviderRegistry"]
Init --> View["DouView/TemplateRendererInterface"]
Entry --> Router["Router::dispatch()"]
Router --> Resolver["AdminResolver::resolve()"]
Resolver --> MWReg["MiddlewareRegistry"]
MWReg --> MW1["AuthMiddleware"]
MWReg --> MW2["PermissionMiddleware"]
MWReg --> MW3["CsrfMiddleware"]
MWReg --> MW4["AdminWorkspaceMiddleware"]
Resolver --> Dispatcher["Dispatcher"]
Dispatcher --> Controller["BaseController子类"]
Controller --> Service["Service层"]
Controller --> MenuReg["AdminMenuRegistry"]
Controller --> NavRes["AdminNavResolver"]
Controller --> View
ModuleNav["模块化导航配置<br/>admin/nav/*.php"] --> MenuReg
性能考虑
- 视图编译缓存:Init 已配置 DouView 的 compile_dir 为 storage/cache/template/admin,确保模板编译产物复用。
- 中间件短路:认证失败、权限不足、CSRF 失败尽早返回,减少后续开销。
- 延迟求值:BaseController::layoutVars() 仅在真正渲染模板时执行,避免不必要的 Session 读取与计算。
- 配置与语言包:Init 在 loadModules 阶段集中加载并缓存 module/system/features/lang,减少重复 IO。
- 静态资源与 JS 路由:Init 注入 js_routes_script_url 与 js_lang_script_url,利用版本化 manifest 提升缓存命中率。
- 数据库与缓存:服务层应合理使用查询缓存与批量操作,避免 N+1 查询。
- 日志与调试:DOU_DEBUG 开启时注意生产环境关闭详细错误输出,避免泄露敏感信息。
- 菜单注册表缓存:AdminMenuRegistry::subMenus() 使用静态缓存避免重复扫描文件系统。
- 新增 模块化导航配置的文件系统扫描已在运行时缓存,避免每次请求都重新扫描 admin/nav/ 目录。
故障排查指南
- 未捕获异常:admin/index.php 的 admin_render_uncaught 会记录错误日志,并根据是否 JSON 请求返回 JSON 或后台提示页;若 SiteDebugExceptionRenderer 启用,可渲染详细堆栈。
- CSRF 失败:CsrfMiddleware 抛出 DomainException,入口捕获后通过 message()->respond() 输出统一提示页,包含倒计时与返回按钮。
- 认证失败:AuthMiddleware 抛出 HttpResponseException 并重定向到登录页。
- 权限不足:PermissionMiddleware 抛出 HttpResponseException 并重定向到后台首页。
- 404/405:Router 对未命中与方法不允许的情况统一重定向到首页并携带 page_wrong 提示。
更新 新增了导航状态相关的故障排查要点,包括 $nav 变量结构不正确时的检查方法和菜单匹配规则验证。
结论
DouPHP 后台采用清晰的分层与声明式路由,结合中间件管道实现安全、认证、权限与横切关注点的解耦。Init 负责系统初始化与视图变量注入,BaseController 提供统一的视图渲染与响应处理,AdminResolver 与 Router 协同完成路由匹配与调度。最新的导航系统重构通过 AdminMenuRegistry 和 AdminNavResolver 提供了更强大、灵活的菜单管理能力。整体架构具备良好的可扩展性与可维护性,便于添加新功能与优化性能。
更新 最新的改进包括增强的未命中路由安全处理、新的 $nav 变量结构、声明式菜单注册表以及数据驱动的导航状态计算,进一步提升了系统的健壮性和灵活性。特别是新增的六个模块化导航配置文件,为 AI、Book、Chat、Distribution、User、Weixin 等核心功能模块提供了独立的菜单管理能力。
附录:扩展指南
新增后台控制器
- 在 admin/controller/<module>/ 下新建控制器类,继承 BaseController。
- 在 admin/route/<module>.php 中声明路由条目,映射到控制器的方法。
- 在控制器方法中调用服务层,返回 $this->view('xxx.htm', $data) 或重定向/JSON。
参考路径
- admin/controller/BaseController.php:60-68
- admin/route/index.php:30-36
- admin/controller/index/IndexController.php:73-108
新增服务层
- 在 admin/service/<module>/ 下新建服务类,封装业务逻辑。
- 在控制器中通过构造函数注入或门面调用服务。
- 服务层可依赖容器、ORM、缓存、外部 API 等。
参考路径
- admin/controller/index/IndexController.php:45-58
- admin/init/Init.php:219-356
新增视图模板
- 在 admin/view/ 下新建 xxx.htm 模板文件。
- 控制器通过 $this->view('xxx.htm', $data) 渲染,模板可使用 {$cur}、{$setting}、{$workspace}、{$nav} 等全局变量。
- 如需自定义布局变量,可在控制器中重写 layoutVars() 或直接在 action data 中传递。
更新 模板现在使用新的 $nav 变量结构,包含 side(侧栏状态)、sub_menu(子菜单)、route_name(路由名)等键。
参考路径
- admin/controller/BaseController.php:205-245
- admin/init/Init.php:186-212
- admin/controller/index/IndexController.php:98-108
- admin/view/inc/sidebar.tpl:11-18
中间件扩展
- 在 admin/middleware/ 下新建中间件类,实现 MiddlewareInterface。
- 在 AdminResolver::$aliasMap 中注册别名,并在默认栈或路由级按需启用。
- 中间件内可执行安全头、代理信任、认证、权限、CSRF、工作区变量注入等逻辑。
参考路径
- admin/foundation/routing/AdminResolver.php:44-63
- admin/middleware/AdminWorkspaceMiddleware.php:58-83
模块化导航配置扩展
创建新的模块导航配置
要为新的功能模块添加导航配置,只需在 admin/nav/ 目录下创建一个 PHP 文件,文件名即为模块标识符。
<?php
// admin/nav/my_module.php
if (!defined('IN_DOUCO')) {
die('Hacking attempt');
}
return array(
'title' => 'my_module',
'icon' => 'bi-folder',
'items' => array(
array(
'key' => 'main',
'name' => 'my_module_main',
'link' => 'admin.my_module',
'match' => array('admin.my_module.*'),
),
array(
'key' => 'settings',
'name' => 'my_module_settings',
'link' => 'admin.my_module.settings',
'match' => array('admin.my_module.settings.*'),
),
),
);
导航配置字段说明
title: 模块标题标识符,用于语言包翻译icon: Bootstrap Icons 图标类名items: 菜单项数组,每个项包含:key: 菜单项唯一标识符name: 显示名称标识符,用于语言包翻译link: 路由名称match: 路由匹配模式数组exclude: 排除的路由模式数组renders: 指定渲染哪个子菜单族when: 条件判断数组
路由匹配规则
- 段边界通配:
admin.user.*匹配 admin.user 及其任意层下级 - 精确匹配:
admin.user.log精确匹配路由名 - 排除规则:exclude 数组用于排除特定路由
- 条件判断:when 数组支持多种条件判断
新增 这是新增的模块化导航配置扩展指南,帮助开发者为新功能模块创建独立的导航配置。
参考路径
- admin/nav/ai.php:27-48
- admin/nav/book.php:27-51
- admin/service/menu/AdminMenuRegistry.php:147-154
导航状态扩展
- 在控制器中使用 AdminNavResolver::resolve() 方法计算导航状态。
- 支持页面级覆盖(overrides)处理复杂场景。
- 使用 match/exclude 规则精确控制菜单激活状态。
新增 这是新增的导航状态扩展指南,帮助开发者正确处理复杂的导航场景。
参考路径
- admin/controller/data/DataController.php:67-102
- admin/service/menu/AdminNavResolver.php:64-136
配置与环境
- 数据库与系统常量在 config/config.php 中定义,包括 DOU_CHARSET、SYSTEM_SIGN、ADMIN_DIR、API_DIR、MINIPROGRAM_DIR、DOU_APP_KEY、DOU_DEBUG。
- 运行时可通过 Config 门面读写配置项,如 site、module、features、param 等。
参考路径
- config/config.php:15-53
- admin/init/Init.php:219-241
导航系统重构说明
重要更新 后台导航系统已完成重构,主要变更如下:
移除旧的 NavState 系统
- 不再使用基于 NavState 的导航状态管理
- 移除了控制器中的手动导航变量声明(cur、submenu、sub_cur)
- BaseController 的 layoutVars() 方法不再包含导航相关变量
引入声明式菜单注册表
- AdminMenuRegistry 提供集中式的菜单定义管理
- 支持核心族和模块族的动态装配
- 通过配置文件声明菜单结构和行为
基于路由的自动导航高亮
- AdminNavResolver 基于当前路由名计算激活状态
- 模板层统一消费 $nav 变量结构
- sidebar.tpl 模板已更新为使用新的变量结构
模块化导航配置
- 六个核心模块(AI、Book、Chat、Distribution、User、Weixin)拥有独立的导航配置文件
- 每个模块的菜单定义集中在各自的 admin/nav/*.php 文件中
- 通过 AdminMenuRegistry::subMenus() 自动扫描并装配所有模块导航配置
向后兼容性保证
- BaseController::navFallbackVars() 提供向后兼容的导航变量
- 旧模板代码仍可正常工作,无需立即修改
- 渐进式迁移到新架构
参考路径
- admin/controller/BaseController.php:74-90
- admin/foundation/routing/AdminResolver.php:98-99
- admin/view/inc/sidebar.tpl:11-18
导航系统架构详解
AdminMenuRegistry 的核心作用
AdminMenuRegistry 作为菜单注册表的核心组件,提供了声明式的菜单定义和管理:
// 模块化导航配置示例(AI 模块)
return array(
'title' => 'ai',
'icon' => 'bi-robot',
'items' => array(
array(
'key' => 'ai', 'name' => 'ai', 'link' => 'admin.ai',
'match' => array('admin.ai.*', 'admin.ai_generate.*'),
),
// 更多菜单项...
),
);
模块化导航配置扫描机制
系统通过 glob 模式扫描 admin/nav/*.php 文件,自动发现并加载所有模块的导航配置:
$navDir = rtrim(str_replace('\\', '/', ROOT_PATH), '/') . '/admin/nav/';
foreach ((array) glob($navDir . '*.php') as $file) {
$declared = include $file;
if (is_array($declared) && isset($declared['title'], $declared['items'])) {
$families[basename($file, '.php')] = $declared;
}
}
菜单匹配规则
- 段边界通配:
admin.user.*匹配 admin.user 及其任意层下级 - 精确匹配:
admin.user.log精确匹配路由名 - 排除规则:exclude 数组用于排除特定路由
- 条件判断:when 数组支持多种条件判断
DataController 的特殊处理
DataController 实现了数据驱动的导航状态计算,通过页面级覆盖机制处理复杂场景:
private function navVars(array $bundle)
{
$overrides = array();
if ($dataGroup === 'miniprogram') {
$overrides['sub_menu'] = 'miniprogram';
$overrides['sub_item'] = 'data';
} elseif ($dataGroup === 'banner') {
$overrides['sub_item'] = 'data_banner';
}
// 其他处理逻辑...
return array(
'cur' => $cur,
'nav' => AdminNavResolver::resolve($routeName, $overrides),
);
}
模板层的适配
模板层已完全适配新的 $nav 变量结构,所有导航判断都使用新的数据结构:
<!-- 侧边栏模板中的新用法 -->
<li{if $nav.side.setting.is_active} class="cur"{/if} data-id="setting">
<a href="{url link='admin.setting'}"><i class="{$workspace.menu_icon_map.setting}"></i><em>{$lang.setting}</em></a>
</li>
章节来源
- admin/service/menu/AdminMenuRegistry.php:77-159
- admin/service/menu/AdminNavResolver.php:64-136
- admin/controller/data/DataController.php:67-102
- admin/view/inc/sidebar.tpl:11-18
- admin/nav/ai.php:27-48
- admin/nav/book.php:27-51
- admin/nav/chat.php:27-44
- admin/nav/distribution.php:28-37
- admin/nav/user.php:27-51
- admin/nav/weixin.php:27-38