文档目录
代码规范与约定

简介

本规范面向 DouPHP 项目的后端 PHP、前端模板与静态资源,目标是统一编码风格、命名约定、模块职责、SQL 编写、错误处理与日志记录标准,并提供可执行的代码审查清单与自动化检查建议。文档基于仓库现有实现进行归纳,确保规范与既有代码一致且可落地执行。

更新 新增导航和页面事实约定章节,明确$route_module和$route_action变量的语义分离原则,替代旧的$cur变量使用方式。

项目结构

DouPHP 采用"入口 + 核心框架 + 三端(前台 front、后台 admin、API)+ 主题与插件"的分层组织方式:

  • 根入口 index.php 负责初始化引导、路由委派与全局异常处理。
  • core 提供框架能力(自动加载、容器、HTTP、ORM、服务、支持类等)。
  • config 集中管理应用配置(数据库、路径、调试开关等)。
  • front/admin/api 为三个独立入口域,各自包含 controller、service、model、request、route、middleware、init 等分层目录。
  • theme/newtheme/miniprogram 分别承载前台主题、新主题与小程序前端资源。
  • plugin 存放第三方或业务插件。
  • storage 用于运行时数据与缓存。
graph TB
A["入口 index.php"] --> B["引导 core/bootstrap.php"]
B --> C["配置 config/config.php"]
B --> D["自动加载 core/autoload.php"]
A --> E["前台 front/*"]
A --> F["后台 admin/*"]
A --> G["API api/*"]
E --> H["主题 theme/* / newtheme/*"]
F --> I["管理界面视图 admin/view/*"]
G --> J["API 响应与中间件"]

图示来源

  • index.php:1-75
  • core/bootstrap.php:15-180
  • config/config.php:15-53
  • core/autoload.php:18-114

章节来源

  • index.php:1-75
  • core/bootstrap.php:15-180
  • config/config.php:15-53
  • core/autoload.php:18-114

核心组件

  • 入口与引导
    • index.php:设置路由委派、解析语言前缀、启动 Init、分发路由、统一捕获异常并输出 JSON 或页面提示。
    • core/bootstrap.php:定义常量、加载配置、注册自动加载、别名、DI 容器、Request/Router 单例、助手函数与事件注册器。
  • 自动加载与命名空间映射
    • core/autoload.php:实现 Dou\ 命名空间的自动加载规则,覆盖插件、Core、端侧(Admin/Front/Api)、Vendor 与兜底映射。
  • 控制器基类
    • admin/controller/BaseController.php:后台控制器基类,封装 view()、布局变量注入、删除结果响应、布尔切换响应等。
    • api/controller/BaseController.php:API 控制器基类,复用前台用户中心导航构建逻辑。
    • front/controller/BaseController.php:前台控制器基类,提供页面事实变量统一处理和导航构建。
  • 模型通用修改器
    • core/model/concerns/ContentMutators.php:内容模型的字段写入时标准化(标题、slug、关键词、描述、排序、时间、价格等)。

章节来源

  • index.php:1-75
  • core/bootstrap.php:15-180
  • core/autoload.php:18-114
  • admin/controller/BaseController.php:30-370
  • api/controller/BaseController.php:24-60
  • front/controller/BaseController.php:38-184
  • core/model/concerns/ContentMutators.php:21-111

架构总览

请求从入口进入,经引导初始化后由路由分发到对应端(front/admin/api)的控制器,控制器调用服务层与模型层完成业务逻辑,最终通过统一的响应对象返回 JSON 或视图。

sequenceDiagram
participant U as "客户端"
participant R as "入口 index.php"
participant B as "引导 bootstrap.php"
participant RT as "路由 Router"
participant C as "控制器 Controller"
participant S as "服务 Service"
participant M as "模型 Model"
participant V as "视图/响应"
U->>R : HTTP 请求
R->>B : 初始化常量/配置/自动加载
B-->>R : 可用 Request/Router/容器
R->>RT : 设置委派并分发
RT->>C : 调用具体控制器方法
C->>S : 执行业务逻辑
S->>M : 读写数据
M-->>S : 数据对象
S-->>C : 业务结果
C->>V : 构造响应(ViewResponse/ApiResponse)
V-->>U : 返回响应

