加载中…
文档目录
路由配置

简介

本文件面向 DouPHP 的路由配置系统,系统性说明前台、后台、API 三个端的路由管理机制与实现细节。重点覆盖:

  • 路由风格规则(config/route.php)的结构与作用
  • 各端 Router 与 Resolver 的职责边界与差异
  • 声明式路由定义(front/admin/api 下的 route/*.php)
  • URL 重写、参数绑定、中间件装配与错误处理
  • 路由缓存与性能优化策略
  • 自定义路由开发与常见问题解决方案

项目结构

DouPHP 将“路由”拆分为三层:

  • 配置层:统一的路由风格规则(config/route.php),用于前台栏目类模块的 URL 风格生成
  • 调度层:各端 Router(front/admin/api)负责入口分发
  • 解析层:各端 Resolver(FrontResolver/AdminResolver/ApiResolver)负责把请求映射到控制器与方法,并组装中间件链
graph TB
A["前端入口"] --> B["FrontResolver<br/>解析前台URL"]
C["后台入口"] --> D["AdminResolver<br/>解析后台URL"]
E["API入口"] --> F["ApiResolver<br/>解析API URL"]
B --> G["Dispatcher<br/>执行控制器方法"]
D --> G
F --> G
H["路由风格规则<br/>config/route.php"] -.-> B

核心组件

  • 前台 Router:薄壳调度器,调用 FrontResolver 产出 DispatchPlan,未命中返回前台 404 提示页
  • 后台 Router:薄壳调度器,调用 AdminResolver,未命中或方法不允许时重定向到后台首页并携带错误提示
  • API Router:薄壳调度器,调用 ApiResolver,未命中或方法不允许时返回 JSON 404/405
  • FrontResolver:基于 PrettyRouteMatcher 匹配前台 declared 条目,装配中间件、视图上下文与主题扩展
  • AdminResolver:基于 BackendDeclaredMatcher 匹配后台 declared 条目,装配默认中间件栈与表单目标
  • ApiResolver:基于 BackendDeclaredMatcher 匹配 API declared 条目,装配默认中间件栈(含限流与可选用户认证)

架构总览

三个端共享同一套“声明式路由 + 中间件分层”的设计思想,但侧重点不同:

  • 前台:强调 SEO 友好的 URL 风格(通过 config/route.php 的风格规则),以及主题扩展与表单目标自动装配
  • 后台:强调权限与安全(CSRF、鉴权、授权、工作区),以及资源型 CRUD 的便捷声明
  • API:强调无状态、限流、JSON 响应与严格的 HTTP 方法约束
sequenceDiagram
participant U as "客户端"
participant R as "各端Router"
participant Res as "各端Resolver"
participant M as "中间件链"
participant C as "控制器方法"
U->>R : 发起HTTP请求
R->>Res : resolve(request, container)
Res-->>R : DispatchPlan(控制器FQCN, 方法名, 参数, 中间件)
R->>M : 按顺序执行中间件
M->>C : 调用控制器方法
C-->>M : 返回结果
M-->>R : 最终Response
R-->>U : 发送响应

详细组件分析

前台路由(FrontResolver)

  • 输入:已剥离语言前缀的请求路由字符串
  • 匹配:使用 PrettyRouteMatcher 对前台 declared 条目进行匹配(包含系统内置端点与业务端点)
  • 输出:DispatchPlan(控制器FQCN、方法名、路径参数、中间件链)
  • 附加能力:
    • 会员模块开关保护(features.user)
    • 统一中间件栈:安全头、可信代理、限流、可选用户认证、CSRF
    • 表单目标自动装配(create/edit 动作自动设置 form_action 与 _method)
    • 主题扩展加载(ThemeExtensionLoader)
flowchart TD
Start(["进入 FrontResolver.resolve"]) --> ReadRoute["读取请求路由字符串"]
ReadRoute --> Match["PrettyRouteMatcher.normalize()"]
Match --> |未匹配| NotFound["返回 notFound 计划"]
Match --> |命中| BuildPlan["组装模块/动作/参数/FQCN"]
BuildPlan --> Guard{"是否启用用户模块?"}
Guard --> |否| MW["组装中间件链"]
Guard --> |是| MW
MW --> Assign["设置BaseURL/路由信息/视图变量/表单目标/主题扩展"]
Assign --> Return["返回 DispatchPlan"]

后台路由(AdminResolver)

  • 输入:?route=module[/id[/action]] 形式
  • 匹配:BackendDeclaredMatcher 根据 admin/route/*.php 中的 declared 条目匹配(支持 specificity 排序与 HTTP 方法过滤)
  • 输出:DispatchPlan(控制器FQCN、方法名、路径参数、中间件链)
  • 默认中间件栈:安全头、可信代理、鉴权、授权、CSRF、工作区
  • 附加能力:
    • 表单目标自动装配(create/edit)
    • 未命中或方法不允许时,Router 层统一重定向到后台首页并携带错误提示
sequenceDiagram
participant AR as "AdminResolver"
participant BM as "BackendDeclaredMatcher"
participant MR as "MethodResolver"
participant MW as "MiddlewareRegistry"
AR->>BM : match(routeRaw, 'Admin', method)
alt 未命中
BM-->>AR : null
AR-->>AR : 返回 notFound
else 命中
BM-->>AR : {module, action, fqcn, params, entry}
AR->>MR : resolve(action, fqcn)
AR->>MW : compose(defaultAliases, entry)
AR-->>AR : 返回 DispatchPlan
end

API 路由(ApiResolver)

  • 输入:?route=module[/id[/action]] 形式
  • 匹配:BackendDeclaredMatcher 根据 api/route/*.php 中的 declared 条目匹配
  • 输出:DispatchPlan(控制器FQCN、方法名、路径参数、中间件链)
  • 默认中间件栈:安全头、可信代理、限流、可选用户认证(features.user)
  • 错误处理:未命中返回 JSON 404;方法不允许返回 JSON 405(带 Allow 头)
sequenceDiagram
participant UR as "ApiResolver"
participant BM as "BackendDeclaredMatcher"
participant MR as "MethodResolver"
participant MW as "MiddlewareRegistry"
UR->>BM : match(routeRaw, 'Api', method)
alt 未命中
BM-->>UR : null
UR-->>UR : 返回 notFound
else 命中
BM-->>UR : {module, action, fqcn, params, entry}
UR->>MR : resolve(action, fqcn)
UR->>MW : compose(defaultAliases, entry)
UR-->>UR : 返回 DispatchPlan
end

路由风格规则(config/route.php)

  • 目的:为前台栏目类模块(如 product/article/doc)提供可配置的 URL 风格族
  • 结构要点:
    • page:单页面风格(固定加载 page.php)
    • column:栏目模块风格(分类别名/ID/日期归档等组合,支持短地址模块 short_rules)
    • simple:简单模块风格(列表/分组/操作页)
  • 每条规则包含:
    • pattern:URL 模式(支持命名参数、正则、可选段)
    • params:参数默认正则(pattern 内嵌正则优先)
    • target:目标文件名模板(如 {module}_category)
    • module_fixed:固定模块名(当 URL 不含模块段时使用)
    • short_rules:短地址模块专用规则家族(column 风格下,顶级分类别名取代模块名段)
flowchart TD
S["选择风格族"] --> P["遍历规则数组"]
P --> M{"匹配URL?"}
M --> |是| T["生成目标target/参数params"]
M --> |否| N["继续下一条规则"]
T --> End["完成匹配"]
N --> P

声明式路由示例

  • 前台栏目模块:通过 Route::column('product', ProductController::class) 按当前风格展开多条 declared 条目
  • 后台资源路由:Route::resource('product', ProductController::class) 配合 prefix/sub 生成标准 CRUD 路由
  • API 资源路由:Route::resource('product', ProductController::class) 仅暴露 index/show,并通过 group 限定子控制器范围

依赖关系分析

  • Router 与 Resolver 解耦:Router 只负责调度与错误处理,Resolver 专注解析与装配
  • 中间件装配集中化:各 Resolver 通过 MiddlewareRegistry 组装默认栈与路由级细化
  • 声明式路由集中管理:各端 route/*.php 以声明方式注册,便于维护与扫描
  • 前端 JS 路由表:routes_js.php 暴露命名路由清单,供前端构建 URL
graph LR
FR["FrontResolver"] --> MR["MethodResolver"]
FR --> MW["MiddlewareRegistry"]
AR["AdminResolver"] --> MR
AR --> MW
AIR["ApiResolver"] --> MR
AIR --> MW
FR -.-> CFG["config/route.php"]

性能与缓存

  • 路由匹配性能
    • 前台使用 PrettyRouteMatcher 对 declared 条目进行归一化匹配,避免运行时复杂正则回溯
    • 后台/API 使用 BackendDeclaredMatcher 基于 specificity 排序与 HTTP 方法过滤,提升命中率与准确性
  • 中间件装配
    • 默认中间件栈在 Resolver 中一次性组装,减少重复计算
    • 路由级细化(without/append/params)仅在命中条目上生效,降低无关开销
  • 前端路由表
    • routes_js.php 输出 window.__douRouteManifest,供前端静态消费,避免运行时解析
  • 建议
    • 合理拆分路由文件,避免单个 route/*.php 过大
    • 使用命名路由与声明式资源路由,减少手写 pattern 带来的维护成本
    • 开启 URL 重写后,确保服务器配置正确,避免回退到 ?route= 形态导致额外查询

故障排查指南

  • 前台未命中(404)
    • 检查 FrontResolver 日志通道 route,确认路由字符串与语言标识
    • 确认 FrontResolver 中 PrettyRouteMatcher 是否返回 matched
    • 若控制器 FQCN 不存在或类不可用,会返回 notFound
  • 后台未命中或方法不允许
    • 未命中:Router 层重定向到后台首页并携带错误提示
    • 方法不允许:返回 405,并在响应头中附带 Allow 字段
  • API 未命中或方法不允许
    • 未命中:返回 JSON 404
    • 方法不允许:返回 JSON 405,并附带 allow 字段
  • 表单提交异常
    • 确认 create/edit 动作触发了 assignFormTarget,form_action 与 _method 是否正确注入
  • 中间件问题
    • 检查默认中间件栈与路由级 without/append 配置
    • 注意 features.user 开关对用户认证中间件的入栈影响

结论

DouPHP 的路由系统通过“配置层 + 调度层 + 解析层”的分层设计,实现了前台 SEO 友好、后台安全可控、API 简洁高效的三端统一体验。声明式路由与中间件分层让扩展与维护更加清晰,结合前端路由表与 URL 重写,形成完整的端到端路由生态。

附录:最佳实践与自定义开发

最佳实践

  • RESTful API 设计
    • 使用 Route::resource 声明标准 CRUD 接口,仅暴露必要动作(only)
    • 明确 HTTP 方法与资源路径,避免混用 GET/POST
  • URL 规范化
    • 前台栏目模块优先使用 config/route.php 的风格族,保持 URL 一致性与可读性
    • 短地址模块使用 short_rules 精简 URL,同时保留分页与分类语义
  • SEO 优化
    • 使用 slug 与分类别名,避免纯数字 ID 暴露内部结构
    • 开启 URL 重写,确保搜索引擎抓取友好路径
  • 中间件策略
    • 默认栈遵循 secure-by-default,必要时通过 withoutMiddleware 豁免特定端点(如支付回调)
    • 用户认证与限流按需开启,避免对匿名接口造成不必要限制

自定义路由开发指南

  • 新增前台栏目模块
    • 在 front/route/{module}.php 中使用 Route::column('module', Controller::class)
    • 在 config/route.php 中选择合适的风格族,必要时添加新规则
  • 新增后台资源路由
    • 在 admin/route/{module}.php 中使用 Route::resource('module', Controller::class)
    • 如需子控制器,使用 prefix/sub 组合
  • 新增 API 资源路由
    • 在 api/route/{module}.php 中使用 Route::resource('module', Controller::class)
    • 通过 only/get/post 精确控制暴露的动作
  • 前端路由表同步
    • 确保 routes_js.php 暴露的端点被前端消费,避免硬编码 URL
添加日期:2026-10-05