简介
本指南面向需要在 DouPHP 中新增业务模块的开发者,覆盖从需求分析到代码落地的完整流程。重点包括:
- MVC 分层与职责边界(控制器、服务层、模型)
- 数据库操作(ORM 使用、查询构建、事务处理建议)
- 前后端数据交互(API 设计、数据格式、错误处理)
- 权限控制(用户认证、角色授权、访问控制)
- 缓存机制(数据缓存、页面缓存、性能优化)
- 测试与部署注意事项
- 以“文章”模块为示例,展示从零开始创建完整功能的步骤
项目结构
DouPHP 采用多入口 + 模块化组织:
- 根入口 index.php 负责引导、路由分发与异常处理
- core/bootstrap.php 完成环境初始化、配置加载、自动加载、容器与门面注册
- config/config.php 提供数据库与应用级常量
- admin、api、front 三端各自拥有 controller、service、model、request、route、middleware 等目录
- core/orm 提供轻量 ORM(Model、Builder、Collection、Relations)
- _'/module 下包含可插拔能力(如用户鉴权中间件)
graph TB
A["index.php<br/>入口与异常处理"] --> B["core/bootstrap.php<br/>引导与装配"]
B --> C["config/config.php<br/>应用配置"]
B --> D["路由分发<br/>Route::dispatch()"]
D --> E["前端 front/*<br/>视图渲染"]
D --> F["后台 admin/*<br/>管理界面"]
D --> G["API api/*<br/>JSON 接口"]
E --> H["服务层 service/*"]
F --> H
G --> H
H --> I["模型层 model/*<br/>ORM Model"]
I --> J["数据库"]
图表来源
- index.php:1-126
- core/bootstrap.php:1-180
- config/config.php:1-53
章节来源
- index.php:1-126
- core/bootstrap.php:1-180
- config/config.php:1-53
核心组件
- 入口与引导
- index.php:设置路由委托、解析语言前缀、启动 Init、执行 Route::dispatch()、统一捕获并响应异常(含 JSON/HTML 分支)。
- core/bootstrap.php:定义路径常量、加载配置、注册自动加载与门面、初始化 DI 容器、绑定 Request 与 DelegatingRouter。
- 控制器基类
- admin/controller/BaseController.php:后台 view() 注入布局变量、AI 工具栏、删除结果分流、开关切换响应等。
- api/controller/BaseController.php:API 端会员中心导航构建复用前台实现。
- ORM 模型
- core/orm/Model.php:ActiveRecord 风格基类,支持静态查询、关系、事件、全局 scope、属性转换、时间戳等。
- 权限与中间件
- API 用户认证中间件:从 Authorization 头提取 token 并交由 auth('api') 解析登录态。
- 前台鉴权模式配置:集中声明各模块/路由的认证策略(public/optional/required/work_required)。
章节来源
- index.php:1-126
- core/bootstrap.php:1-180
- admin/controller/BaseController.php:1-371
- api/controller/BaseController.php:1-62
- core/orm/Model.php:1-800
- _'/module/user/api/middleware/UserAuthMiddleware.php:1-42
- _'/module/user/front/init/middleware.php:18-55
架构总览
请求在 DouPHP 中的流转如下:
- 入口 index.php 解析 route 参数与语言前缀,调用 Front\Init\Init()->boot() 完成场景初始化
- 通过 Route::dispatch() 将请求调度到对应 Controller Action
- 控制器调用 Service 进行业务编排,Service 通过 ORM Model 或 DB 门面进行数据读写
- 返回 Response(ViewResponse/ApiResponse/Redirect),由入口统一发送
sequenceDiagram
participant U as "客户端"
participant R as "index.php"
participant Boot as "Front\\Init\\Init"
participant RT as "Route"
participant C as "Controller"
participant S as "Service"
participant M as "Model/DB"
participant Resp as "Response"
U->>R : HTTP 请求
R->>Boot : boot(route)
R->>RT : dispatch()
RT-->>C : 调用具体 Action
C->>S : 执行业务逻辑
S->>M : 读取/写入数据
M-->>S : 结果
S-->>C : 业务结果
C-->>Resp : 构造响应
Resp-->>U : 发送响应
图表来源
- index.php:26-75
- core/bootstrap.php:144-171
章节来源
- index.php:26-75
- core/bootstrap.php:144-171
详细组件分析
控制器层(Admin/Front/API)
- 后台控制器基类
- 提供 view() 合并布局变量、AI 工具栏注入、删除结果分流、布尔切换响应等通用能力
- 推荐所有后台控制器继承此基类以复用行为
- API 控制器基类
- 提供会员中心导航构建等 API 端通用能力
- 文章控制器(前台/后台)
- 前台 ArticleController:列表/详情、SEO、导航、评论插件集成、分页与归档
- 后台 ArticleController:CRUD、批量操作、表单校验(Request)、跳转与提示
classDiagram
class BaseController_Admin {
+view(template, data, status)
+respondDeleteResult(result)
+respondToggle(request, value, message, backUrl)
#layoutVars() array
}
class BaseController_Api {
+buildLinkUserCenter(currentModule) array
}
class ArticleController_Front {
+index(request) Response
+show(request) Response
}
class ArticleController_Admin {
+index(request) Response
+create() Response
+store(formRequest, request) Response
+edit(request) Response
+update(formRequest, request) Response
+destroy(request) Response
+action(request) Response
}
BaseController_Admin <|-- ArticleController_Admin
BaseController_Api <|-- ArticleController_Front
图表来源
- admin/controller/BaseController.php:45-371
- api/controller/BaseController.php:38-62
- front/controller/article/ArticleController.php:41-283
- admin/controller/article/ArticleController.php:35-221
章节来源
- admin/controller/BaseController.php:45-371
- api/controller/BaseController.php:38-62
- front/controller/article/ArticleController.php:41-283
- admin/controller/article/ArticleController.php:35-221
服务层(Service)
- 职责边界
- 组装展示数据、编排业务流程、协调模型与外部服务(如附件、审计日志)
- 不直接承担请求校验(由 Request 完成)
- 文章服务示例
- 列表数据构建(分页、过滤、字段裁剪)
- 新增/更新(内容清洗、远程图片本地化、主图上传、草稿认领、审计日志)
- 删除(二次确认分支、审计日志)
- 批量操作(批量删除、批量转移分类)
flowchart TD
Start(["进入 Service 方法"]) --> Validate["参数校验/上下文检查"]
Validate --> |合法| Process["业务处理<br/>内容清洗/图片处理/关联数据"]
Validate --> |非法| ThrowErr["抛出 DomainException"]
Process --> Persist["持久化/更新"]
Persist --> Audit["记录审计日志"]
Audit --> Return["返回结果"]
ThrowErr --> End(["结束"])
Return --> End
图表来源
- admin/service/article/ArticleService.php:63-314
章节来源
- admin/service/article/ArticleService.php:63-314
模型与 ORM(Model)
- 设计要点
- 静态入口为主:Model::where()/with()/query()/create()
- 读:query()->find()/first()/get()/with()
- 写:fill()->save() / create() / query()->whereKey($id)->update() / destroy()
- 支持关系、预加载、属性转换、事件、全局 scope、时间戳
- 使用建议
- 复杂聚合/元信息/原生 SQL 仍可使用 DB 门面
- 模板透明:实例支持数组式访问、迭代、计数、序列化
classDiagram
class Model {
+table : string
+primary : string
+fillable : array
+casts : array
+prefetchers : array
+with : array
+appends : array
+translatable : array
+newQuery() Builder
+create(attributes) static
+destroy(id) static
+__callStatic(method, params)
+getAttribute(key) mixed
+setAttribute(key, value) $this
}
class Builder {
+where(...)
+with(...)
+paginate(pageSize, page, url)
}
Model --> Builder : "newQuery()"
图表来源
- core/orm/Model.php:51-800
章节来源
- core/orm/Model.php:51-800
权限控制(认证与授权)
- API 端
- 中间件从 Authorization: Bearer <token> 提取 token,交给 auth('api') 解析登录态
- 未登录/无工作身份时直接返回 JSON 错误并终止
- 前台端
- 通过配置文件集中声明各模块/路由的认证模式(public/optional/required/work_required)
- 未命中默认 optional,但安全边界应显式登记
sequenceDiagram
participant Client as "客户端"
participant MW as "UserAuthMiddleware"
participant Auth as "auth('api')"
participant Ctrl as "API 控制器"
Client->>MW : 携带 Authorization 头
MW->>Auth : 解析 token 获取会话
Auth-->>MW : 登录态/游客
alt 已登录且具备工作身份
MW-->>Ctrl : 放行
Ctrl-->>Client : 业务响应
else 未登录/无身份
MW-->>Client : 401/403 JSON 错误
end
图表来源
- _'/module/user/api/middleware/UserAuthMiddleware.php:25-42
- _'/module/user/front/init/middleware.php:18-55
章节来源
- _'/module/user/api/middleware/UserAuthMiddleware.php:25-42
- _'/module/user/front/init/middleware.php:18-55
前后端数据交互(API 设计、数据格式、错误处理)
- 入口统一异常处理
- 业务规则异常(DomainException)在 JSON 请求下返回 422,HTML 请求走消息页
- 未捕获异常按 site.debug 输出调试页或 JSON 500
- API 控制器基类
- 复用前台会员中心导航构建,便于跨端一致的用户中心体验
- 建议
- 统一 ApiResponse 结构(成功/失败、错误码、错误信息、附加数据)
- 明确状态码与错误码约定,避免混用
章节来源
- index.php:46-75
- api/controller/BaseController.php:38-62
数据库操作(ORM、查询构建、事务)
- ORM 使用
- 通过 Model::query() 构建条件、预加载关系、分页
- 使用 fill()->save() 或 create() 进行写入;批量删除使用 destroy()
- 查询构建
- 结合 filterByCategory/filterByKeyword 等自定义作用域,提升可读性
- 事务处理
- 当涉及多表或多步写操作时,建议在 Service 层使用底层连接的事务封装(例如 DB::transaction),确保一致性
- 若发生异常,及时回滚并抛出领域异常,由入口统一响应
章节来源
- admin/service/article/ArticleService.php:63-314
- core/orm/Model.php:476-555
缓存机制(数据缓存、页面缓存、性能优化)
- 数据缓存
- 对高频读取且变更不频繁的数据(如配置、字典、树形结构)进行缓存
- 建议使用统一的 Cache 门面或存储抽象,避免散落的 session/file 缓存
- 页面缓存
- 对静态或低频变化的页面片段可使用页面缓存(如输出缓冲+键控存储)
- 性能优化
- 合理使用 with() 预加载减少 N+1 查询
- 分页与字段裁剪减少传输体积
- 合理索引与查询条件,避免全表扫描
依赖关系分析
- 入口与引导
- index.php 依赖 core/bootstrap.php 提供的路由与请求对象
- bootstrap 阶段完成配置、自动加载、容器、门面与助手函数注册
- 控制器与服务
- 控制器依赖服务进行业务编排;服务依赖模型与外部服务(附件、审计)
- 模型与数据库
- 模型基于 ORM 抽象,最终落到数据库连接
graph LR
Index["index.php"] --> Bootstrap["core/bootstrap.php"]
Bootstrap --> Config["config/config.php"]
Bootstrap --> Router["路由/请求"]
Router --> AdminCtrl["admin/controller/*"]
Router --> FrontCtrl["front/controller/*"]
Router --> ApiCtrl["api/controller/*"]
AdminCtrl --> AdminSvc["admin/service/*"]
FrontCtrl --> FrontSvc["front/service/*"]
ApiCtrl --> ApiSvc["api/service/*"]
AdminSvc --> Model["core/orm/Model"]
FrontSvc --> Model
ApiSvc --> Model
Model --> DB["数据库"]
图表来源
- index.php:26-75
- core/bootstrap.php:115-171
- core/orm/Model.php:476-555
章节来源
- index.php:26-75
- core/bootstrap.php:115-171
- core/orm/Model.php:476-555
性能考虑
- 查询层面
- 使用 with() 预加载关联数据,避免 N+1
- 仅选择必要字段(field()),减少内存与网络开销
- 合理使用分页与排序,避免大结果集
- 缓存层面
- 热点数据缓存(配置、字典、树)
- 页面片段缓存(首页、分类列表等)
- 资源层面
- 图片与附件使用独立存储与 CDN
- 静态资源压缩与合并
故障排查指南
- 入口异常处理
- 业务异常:JSON 请求返回 422 并附带错误信息;HTML 请求走消息页
- 未捕获异常:site.debug 开启时输出调试页,否则返回 JSON 500 或错误页
- 常见问题定位
- 检查路由是否正确映射到控制器 Action
- 检查 Service 是否抛出领域异常(DomainException)及提示信息
- 检查 ORM 查询是否命中预期数据,必要时打印 SQL 或使用调试工具
- 检查权限中间件配置,确认路由是否在 required/optional/public 白名单内
章节来源
- index.php:46-75
- index.php:90-126
结论
DouPHP 提供了清晰的 MVC 分层、完善的引导与路由体系、轻量 ORM 以及灵活的权限与中间件机制。遵循本文档的分层职责与最佳实践,可以快速、稳定地扩展新功能。建议在新模块中:
- 严格划分控制器(请求/响应)、服务(业务)、模型(数据)的职责
- 使用 ORM 与查询构建器,保持可维护性与可读性
- 通过中间件与配置集中管理权限与安全策略
- 引入缓存与分页优化性能
- 完善错误处理与日志审计,便于问题定位与追踪
附录:从零实现一个完整功能的步骤
以下以“新增一个业务模块”为例,给出端到端步骤(以“文章”模块为参考):
-
需求分析与设计
- 明确实体、字段、关系与业务流程
- 确定是否需要分类、标签、附件、评论等扩展能力
- 规划前台展示、后台管理与 API 暴露范围
-
目录与文件创建
- 后台:admin/controller/<module>/、admin/service/<module>/、admin/model/<module>/、admin/request/<module>/、admin/route/<module>.php
- 前台:front/controller/<module>/、front/service/<module>/、front/model/<module>/、front/route/<module>.php
- API:api/controller/<module>/、api/service/<module>/、api/route/<module>.php
- 视图:admin/view/.htm、theme//module*.dwt
- 语言包:languages/zh_cn/module.php
-
模型定义(ORM)
- 新建 Model,声明表名、主键、填充字段、类型转换、关系与预加载
- 如需全局过滤(如软删除、站点隔离),在 boot() 中注册全局 scope
-
服务层实现
- 列表:分页、过滤、字段裁剪、关联数据预加载
- 新增/更新:输入清洗、附件处理、草稿认领、审计日志
- 删除:二次确认分支、审计日志
- 批量:批量删除/转移等
-
控制器编写
- 后台控制器:继承 BaseController,实现 index/create/store/edit/update/destroy/action
- 前台控制器:实现列表/详情/搜索/归档等
- API 控制器:实现 RESTful 接口,统一返回结构
-
路由与中间件
- 注册路由文件,映射 URL 到控制器 Action
- 如需权限控制,在前台中间件配置中声明认证模式(public/optional/required)
- API 端启用用户认证中间件,确保 token 校验
-
视图与模板
- 后台使用 .htm 模板,配合 layoutVars 注入公共变量
- 前台使用 .dwt 模板,注入 SEO、导航、分页等数据
-
测试与验证
- 单元测试:服务层核心逻辑
- 接口测试:API 端点(正常/异常/权限)
- 端到端测试:前台/后台关键流程
-
部署与上线
- 配置数据库与缓存
- 迁移脚本与初始数据
- 权限与菜单配置
- 监控与日志
章节来源
- admin/controller/article/ArticleController.php:35-221
- front/controller/article/ArticleController.php:41-283
- admin/service/article/ArticleService.php:63-314
- core/orm/Model.php:51-800
- _'/module/user/front/init/middleware.php:18-55
- _'/module/user/api/middleware/UserAuthMiddleware.php:25-42