图示来源

  • index.php:26-75
  • core/bootstrap.php:115-180
  • admin/controller/BaseController.php:60-68
  • api/controller/BaseController.php:38-60

详细组件分析

入口与引导流程

  • 入口职责
    • 设置路由委派、解析语言前缀、启动 Init、分发路由、统一捕获异常并输出 JSON 或页面提示。
  • 引导职责
    • 定义常量、加载配置、注册自动加载、别名、DI 容器、Request/Router 单例、助手函数与事件注册器。
flowchart TD
Start(["进程启动"]) --> Boot["加载 bootstrap.php"]
Boot --> Config["读取 config/config.php"]
Config --> Autoload["注册自动加载与别名"]
Autoload --> DI["初始化容器与单例"]
DI --> Entry["入口 index.php 继续"]
Entry --> Route["设置路由委派并分发"]
Route --> Handle["捕获异常并输出响应"]
Handle --> End(["结束"])

图示来源

  • core/bootstrap.php:15-180
  • config/config.php:15-53
  • index.php:26-75

章节来源

  • index.php:1-75
  • core/bootstrap.php:15-180
  • config/config.php:15-53

自动加载与命名空间约定

  • 命名空间与目录映射
    • Dou\Plugin* -> plugin//src/ 或 plugin/*
    • Dou\Core* -> core/*
    • 端侧 Dou\Admin|Front|Api 下的 Init/Lib/Middleware/Http/Controller/Model/Service/Request/Facade/Foundation/Contract 按层映射到对应目录
    • Dou\Vendor* -> core/library/{package}/...
  • 模块类映射
    • 根据已安装模块动态生成 ClassMap,提升加载效率。
classDiagram
class 自动加载器 {
+注册Dou命名空间
+解析插件类
+解析Core类
+解析端侧类
+解析Vendor类
+兜底映射
}
class 插件类 {
+Dou\\Plugin\\*
}
class Core类 {
+Dou\\Core\\*
}
class 端侧类 {
+Dou\\{Admin|Front|Api}\\*
}
class Vendor类 {
+Dou\\Vendor\\*
}
自动加载器 --> 插件类 : "优先匹配"
自动加载器 --> Core类 : "次级匹配"
自动加载器 --> 端侧类 : "按层映射"
自动加载器 --> Vendor类 : "库适配"

图示来源

  • core/autoload.php:18-114
  • core/autoload.php:140-204
  • core/autoload.php:234-273

章节来源

  • core/autoload.php:18-114
  • core/autoload.php:140-204
  • core/autoload.php:234-273

控制器基类与响应模式

  • 后台控制器基类
    • 提供 view() 渲染 ViewResponse,合并布局变量与 AI 工具栏配置。
    • 提供 respondDeleteResult() 统一删除结果响应(302 + flash 或二次确认页)。
    • 提供 respondToggle() 统一布尔切换响应(JSON 或 302 + flash)。
  • API 控制器基类
    • 复用前台用户中心导航构建逻辑,保持 API 与前台一致的导航 ViewModel。
  • 前台控制器基类
    • 提供 pageFactVars() 统一处理页面事实变量,包括导航列表、cur、route_module、route_action。
    • 强制区分导航高亮(cur)和内容分支(route_module/route_action)的使用场景。
classDiagram
class 后台控制器基类 {
+view(template, data, status)
-absolutizeActionUrls(data)
-injectAiToolbar(data)
-isAiMountableModule(module)
+layoutVars()
-normalizeFlashes(rawAll)
-normalizeOne(raw)
+respondDeleteResult(result)
+respondToggle(request, value, message, backUrl)
+buildLinkUserCenter(currentModule)
}
class API控制器基类 {
+buildLinkUserCenter(currentModule)
}
class 前台控制器基类 {
+pageFactVars(merged)
+view(template, data, statusCode)
+layoutVars()
+respond(request, redirectUrl, data, message)
+buildLinkUserCenter(currentModule)
}
后台控制器基类 <|-- 具体后台控制器
API控制器基类 <|-- 具体API控制器
前台控制器基类 <|-- 具体前台控制器

图示来源

  • admin/controller/BaseController.php:30-370
  • api/controller/BaseController.php:24-60
  • front/controller/BaseController.php:38-184

章节来源

  • admin/controller/BaseController.php:30-370
  • api/controller/BaseController.php:24-60
  • front/controller/BaseController.php:38-184

导航和页面事实约定

新增 本节详细说明$route_module和$route_action变量的语义分离原则,以及新的导航高亮机制。

  • 页面事实变量处理
    • route_module:当前页命中的稳定路由模块名,用于内容分支判断(如区分不同宿主页面)。
    • route_action:当前页命中的稳定路由动作名,用于细粒度内容控制。
    • cur:由 NavigationBuilder::middle() 解析出的归属模块,专用于菜单高亮判断。
  • 导航高亮机制
    • 禁止使用$route_module/$route_action进行菜单高亮判断。
    • 菜单高亮必须通过 NavigationBuilder 计算的布尔值或使用 cur 变量。
    • NavigationBuilder 会自动从 request()->routeModule() 获取当前模块作为默认值。
  • 变量注入顺序
    • action data > layoutVars() > pageFactVars() 兜底值。
    • 保证存量手写值的控制器在清理批次前后行为均不受影响。
flowchart TD
A["控制器 action 返回 $data"] --> B["合并 layoutVars()"]
B --> C["pageFactVars() 处理"]
C --> D{"是否已有 nav_top_list?"}
D --> |否| E["NavigationBuilder::top()"]
D --> |是| F["跳过"]
C --> G{"是否已有 nav_middle_list?"}
G --> |否| H["NavigationBuilder::middle()"]
G --> |是| I["跳过"]
C --> J{"是否已有 cur?"}
J --> |否| K["NavigationBuilder::contextModule()"]
J --> |是| L["跳过"]
C --> M{"是否已有 route_module?"}
M --> |否| N["request()->routeModule()"]
M --> |是| O["跳过"]
C --> P{"是否已有 route_action?"}
P --> |否| Q["request()->routeAction()"]
P --> |是| R["跳过"]
E --> S["最终模板变量"]
I --> S
K --> S
N --> S
Q --> S

图示来源

  • front/controller/BaseController.php:81-109
  • front/service/nav/NavigationBuilder.php:72-90

章节来源

  • front/controller/BaseController.php:63-109
  • front/service/nav/NavigationBuilder.php:58-90

模型字段修改器(ContentMutators)

  • 统一字段写入时的清洗与类型转换,避免脏数据入库。
  • 支持的字段包括:标题、slug、定义项、关键词、描述、排序、添加时间、价格、促销价等。
flowchart TD
In(["写入字段值"]) --> Type{"字段类型"}
Type --> |标题/Slug| Trim["去除首尾空白"]
Type --> |定义项| Replace["替换换行为逗号"]
Type --> |关键词/描述| Cast["强制字符串"]
Type --> |排序| Numeric["数值化或空串"]
Type --> |添加时间| ParseTime["strtotime 转时间戳"]
Type --> |价格/促销价| TrimPrice["去除空白"]
Trim --> Out(["标准化后的值"])
Replace --> Out
Cast --> Out
Numeric --> Out
ParseTime --> Out
TrimPrice --> Out

图示来源

  • core/model/concerns/ContentMutators.php:21-111

章节来源

  • core/model/concerns/ContentMutators.php:21-111

依赖关系分析

  • 入口依赖引导与配置
    • index.php 依赖 bootstrap.php 提供的常量、自动加载、容器与助手;依赖 config/config.php 中的数据库与路径配置。
  • 引导依赖自动加载与别名
    • bootstrap.php 注册自动加载与别名,使后续控制器、服务、模型可按命名空间加载。
  • 控制器依赖服务与模型
    • 控制器通过门面/助手调用服务与模型,遵循分层解耦。
  • 前台控制器依赖导航构建器
    • 前台控制器基类依赖 NavigationBuilder 进行导航数据构建和上下文模块解析。
graph LR
Index["index.php"] --> Bootstrap["bootstrap.php"]
Bootstrap --> Config["config/config.php"]
Bootstrap --> Autoload["autoload.php"]
Index --> Router["路由分发"]
Router --> Controllers["控制器"]
Controllers --> Services["服务"]
Services --> Models["模型"]
FrontControllers["前台控制器"] --> NavBuilder["NavigationBuilder"]
NavBuilder --> Request["Request"]

图示来源

  • index.php:1-75
  • core/bootstrap.php:15-180
  • config/config.php:15-53
  • core/autoload.php:18-114
  • front/controller/BaseController.php:83-94

章节来源

  • index.php:1-75
  • core/bootstrap.php:15-180
  • config/config.php:15-53
  • core/autoload.php:18-114

性能考量

  • 自动加载优化
    • 使用 ClassMap 对已安装模块类进行预注册,减少文件系统探测开销。
  • 单例与懒加载
    • Request、Router、容器等在引导阶段以单例形式注册,避免重复构造。
  • 响应最小化
    • 控制器统一返回 ViewResponse/ApiResponse,减少冗余数据处理。
  • 配置一次性加载
    • module.php 在引导阶段统一读取并序列化,供多处复用,降低 IO 次数。
  • 导航缓存优化
    • NavigationBuilder 使用静态缓存避免重复数据库查询,提升导航构建性能。

故障排查指南

  • 未安装跳转
    • 若 storage/install.lock 不存在,非安装路径的请求将被重定向至安装程序。
  • 全局异常处理
    • 入口捕获 DomainException、HttpResponseException、RedirectException 与普通 Exception/Throwable,按 site.debug 与 JSON 协商输出调试页或 JSON 500。
  • 日志记录
    • 未捕获异常会写入 error_log,便于定位问题。
  • 导航高亮问题
    • 如果菜单高亮不正确,检查是否使用了$route_module/$route_action进行高亮判断,应改用 cur 变量或 NavigationBuilder 计算结果。

章节来源

  • core/bootstrap.php:42-57
  • index.php:38-75
  • index.php:90-125

结论

DouPHP 通过清晰的入口引导、严格的命名空间自动加载、分层控制器基类与统一的响应模式,构建了可扩展、易维护的代码体系。配合 ContentMutators 的数据清洗与全局异常处理,项目在稳定性与一致性方面具备良好基础。新增的导航和页面事实约定进一步明确了$route_module/$route_action与cur变量的语义分离,提升了代码的可维护性和可读性。建议在团队中严格执行本规范,并结合自动化检查工具保障代码质量。

附录:检查清单与工具配置

PHP 代码风格与 PSR 遵循

  • 命名空间与自动加载
    • 所有类必须位于 Dou\ 命名空间下,并按 autoload.php 约定的目录结构放置。
  • 缩进与括号
    • 使用 4 空格缩进;控制结构与函数大括号遵循 PSR-12 风格。
  • 注释格式
    • 文件头部保留版权与协议注释;类与方法使用结构化注释(含参数与返回值说明)。
  • 常量与配置
    • 应用常量集中在 bootstrap.php 与 config/config.php 中定义,避免硬编码。

目录结构与模块职责

  • 三端分层
    • controller:接收请求、编排服务、返回响应。
    • service:业务逻辑与跨模块协作。
    • model:数据访问与字段修改器。
    • request:输入校验与参数绑定。
    • route:路由定义。
    • middleware:横切关注点(鉴权、限流、安全头)。
    • init:端侧初始化与容器绑定。
  • 主题与插件
    • theme/newtheme:前台主题资源与模板。
    • plugin:插件按包隔离,遵循 Dou\Plugin* 命名空间。

命名约定

  • 类名:StudlyCase(如 BaseController、ContentMutators)。
  • 方法名:camelCase(如 layoutVars、respondDeleteResult)。
  • 变量名:camelCase(如 $statusCode、$backUrl)。
  • 常量:UPPER_SNAKE_CASE(如 ROOT_PATH、DOU_DEBUG)。
  • 文件名:与类名一致(如 BaseController.php)。

导航和页面事实变量约定

新增 本节规定$route_module、$route_action和cur变量的使用规范。

  • 变量语义分离
    • route_module:仅用于内容分支判断,如区分不同宿主页面的展示逻辑。
    • route_action:仅用于细粒度的内容控制,如特定动作的特殊处理。
    • cur:专用于菜单高亮判断,由 NavigationBuilder 计算得出。
  • 禁止事项
    • 禁止使用$route_module/$route_action进行菜单高亮判断。
    • 禁止在模板中直接比较$route_module/$route_action进行导航状态判断。
  • 正确用法示例
    • 内容分支:if ($route_module === 'product') { ... }
    • 菜单高亮:if ($cur === 'product') { ... } 或使用 NavigationBuilder 计算的布尔值

SQL 查询编写规范

  • 使用 ORM 或查询构建器,避免拼接原始 SQL。
  • 参数化查询,防止注入。
  • 分页与索引:列表查询需考虑分页与必要索引。
  • 事务:涉及多表写操作时使用事务保证一致性。

错误处理模式

  • 控制器抛出领域异常或返回统一响应对象。
  • 入口统一捕获并输出 JSON 或页面提示。
  • 日志:关键错误记录 error_log,便于追踪。

日志记录标准

  • 使用 error_log 记录未捕获异常与关键业务事件。
  • 敏感信息脱敏后再记录。
  • 区分环境:生产环境关闭调试输出,仅记录必要日志。

前端代码规范(JavaScript/CSS/模板)

  • JavaScript
    • 模块化:按功能拆分脚本,避免全局污染。
    • 命名:camelCase 变量与函数,PascalCase 构造函数。
    • 异步:统一使用 Promise/async-await 处理异步逻辑。
  • CSS
    • 选择器语义化,避免深层嵌套。
    • 变量与主题:使用 CSS 变量管理颜色与尺寸。
  • 模板文件
    • .dwt/.htm:仅展示逻辑,不包含复杂业务计算。
    • 变量输出需转义,防止 XSS。
    • 导航高亮:使用 cur 变量而非$route_module/$route_action。

代码审查检查清单

  • 是否遵循命名空间与自动加载约定?
  • 控制器是否只编排服务与返回响应?
  • 服务层是否包含完整业务逻辑?
  • 模型是否使用修改器清洗字段?
  • 是否使用参数化查询与事务?
  • 是否统一异常处理与日志记录?
  • 前端模板是否仅负责展示?
  • 是否通过自动化检查(Lint/格式化)?
  • 新增 导航高亮是否正确使用 cur 变量而非$route_module/$route_action?
  • 新增 内容分支是否正确使用$route_module/$route_action?

自动化检查工具配置建议

  • PHP
    • 使用 PHP_CodeSniffer 或 PHP CS Fixer 配置 PSR-12 规则。
    • 在 Git Hooks 或 CI 中强制执行。
  • 前端
    • ESLint + Prettier 统一 JS 风格。
    • Stylelint 检查 CSS。
  • 模板
    • 模板变量输出转义检查(结合 Lint 规则)。
    • 新增 导航变量使用检查:检测模板中是否误用$route_module/$route_action进行高亮判断。
添加日期:2026-10-05