文档目录
前台架构设计

简介

本文面向 DouPHP 前台应用的架构设计与实现,聚焦 MVC 分层(控制器、服务、模型)、请求处理流程(路由解析到响应生成)、中间件机制(CSRF、用户认证、权限控制)以及前台与后台、API 模块的协作关系。文档提供架构图与流程图,并给出扩展点与自定义开发建议,帮助开发者快速理解与扩展前台能力。

项目结构

前台应用位于 front 目录,采用清晰的 MVC 分层与模块化组织:

  • 控制器层:front/controller/*,按业务模块划分,继承 BaseController,负责接收请求、调用服务、返回视图或响应。
  • 服务层:front/service/*,封装领域逻辑,供控制器调用。
  • 模型层:front/model/*,数据访问与实体映射。
  • 路由与调度:front/foundation/routing/*,负责 URL 匹配、控制器与方法解析、中间件装配。
  • 中间件:front/middleware/*,统一安全与鉴权策略。
  • 初始化:front/init/*,站点启动、语言与主题、全局变量注入等。
  • 配置:config/*,数据库、应用密钥、调试开关、URL 风格规则等。
graph TB
A["入口 index.php"] --> B["前台初始化 Init::boot()"]
B --> C["路由 Router::dispatch()"]
C --> D["FrontResolver::resolve()"]
D --> E["中间件链<br/>SecurityHeaders / TrustProxy / Throttle / UserAuth / Csrf"]
E --> F["控制器方法执行"]
F --> G["服务层 Service"]
G --> H["模型层 Model"]
F --> I["视图渲染 ViewResponse"]
I --> J["HTTP 响应发送"]

图表来源

  • index.php:16-44
  • front/init/Init.php:73-89
  • front/foundation/routing/Router.php:40-56
  • front/foundation/routing/FrontResolver.php:52-105

章节来源

  • index.php:16-44
  • front/init/Init.php:73-89
  • front/foundation/routing/Router.php:40-56
  • front/foundation/routing/FrontResolver.php:52-105

核心组件

  • 入口与异常处理:根入口 index.php 设置路由委托、预处理语言前缀、启动前台 Init、分发路由、统一捕获异常并按 JSON/HTML 输出。
  • 前台初始化:Init::boot 完成会话、时区、语言、主题、视图引擎、语言包与模块加载、会员状态注入、站点关闭检测等。
  • 路由解析:FrontResolver 基于 PrettyRouteMatcher 将 URL 解析为 DispatchPlan,装配中间件链与表单目标、主题扩展。
  • 中间件:CsrfMiddleware 提供 CSRF 校验;UserAuthMiddleware 提供登录态恢复与鉴权拒绝策略;ThrottleMiddleware 限流;SecurityHeadersMiddleware 安全头。
  • 控制器基类:BaseController 提供 view/respond/layoutVars 等通用能力,统一 JSON/重定向分流。
  • 配置:config/config.php 定义数据库、应用密钥、调试标志;config/route.php 定义 URL 风格规则(page/column/simple)。

章节来源

  • index.php:16-75
  • front/init/Init.php:73-89
  • front/foundation/routing/FrontResolver.php:52-105
  • front/middleware/CsrfMiddleware.php:24-95
  • front/middleware/UserAuthMiddleware.php:26-98
  • front/controller/BaseController.php:37-133
  • config/config.php:15-52
  • config/route.php:32-355

架构总览

前台采用“薄壳路由 + 声明式中间件 + 控制器-服务-模型”的分层架构。入口仅做最小化编排,核心逻辑集中在 FrontResolver 与 Init。中间件以别名注册,默认栈顺序保证安全优先。控制器通过依赖注入获取服务,服务组合模型与外部资源,最终由 BaseController 统一输出视图或 JSON。

sequenceDiagram
participant Client as "客户端"
participant Entry as "入口 index.php"
participant Init as "前台初始化 Init"
participant Router as "路由 Router"
participant Resolver as "FrontResolver"
participant MW as "中间件链"
participant Ctrl as "控制器"
participant Svc as "服务层"
participant Model as "模型层"
participant View as "视图响应"
Client->>Entry : HTTP 请求
Entry->>Init : boot(routeInfo)
Init-->>Entry : 初始化完成
Entry->>Router : dispatch()
Router->>Resolver : resolve(request, container)
Resolver-->>Router : DispatchPlan(含中间件)
Router->>MW : 依次执行
MW-->>Ctrl : 进入控制器方法
Ctrl->>Svc : 调用业务服务
Svc->>Model : 数据访问
Model-->>Svc : 数据结果
Svc-->>Ctrl : 业务数据
Ctrl->>View : 构建 ViewResponse
View-->>Client : 发送响应

图表来源

  • index.php:16-44
  • front/init/Init.php:73-89
  • front/foundation/routing/Router.php:40-56
  • front/foundation/routing/FrontResolver.php:52-105
  • front/controller/BaseController.php:52-85

详细组件分析

入口与异常处理(index.php)

  • 设置路由委托为前台 Router。
  • 预处理 route 参数,剥离语言前缀写入 Request。
  • 调用 Init::boot 完成站点初始化。
  • 执行 Route::dispatch,若返回 Response 则直接发送。
  • 统一捕获 HttpResponseException、RedirectException、DomainException 与普通异常,按 JSON/HTML 输出错误页或消息提示。
flowchart TD
Start(["请求进入"]) --> Parse["解析 route 与语言前缀"]
Parse --> Boot["Init::boot() 初始化"]
Boot --> Dispatch["Route::dispatch()"]
Dispatch --> Resp{"是否 Response?"}
Resp -- 是 --> Send["发送响应并退出"]
Resp -- 否 --> Next["继续后续处理"]
Dispatch --> Catch{"捕获异常?"}
Catch -- 是 --> Handle["按类型输出错误/消息"]
Catch -- 否 --> End(["结束"])

图表来源

  • index.php:16-75

章节来源

  • index.php:16-75

前台初始化(Init)

  • 公共步骤:会话、错误报告、时区、根 URL、当前语言、自定义文件加载。
  • 核心对象实例化:容器、Provider、SiteBootstrap、SystemBootstrap、日志、常量、配置加载。
  • 视图引擎:DouView 模板目录、编译目录、预处理器、容器注册。
  • 语言与模块:多语言校验、HTTPS 强制、授权检测、语言包、会员模块(features.user)动态加载。
  • 全局视图变量:lang、token、csrf_token、honeypot_ts、site、js_routes、about、param、features、link_list、lang_menu、generator、authorized、url、code_head、cart_total、index.cur、fragment 等。
  • 站点关闭检测:当 site.site_closed 开启时直接输出维护页。
classDiagram
class Init {
+boot(routeInfo) void
-bootCommon(routeInfo) void
-resolveCurLang(routeInfo) void
-bootCore() void
-loadLanguageAndModules() void
-setupViewEngine() void
-assignCommonViewVars() void
-checkSiteClosed() void
}

图表来源

  • front/init/Init.php:73-557

章节来源

  • front/init/Init.php:73-557

路由解析与调度(Router 与 FrontResolver)

  • Router 作为薄壳:读取 Request,调用 FrontResolver 产出 DispatchPlan,未命中返回 page_wrong 提示,命中后交由 Dispatcher 执行。
  • FrontResolver:
    • 使用 PrettyRouteMatcher 规范化 URL,得到 module/action/sub/params/controller。
    • 组装中间件链(默认栈:security_headers -> trust_proxy -> throttle -> user_auth -> csrf),支持路由级豁免与追加。
    • 设置 Request 的 baseUrl、route、params,合并输入,分配 cur、form_target、主题扩展。
    • 返回 DispatchPlan 给 Dispatcher 执行。
flowchart TD
RStart["请求进入 Router"] --> Resolve["FrontResolver::resolve()"]
Resolve --> Match{"匹配成功?"}
Match -- 否 --> NotFound["返回 page_wrong"]
Match -- 是 --> Compose["组装中间件链"]
Compose --> SetReq["设置 Request 信息"]
SetReq --> Plan["返回 DispatchPlan"]
Plan --> Exec["Dispatcher 执行控制器方法"]

图表来源

  • front/foundation/routing/Router.php:40-56
  • front/foundation/routing/FrontResolver.php:52-105

章节来源

  • front/foundation/routing/Router.php:40-56
  • front/foundation/routing/FrontResolver.php:52-105

中间件机制

  • CSRF 中间件:
    • 一次性令牌路由映射(注册、登录、找回密码、留言、分销申请、咨询等)。
    • GET 链接也校验的场景(预约取消、商家处理、余额扣款、登出等)。
    • 失败时抛出 DomainException,提示页面过期并跳转首页。
  • 用户认证中间件:
    • 配置文件 front/init/middleware.php 声明各模块的 auth_modes(public/optional/required),work_required 子策略。
    • 通过 auth('front') guard 解析登录态,注入上下文。
    • 拒绝未认证:XHR 返回 JSON 401 + jump_url,普通请求重定向到登录页并携带 redirect。
    • 拒绝无权限:重定向到会员中心。
sequenceDiagram
participant Req as "请求"
participant MW as "中间件链"
participant Auth as "UserAuthMiddleware"
participant CSRF as "CsrfMiddleware"
participant Ctrl as "控制器"
Req->>MW : 进入中间件
MW->>Auth : 检查登录态根据 auth_modes
alt 未认证
Auth-->>Req : 重定向登录或返回 401 JSON
else 已认证
MW->>CSRF : 校验 CSRF 令牌
alt 校验失败
CSRF-->>Req : 提示页面过期并跳转
else 校验通过
MW->>Ctrl : 进入控制器
end
end

图表来源

  • front/middleware/UserAuthMiddleware.php:26-98
  • front/middleware/CsrfMiddleware.php:24-95
  • front/init/middleware.php:18-131

章节来源

  • front/middleware/CsrfMiddleware.php:24-95
  • front/middleware/UserAuthMiddleware.php:26-98
  • front/init/middleware.php:18-131

控制器与服务交互(以首页为例)

  • IndexController 通过构造函数注入 IndexService、NavigationBuilder、SeoResolver。
  • index() 方法调用服务构建首页数据,并通过 BaseController::view 返回视图,同时注入 SEO 与导航数据。
  • layoutVars() 注入 keywords、description、导航列表等布局变量。
classDiagram
class IndexController {
-indexService : IndexService
-nav : NavigationBuilder
-seo : SeoResolver
+__construct(indexService, nav, seo)
+index() Response
#layoutVars() array
}
class BaseController {
+view(template, data, statusCode) ViewResponse
+respond(request, redirectUrl, data, message) Response
#layoutVars() array
}
IndexController --|> BaseController
IndexController --> IndexService : "调用"
IndexController --> NavigationBuilder : "获取导航"
IndexController --> SeoResolver : "SEO 信息"

图表来源

  • front/controller/index/IndexController.php:30-90
  • front/controller/BaseController.php:37-133

章节来源

  • front/controller/index/IndexController.php:30-90
  • front/controller/BaseController.php:37-133

配置与 URL 风格

  • config/config.php:数据库连接、表前缀、字符集、系统标识、目录常量、应用密钥、调试标志。
  • config/route.php:定义 page/column/simple 三类 URL 风格规则,支持短地址模块、分页段、分类别名、详情 ID/slug 等模式。

章节来源

  • config/config.php:15-52
  • config/route.php:32-355

依赖关系分析

  • 入口依赖前台 Router 与 Init,Init 依赖容器、Provider、Site/System Bootstrap、视图引擎、语言与模块。
  • FrontResolver 依赖 PrettyRouteMatcher、MethodResolver、ThemeExtensionLoader、MiddlewareRegistry。
  • 中间件依赖抽象基类与前端配置(auth_modes),UserAuthMiddleware 依赖 auth('front') guard。
  • 控制器依赖服务与 SEO/导航构建器,服务依赖模型与外部资源。
graph LR
Entry["入口 index.php"] --> Init["Init"]
Entry --> Router["Router"]
Router --> Resolver["FrontResolver"]
Resolver --> MWReg["MiddlewareRegistry"]
MWReg --> MW1["SecurityHeaders"]
MWReg --> MW2["TrustProxy"]
MWReg --> MW3["Throttle"]
MWReg --> MW4["UserAuth"]
MWReg --> MW5["Csrf"]
Resolver --> Controller["控制器"]
Controller --> Service["服务"]
Service --> Model["模型"]

图表来源

  • index.php:16-44
  • front/foundation/routing/FrontResolver.php:174-199
  • front/middleware/UserAuthMiddleware.php:26-98
  • front/middleware/CsrfMiddleware.php:24-95

章节来源

  • index.php:16-44
  • front/foundation/routing/FrontResolver.php:174-199
  • front/middleware/UserAuthMiddleware.php:26-98
  • front/middleware/CsrfMiddleware.php:24-95

性能考虑

  • 视图引擎编译缓存:模板编译目录位于 storage/cache/template/front,减少重复编译开销。
  • 中间件按需入栈:user_auth 仅在 features.user 开启时加入默认栈,避免不必要的鉴权开销。
  • 异步兜底:支付对账抽签在 shutdown 钩子中执行,不影响主请求输出。
  • 静态令牌复用:匿名表单使用一次性令牌,登录会员使用静态令牌,降低令牌管理成本。
  • URL 风格优化:合理配置 URL 风格可减少解析复杂度,提升路由匹配效率。

故障排查指南

  • 未匹配路由:FrontResolver 记录警告日志,返回 page_wrong 提示。检查 URL 风格与路由声明。
  • CSRF 失败:CsrfMiddleware 抛出 DomainException,提示页面过期并跳转首页。检查表单 token 与会话有效期。
  • 未认证:UserAuthMiddleware 根据 from=js 返回 JSON 401 或重定向登录页。检查 session 与登录态恢复。
  • 站点关闭:Init::checkSiteClosed 直接输出维护页。检查 site.site_closed 配置。
  • 异常处理:入口统一捕获并输出 HTML/JSON 错误页。检查 site.debug 与 Accept 头协商。

章节来源

  • front/foundation/routing/FrontResolver.php:58-66
  • front/middleware/CsrfMiddleware.php:86-95
  • front/middleware/UserAuthMiddleware.php:77-98
  • front/init/Init.php:548-557
  • index.php:46-75

结论

DouPHP 前台采用清晰的分层与声明式中间件机制,入口轻量、路由解析集中、控制器职责单一、服务封装业务、模型专注数据访问。通过 Init 完成站点初始化与全局变量注入,FrontResolver 统一装配中间件链与主题扩展,确保安全性与可扩展性。结合灵活的 URL 风格配置与完善的异常处理,前台具备良好的可维护性与扩展性。

附录:扩展与自定义开发指南

  • 新增模块路由:
    • 在 front/route/*.php 声明路由条目(controller FQCN、动作、参数)。
    • 在 front/init/middleware.php 的 auth_modes 中登记该模块的鉴权模式(public/optional/required)。
  • 自定义中间件:
    • 在 front/middleware/* 创建中间件类,继承相应抽象基类。
    • 在 FrontResolver 的 composeMiddlewares 中注册别名或使用路由级 mw_without/mw_append 进行细化。
  • 控制器扩展:
    • 继承 BaseController,实现 view/respond/layoutVars,遵循 JSON/重定向分流约定。
    • 通过依赖注入获取服务与 SEO/导航构建器。
  • 服务与模型:
    • 在 front/service/ 与 front/model/ 按模块组织,保持高内聚低耦合。
    • 使用 DB 门面与 ORM 进行数据访问,避免直接 SQL 拼接。
  • 主题与视图:
    • 在 theme/* 下创建或修改模板,利用 Init 注入的全局变量(如 dou、site、lang、token 等)。
    • 使用 BaseController::view 返回 ViewResponse,确保布局变量合并。
  • 配置与风格:
    • 在 config/route.php 调整 URL 风格规则,适配不同场景。
    • 在 config/config.php 调整应用密钥、调试标志等关键配置。
添加日期:2026-10-05