简介
本技术文档面向初学者与高级开发者,系统性阐述 DouPHP 核心框架的引导流程、自动加载机制、服务容器(DI)初始化与生命周期、路由系统、中间件管道、错误处理与日志记录,以及性能优化建议。文档以代码级为依据,提供可视化架构图与流程图,帮助读者快速掌握框架工作原理并高效扩展。
更新 本次更新重点反映了核心框架的重大重构:将领域模型从 core/foundation/ 迁移到 core/domain/,包括订单状态、支付状态、售后状态等枚举类的重新组织,提升了代码的可维护性和业务语义清晰度。
项目结构
DouPHP 采用"入口 + 核心 + 端侧"的分层组织方式:
- 根入口 index.php 负责最小化启动、异常兜底与响应输出。
- core/bootstrap.php 完成常量定义、配置加载、自动加载注册、容器与 Request 单例绑定等基础工作。
- core/autoload.php 实现基于命名空间约定的类自动加载,覆盖插件、核心、端侧与 Vendor 适配。
- 新增 core/domain/ 目录集中管理领域模型和状态枚举,提供业务语义化的状态管理。
- front/admin/api 三端各自拥有 Init、路由、中间件、控制器与服务,复用 core 能力。
- config 集中管理数据库、模块、路由与安全等配置。
graph TB
A["index.php<br/>应用入口"] --> B["core/bootstrap.php<br/>引导程序"]
B --> C["core/autoload.php<br/>自动加载"]
B --> D["core/foundation/container/Container.php<br/>DI 容器"]
B --> E["Request 单例绑定"]
C --> F["core/domain/*<br/>领域模型"]
F --> G["OrderStatus<br/>PaymentStatus<br/>AftersaleStatus"]
A --> H["前端/后台/API 路由调度"]
H --> I["各端 Init::boot()<br/>前台/后台初始化"]
I --> J["视图引擎/语言/模块装配"]
图表来源
- index.php:1-126
- core/bootstrap.php:1-180
- core/autoload.php:1-274
- core/foundation/container/Container.php:1-509
- core/domain/order/OrderStatus.php:1-137
章节来源
- index.php:1-126
- core/bootstrap.php:1-180
- core/autoload.php:1-274
- config/config.php:1-53
核心组件
- 引导程序 bootstrap:定义路径与协议常量、加载站点配置、注册自动加载器、注册别名、初始化 DI 容器、提前绑定 Request 与 DelegatingRouter,确保在 Init 之前可用。
- 自动加载 autoload:按优先级解析 Dou\Plugin*、Dou\Core*、端侧 Dou\Admin|Front|Api*、Core Module、Dou\Vendor*,最后兜底映射到 core 目录。
- 服务容器 Container:轻量 DI,支持 bind/singleton/factory/instance/alias/when()->needs()->give()、make/call、上下文绑定与构建栈追踪。
- 路由门面 Route:声明式 fluent API,用于构建期收集路由条目;运行时由 DelegatingRouter 分发。
- 端侧 Init:前台/后台分别完成会话、时区、语言、主题、语言包、模块、视图引擎、全局变量与授权检测等初始化。
- 新增 领域模型 Domain:集中管理业务状态枚举和状态迁移规则,提供类型安全的状态管理。
章节来源
- core/bootstrap.php:1-180
- core/autoload.php:1-274
- core/foundation/container/Container.php:1-509
- core/web/routing/Route.php:1-347
- front/init/Init.php:1-558
- admin/init/Init.php:1-393
架构总览
请求从根入口进入,经引导程序完成环境准备后,设置路由委托并执行前台 Init 初始化,随后通过路由分发调用控制器或服务,最终输出 Response。
sequenceDiagram
participant Client as "客户端"
participant Entry as "index.php"
participant Boot as "bootstrap.php"
participant Router as "DelegatingRouter"
participant FrontInit as "Front\\Init : : boot()"
participant Controller as "控制器/服务"
participant Domain as "领域模型"
participant Resp as "Response"
Client->>Entry : HTTP 请求
Entry->>Boot : 引入引导程序
Boot-->>Entry : 完成常量/配置/自动加载/容器/Request
Entry->>Router : setDelegate(前端路由器)
Entry->>FrontInit : boot(routeInfo)
FrontInit-->>Entry : 完成语言/模块/视图/安全等
Entry->>Router : dispatch()
Router->>Controller : 匹配路由并调用
Controller->>Domain : 使用领域状态枚举
Controller-->>Resp : 生成响应
Resp-->>Client : 发送响应
图表来源
- index.php:1-126
- core/bootstrap.php:1-180
- front/init/Init.php:1-558
- core/domain/order/OrderStatus.php:1-137
详细组件分析
引导程序执行流程
- 常量与环境:定义 ROOT_PATH、CONFIG_PATH、STORAGE_PATH、HTTP/IS_HTTPS,并在未安装时重定向至安装程序。
- 配置加载:读取 storage/state/admin_dir.php(可选)与 config/config.php,定义 CORE_PATH/LIBRARY_PATH/FRONT_PATH/API_PATH/ADMIN_PATH/MINIPROGRAM_PATH/PLUGIN_PATH。
- 模块与数据库配置:序列化缓存 module.php 与 DOU_DB_CONFIG,供后续阶段复用。
- 自动加载与别名:注册 spl_autoload_register,注册常用 Facade/Support 短名。
- 容器与早期绑定:获取容器实例,提前绑定 DelegatingRouter 与 Request 单例,确保 Init 之前可访问。
- 助手与事件:加载 app()/response 等全局助手,注册邮件通知与场景分发器。
flowchart TD
S["开始"] --> P["定义常量与协议"]
P --> I{"是否已安装?"}
I -- 否 --> R["重定向到安装程序"]
I -- 是 --> C["加载配置与模块/DB 配置"]
C --> A["注册自动加载与别名"]
A --> K["初始化容器并绑定 Request/Router"]
K --> H["加载助手与事件注册器"]
H --> E["结束"]
图表来源
- core/bootstrap.php:1-180
- config/config.php:1-53
章节来源
- core/bootstrap.php:1-180
- config/config.php:1-53
自动加载机制
- 优先级顺序:插件类 -> Core 类 -> 端侧类(Admin/Front/Api)-> Core Module -> Vendor 适配 -> 兜底 core 目录。
- 端侧约定:Dou\Admin|Front|Api{Init|Lib|Middleware|Http|Controller|Model|Service|Request|Facade|Foundation}... 映射到对应端目录。
- 插件兼容:支持 plugin/<name>/src/ 与 plugin/<name>/ 两种结构。
- 性能要点:按需 require_once,避免重复加载;模块映射预序列化减少 IO。
- 新增 领域模型支持:Dou\Core\Domain* 自动映射到 core/domain/ 目录,支持领域层的独立管理。
flowchart TD
Start["需要类 Dou\\Xxx\\Yyy"] --> CheckPlugin{"Dou\\Plugin\\* ?"}
CheckPlugin -- 是 --> LoadP["定位并加载插件类"]
CheckPlugin -- 否 --> CheckCore{"Dou\\Core\\* ?"}
CheckCore -- 是 --> CheckDomain{"Dou\\Core\\Domain\\* ?"}
CheckDomain -- 是 --> LoadD["定位并加载领域模型"]
CheckDomain -- 否 --> LoadC["定位并加载 Core 类"]
CheckCore -- 否 --> CheckEntry{"Dou\\Admin|Front|Api\\* ?"}
CheckEntry -- 是 --> LoadE["定位并加载端侧类"]
CheckEntry -- 否 --> CheckModule{"Dou\\Core\\Module\\* ?"}
CheckModule -- 是 --> LoadM["定位并加载模块类"]
CheckModule -- 否 --> CheckVendor{"Dou\\Vendor\\* ?"}
CheckVendor -- 是 --> LoadV["定位并加载 Vendor 类"]
CheckVendor -- 否 --> Fallback["core 目录兜底映射"]
Fallback --> End["完成"]
图表来源
- core/autoload.php:1-274
章节来源
- core/autoload.php:1-274
服务容器(DI)的使用与生命周期
- 注册方式:bind(每次新实例)、singleton(首次解析后缓存)、factory(工厂闭包)、instance(直接注入已有实例)、alias(别名)。
- 解析过程:make() 先走别名/工厂/单例缓存,再反射构造,递归解析依赖;call() 支持方法参数注入。
- 上下文绑定:when($consumer)->needs($abstract)->give(...) 仅对当前消费者生效,避免全局污染。
- 生命周期:容器为进程内单例;reset() 可用于测试隔离或重启场景清空状态。
classDiagram
class Container {
+getInstance()
+bind(abstract, concrete)
+singleton(abstract, concrete)
+factory(abstract, factory)
+instance(abstract, instance)
+alias(alias, target)
+make(abstract, parameters)
+call(instance, method, overrides)
+when(consumer) ContextualBindingBuilder
+has/bound/resolved/reset()
}
class ContextualBindingBuilder {
+needs(abstract)
+give(concrete)
}
Container --> ContextualBindingBuilder : "when() 返回"
图表来源
- core/foundation/container/Container.php:1-509
章节来源
- core/foundation/container/Container.php:1-509
路由系统工作原理
- 声明式路由:Route 门面仅在构建期使用,route/*.php 中通过 get/post/put/patch/delete/match/any/group/resource/column/simple/page 等方法登记路由条目。
- 运行时分发:DelegatingRouter 根据当前请求的 URL、方法与上下文匹配路由,调用控制器动作。
- 参数与子控制器:支持 params 占位符映射与 sub 子控制器段,便于模块化组织。
- 名称与前缀:可通过 name('api.') 等前缀组合 resource/group 形成统一命名空间。
sequenceDiagram
participant Req as "请求"
participant Router as "DelegatingRouter"
participant Match as "路由匹配"
participant Ctrl as "控制器动作"
participant Res as "响应"
Req->>Router : 传入 URL/Method/Header
Router->>Match : 解析 pattern/params/sub/module
Match-->>Router : 命中条目
Router->>Ctrl : 调用控制器方法
Ctrl-->>Res : 返回 Response
Res-->>Req : 发送响应体
图表来源
- core/web/routing/Route.php:1-347
- index.php:1-126
章节来源
- core/web/routing/Route.php:1-347
- index.php:1-126
中间件机制与请求处理管道
- 抽象基类:框架提供 AbstractSecurityHeadersMiddleware、AbstractCsrfMiddleware、AbstractThrottleMiddleware、AbstractUserAuthMiddleware 等通用基类,便于快速实现安全、限流、认证等中间件。
- 管道执行:请求进入路由前,依次经过注册的中间件链,每个中间件可对请求进行校验、改写或短路返回。
- 端侧中间件:前台/后台/API 各自维护 middleware 目录,按需注册安全头、CSRF、用户认证、限流等。
- 典型用法:在端侧 init/middleware.php 中注册中间件,或在路由组上附加中间件。
flowchart LR
In["入站请求"] --> M1["安全头中间件"]
M1 --> M2["CSRF 中间件"]
M2 --> M3["认证中间件"]
M3 --> M4["限流中间件"]
M4 --> Out["路由/控制器"]
图表来源
- core/foundation/middleware/MiddlewareInterface.php
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php
- core/foundation/middleware/AbstractCsrfMiddleware.php
- core/foundation/middleware/AbstractThrottleMiddleware.php
- core/foundation/middleware/AbstractUserAuthMiddleware.php
章节来源
- core/foundation/middleware/MiddlewareInterface.php
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php
- core/foundation/middleware/AbstractCsrfMiddleware.php
- core/foundation/middleware/AbstractThrottleMiddleware.php
- core/foundation/middleware/AbstractUserAuthMiddleware.php
前台与后台初始化差异
- 前台 Init:侧重多语言、主题策略、数据/片段/盒子、会员状态、SEO、JS 路由与语言导出、购物车角标等。
- 后台 Init:侧重管理员认证、菜单与工作区、主题设置、更新角标、云服务等后台专用能力。
- 共同点:均通过 InitTrait 完成会话、时区、错误报告、日志运行时、调试开关等基础步骤。
章节来源
- front/init/Init.php:1-558
- admin/init/Init.php:1-393
领域模型重构
重构概述
核心框架进行了重大重构,将领域模型从 core/foundation/ 迁移到 core/domain/,实现了业务领域的独立管理和状态机的规范化。这一重构提升了代码的可维护性、可读性和业务语义的清晰度。
领域模型组织结构
新的领域模型采用按业务域划分的目录结构:
core/domain/order/- 订单相关状态和逻辑core/domain/payment/- 支付相关状态和逻辑core/domain/aftersale/- 售后服务状态和逻辑core/domain/user/- 用户状态管理core/domain/distribution/- 分销申请状态core/domain/vip/- VIP 会员状态core/domain/withdraw/- 提现状态管理
订单状态模型
订单状态模型提供了完整的订单生命周期管理,包括状态验证、迁移规则和展示样式。
stateDiagram-v2
[*] --> PENDING : 下单成功
PENDING --> AWAITING_CONFIRMATION : 等待付款确认
PENDING --> PAID : 直接付款
PENDING --> CANCELLED : 取消订单
AWAITING_CONFIRMATION --> PAID : 审核通过
AWAITING_CONFIRMATION --> PENDING : 审核驳回
AWAITING_CONFIRMATION --> CANCELLED : 超时取消
PAID --> COMPLETED : 发货完成
PAID --> REFUNDING : 发起退款
COMPLETED --> REFUNDING : 申请售后
REFUNDING --> REFUNDED : 全额退款
REFUNDING --> PARTIAL_REFUNDED : 部分退款
REFUNDING --> PAID : 退款驳回
PARTIAL_REFUNDED --> REFUNDING : 继续退款
PARTIAL_REFUNDED --> REFUNDED : 全部退款
CANCELLED --> [*]
REFUNDED --> [*]
图表来源
- core/domain/order/OrderStatus.php:58-67
支付状态模型
支付状态模型独立于订单状态,支持多次支付尝试和复杂的退款流程。
售后状态模型
售后状态模型涵盖了完整的售后服务流程,包括申请、审核、退货、退款等环节。
领域模型的核心特性
- 状态验证:所有状态变更都通过
isValid()方法进行合法性检查 - 迁移控制:使用
canTransit()方法确保状态转换符合业务规则 - 表驱动设计:状态迁移规则通过静态数组配置,易于维护和扩展
- 类型安全:使用字符串常量而非魔法数字,提高代码可读性
- 展示辅助:提供
badgeClass()等方法用于界面展示
章节来源
- core/domain/order/OrderStatus.php:1-137
- core/domain/payment/PaymentStatus.php:1-107
- core/domain/aftersale/AftersaleStatus.php:1-128
- core/domain/user/UserStatus.php:1-94
- core/domain/distribution/DistributionStatus.php:1-108
- core/domain/vip/VipStatus.php:1-95
- core/domain/withdraw/WithdrawStatus.php:1-117
依赖关系分析
- 入口依赖引导程序,引导程序依赖配置与自动加载,自动加载依赖命名空间约定。
- 容器在引导阶段即被初始化,并提前绑定 Request 与 DelegatingRouter,保证 Init 之前可用。
- 路由门面仅在构建期使用,运行时由 DelegatingRouter 接管;中间件在端侧注册并作用于请求管道。
- 前台/后台 Init 依赖容器提供的服务(如语言、主题、消息响应器等),并通过 ProviderRegistry 动态装配。
- 新增 领域模型通过自动加载机制被服务层引用,提供类型安全的状态管理。
graph TB
Index["index.php"] --> Boot["bootstrap.php"]
Boot --> Autoload["autoload.php"]
Boot --> Container["Container.php"]
Boot --> Request["Request 单例"]
Index --> Router["DelegatingRouter"]
Router --> FrontInit["Front\\Init"]
Router --> AdminInit["Admin\\Init"]
FrontInit --> Services["业务服务/模型"]
AdminInit --> Services
Services --> Domain["领域模型"]
Domain --> OrderStatus["OrderStatus"]
Domain --> PaymentStatus["PaymentStatus"]
Domain --> AftersaleStatus["AftersaleStatus"]
图表来源
- index.php:1-126
- core/bootstrap.php:1-180
- core/autoload.php:1-274
- core/foundation/container/Container.php:1-509
- front/init/Init.php:1-558
- admin/init/Init.php:1-393
- core/domain/order/OrderStatus.php:1-137
章节来源
- index.php:1-126
- core/bootstrap.php:1-180
- core/autoload.php:1-274
- core/foundation/container/Container.php:1-509
- front/init/Init.php:1-558
- admin/init/Init.php:1-393
性能考量
- 自动加载:按需加载、避免重复 include;模块映射预序列化减少 IO。
- 容器:优先使用 singleton 或 instance 注册共享对象(如 Request、模板引擎、服务),减少反射开销。
- 路由:尽量使用具体动词路由而非 any,缩小匹配范围;合理使用 group 与 resource 减少重复声明。
- 视图:启用编译缓存目录并确保写入权限;合理分配模板变量,避免大对象频繁重建。
- 中间件:将昂贵检查放在靠后的位置,尽早短路无效请求。
- 配置:将频繁读取的配置放入 Config 缓存或容器单例,避免重复文件 IO。
- 新增 领域模型:状态验证使用静态数组查找,O(1) 时间复杂度;避免在循环中重复创建状态对象。
故障排查指南
- 未安装跳转:若 storage/install.lock 不存在且非安装路径,会重定向到安装程序。
- 语言与重写:当开启多语言但 rewrite 关闭或语言包缺失时,会重定向回首页。
- HTTPS 强制:当配置开启 SSL 且当前非 HTTPS,会 301 跳转到 https。
- 未捕获异常:入口统一捕获 Exception/Throwable,site.debug 开启时输出调试页或 JSON 500;否则提示错误或 JSON 错误。
- 常见错误:
- 无法解析参数:容器抛出 Cannot resolve parameter ...,检查类型提示与绑定。
- 路由不匹配:确认 route/*.php 中的 pattern、methods、sub 与控制器方法一致。
- 中间件短路:检查安全头、CSRF、认证、限流中间件的返回逻辑。
- 新增 状态迁移失败:检查领域模型的
canTransit()方法,确认状态转换是否符合业务规则。
章节来源
- core/bootstrap.php:1-180
- front/init/Init.php:1-558
- index.php:1-126
结论
DouPHP 核心框架通过清晰的引导流程、灵活的自动加载、强大的 DI 容器与声明式路由,提供了可扩展、易维护的请求处理管线。结合中间件机制与完善的错误处理,既能满足初学者快速上手,也能支撑高级开发者深度定制。
更新 领域模型的重构进一步提升了框架的业务语义清晰度和代码可维护性。通过将领域状态和业务规则集中管理,开发者可以更专注于业务逻辑的实现,同时获得类型安全和状态一致性保障。建议在项目中遵循命名规范、合理使用容器与路由、谨慎添加中间件,并充分利用新的领域模型来管理复杂的状态流转。
附录:使用示例与最佳实践
- 服务注册与解析
- 在引导或模块初始化中通过 container->singleton()/instance() 注册服务。
- 在控制器或服务构造函数中声明依赖,容器自动注入。
- 使用 when()->needs()->give() 针对特定消费者切换实现。
- 路由声明
- 使用 Route::get/post/put/patch/delete/match/any 登记路由。
- 使用 group 与 resource 批量声明 CRUD 路由,配合 only/except 控制范围。
- 使用 column/simple/page 按风格规则展开路由。
- 中间件
- 继承 Abstract*Middleware 实现安全头、CSRF、限流、认证等。
- 在端侧 middleware.php 中注册中间件,或按路由组附加。
- 领域模型使用
- 新增 使用领域状态枚举替代魔法数字,如
OrderStatus::PAID而非'paid'。 - 新增 在状态变更前调用
canTransit()验证状态转换合法性。 - 新增 利用
isValid()方法进行输入验证,确保数据完整性。 - 新增 使用
badgeClass()等方法获取展示样式,保持 UI 一致性。
- 新增 使用领域状态枚举替代魔法数字,如
- 错误处理
- 业务异常抛出 DomainException,入口统一渲染 JSON 或页面。
- 未捕获异常通过 SiteDebugExceptionRenderer 输出调试信息或标准错误。
- 性能优化
- 将热路径对象注册为单例;减少反射与 IO;启用模板编译缓存。
- 路由尽量精确匹配;中间件尽早短路;避免在循环中重复创建大对象。
- 新增 领域模型状态验证使用静态数组,避免重复计算;合理使用缓存提升查询性能。
章节来源
- core/foundation/container/Container.php:1-509
- core/web/routing/Route.php:1-347
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php
- core/foundation/middleware/AbstractCsrfMiddleware.php
- core/foundation/middleware/AbstractThrottleMiddleware.php
- core/foundation/middleware/AbstractUserAuthMiddleware.php
- index.php:1-126
- core/domain/order/OrderStatus.php:1-137
- core/service/order/OrderStatusTransition.php:1-200