简介
本文件面向 DouPHP 的“模块配置系统”,聚焦于 config/module.php 的配置结构与运行机制,说明模块启用/禁用、模块间关联与展示控制、以及动态加载与卸载流程。同时给出内置模块(电商、CMS、用户等)在系统中的角色划分,并提供最佳实践、常见问题诊断方法。
项目结构
DouPHP 将“模块能力”与“模块账本”分离:
- 框架层固定清单:定义前台路由、小程序页面、保留段等系统级常量,不随安装/卸载变化。
- 用户可调模块账本:通过配置文件声明当前站点启用的模块集合及展示规则。
- 运行时模块解析:根据 features 开关与类是否存在,按需解析 Service 实例,避免未安装模块导致启动失败。
- 后台模块管理:提供在线/本地安装与卸载入口,并维护已安装模块记录。
graph TB
A["config/module.php<br/>模块账本"] --> B["config/system.php<br/>系统常量"]
B --> C["core/foundation/Extension/Module.php<br/>运行时模块解析"]
A --> C
D["admin/controller/module/ModuleController.php<br/>模块管理入口"] --> E["admin/service/module/ModuleService.php<br/>安装/卸载服务"]
E --> F["存储: storage/installed/*.installed.php<br/>site.update_date"]
C --> G["前端/小程序<br/>按 features 渲染"]
核心组件
- 模块账本配置(config/module.php)
- column_module:列表型内容模块(如商品、文章、文档等)。
- single_module:单页/功能型模块(如订单、用户、会员、积分、钱包、售后、表单、投票等)。
- link_*:用于构建导航/工作台/订单项等聚合链接的模块集合。
- no_show_menu/no_show_nav:隐藏菜单或导航的模块白名单。
- 系统常量(config/system.php)
- front_fixed_module/miniprogram_builtin_module:前台与小程序内建模块。
- reserved_first_segment:保留 URL 首段,防止被模块短名占用。
- miniprogram_no_handle/nav_hidden_single/admin_hidden_single:不同端侧的隐藏策略。
- 运行时模块解析(core/foundation/Extension/Module.php)
- 基于 features.{短名} 开关与类存在性,跨 layer(core/front/admin/api)探测 Service 类。
- 支持短名与 dot 键两种键形式;提供 register() 覆盖默认映射。
- 对强依赖 user 的衍生模块进行路由级闸控。
- 后台模块管理(admin/controller/module/ModuleController.php + admin/service/module/ModuleService.php)
- 在线安装:从云端拉取扩展列表。
- 本地安装:扫描 storage/work/install/*.zip。
- 卸载:二次确认、校验数据表为空、删除 installed 标记、更新云端状态。
架构总览
下图展示了“配置—解析—运行—管理”的闭环:
sequenceDiagram
participant Admin as "后台控制器"
participant Svc as "模块服务"
participant Conf as "配置/存储"
participant Runtime as "运行时解析"
participant FE as "前端/小程序"
Admin->>Svc : 安装/卸载模块
Svc->>Conf : 写入/读取 site.update_date 与 installed 标记
Conf-->>Svc : 返回已安装模块集合
FE->>Runtime : 请求页面/接口
Runtime->>Runtime : 检查 features.{module} 与类存在
Runtime-->>FE : 返回可用能力/数据
详细组件分析
模块账本:config/module.php
- 作用
- 集中声明当前站点启用的模块集合与展示规则,是“用户可调”的模块账本。
- 通过 column_module/single_module 区分内容型与功能型模块,便于前端渲染与权限控制。
- 通过 link_* 组合多个模块到统一入口(用户中心、工作台、订单项等)。
- 通过 no_show_menu/no_show_nav 控制后台菜单与前台导航可见性。
- 关键要点
- 仅列出“启用”的模块;注释掉即视为未启用。
- 与 system.php 的系统常量互补:system.php 管“框架固定能力”,module.php 管“站点启用能力”。
系统常量:config/system.php
- 作用
- 定义前台与小程序的内建模块、URL 保留段、以及各端隐藏策略。
- 这些常量不参与安装/卸载变更,保证路由与小程序页面的稳定性。
- 关键要点
- 小程序 app.json 生成时,会参考 miniprogram_builtin_module 与 miniprogram_no_handle。
- 前台路由判定会使用 front_fixed_module 与 reserved_first_segment。
运行时模块解析:core/foundation/Extension/Module.php
- 作用
- 以 features.{短名} 为开关,结合类是否存在,决定是否注入对应 Service。
- 支持短名与 dot 键两种键形式,自动跨 layer 探测实现类。
- 对强依赖 user 的模块(如 order/vip/point/money/withdraw/share/favorites)进行路由级保护。
- 关键行为
- has()/make():先查 features,再判 class_exists,最后缓存实例。
- assertUserAvailable():命中 user 衍生模块且 features.user 关闭时抛出异常,避免容器构造失败。
- register():允许覆盖默认映射,满足非标准命名或 Infra 层类的场景。
flowchart TD
Start(["调用 Module::make(key)"]) --> CheckFeatures["检查 features.{key}"]
CheckFeatures --> |关闭| ReturnNull["返回 null"]
CheckFeatures --> |开启| FindClass["跨 layer 探测实现类"]
FindClass --> Found{"找到类?"}
Found --> |否| ReturnNull
Found --> |是| MakeInstance["容器创建实例并缓存"]
MakeInstance --> End(["返回实例"])
后台模块管理:ModuleController + ModuleService
- 在线安装
- 通过云端服务获取扩展列表,并在会话中维护 system_sign。
- 本地安装
- 扫描 storage/work/install/*.zip,列出待安装包。
- 卸载流程
- 二次确认:返回带超时与确认地址的消息载荷。
- 执行卸载:校验 extendId、检测数据表为空、删除 installed 标记、更新云端状态、写审计日志。
sequenceDiagram
participant U as "管理员"
participant C as "ModuleController"
participant S as "ModuleService"
participant FS as "文件系统/存储"
participant Cloud as "云端服务"
U->>C : 打开卸载页
C->>S : buildModuleUninstallData()
S-->>C : 可卸载列表
U->>C : 选择模块并确认
C->>S : performUninstall(extendId)
S->>FS : 校验 storage/installed/*.installed.php
S->>Cloud : clearModule / changeUpdateDate
S-->>C : 卸载成功
C-->>U : 跳转回卸载列表
小程序特性开关对齐
- 小程序类型定义中的可选特性键与后端 single_module/column_module 对齐,确保前后端能力一致。
- 未安装模块时,后端不下发该键,前端需处理 undefined 情况。
依赖关系分析
- 配置层
- module.php 提供“启用模块账本”,system.php 提供“系统常量”。
- 运行层
- Extension/Module.php 依据 features 与类存在性决定能力是否可用。
- 管理层面
- ModuleController/ModuleService 负责安装/卸载,影响 storage 与云端状态,从而改变 features 与可用能力。
graph LR
M["config/module.php"] --> R["Extension/Module.php"]
S["config/system.php"] --> R
MC["ModuleController"] --> MS["ModuleService"]
MS --> ST["storage/installed/*.installed.php"]
MS --> CL["云端服务"]
R --> FE["前端/小程序"]
性能考虑
- 按需解析:Extension/Module 仅在需要时探测类并缓存实例,减少不必要的反射与构造开销。
- 最小化启用:只在 module.php 中启用必要模块,降低前端渲染与路由匹配成本。
- 避免循环依赖:遵循 core → front → admin → api 的探测顺序,避免反向引用。
- 卸载前清理:卸载模块前确保无数据残留,避免后续查询产生额外开销。
故障排查指南
- 访问依赖 user 的模块报“未安装用户模块”
- 现象:路由命中 order/vip/point/money/withdraw/share/favorites 等模块时报错。
- 原因:features.user 未开启或 user 模块未安装。
- 解决:启用 user 模块,或在 module.php 中确保相关模块依赖链完整。
- 参考:assertUserAvailable 的路由级保护逻辑。
- 卸载模块失败提示“存在数据”
- 现象:performUninstall 抛出异常。
- 原因:模块数据表仍有记录。
- 解决:先清空数据或迁移后再卸载。
- 卸载后仍显示模块
- 现象:前端/后台仍出现模块入口。
- 原因:storage/installed/*.installed.php 未删除或云端状态未同步。
- 解决:确认卸载流程完成,必要时手动清理 installed 标记并刷新云端状态。
- 小程序端缺少某功能
- 现象:小程序未下发对应特性键。
- 原因:后端未安装或未启用该模块。
- 解决:在后端启用模块,并确保前后端键名对齐。
结论
DouPHP 的模块配置体系通过“配置账本 + 系统常量 + 运行时解析 + 后台管理”四层协作,实现了模块的灵活启用、安全卸载与跨端一致性。建议在生产环境严格管控 module.php 的启用范围,配合 system.php 的保留段与隐藏策略,确保稳定与性能。对于自定义模块,遵循命名规范并通过 Extension/Module 的 register 机制进行适配,可实现无缝集成。
附录
内置模块分类与典型用途
- 电商模块
- 商品/类目/品牌/属性/库存/订单/支付/物流/售后等,通常属于 single_module 或 column_module 的组合。
- CMS 模块
- 文章/文档/专题/下载/图库/案例/视频等,多为 column_module,用于内容展示。
- 用户模块
- 用户/会员/积分/钱包/提现/分享/收藏/评论/优惠券/工单/表单/投票/咨询/链接/门店/名片/邮箱/微信/合作伙伴/快递/落地页/设备/留言板/团队/标签/品牌/短信等,多属 single_module,支撑交易与互动。
自定义模块配置方法
- 命名规范
- 短名 key 对应 Service 类:Dou{Layer}\Service{Studly}{Studly}Service。
- 若不符合默认命名,可使用 dot 键或 register() 指定 FQCN。
- 启用方式
- 在 module.php 的 appropriate 列表中添加短名。
- 确保 features.{短名} 为 true(由安装流程设置)。
- 与 user 的依赖
- 若模块强依赖 user,需在路由层通过 assertUserAvailable 保护,避免未安装 user 时崩溃。
模块间通信的配置方式
- 通过 Extension/Module::make('xxx') 获取对方 Service 实例,实现解耦调用。
- 使用 dot 键精确指向子能力,避免命名冲突。
- 对跨层调用,优先使用 core 层提供的只读能力,减少耦合。