文档目录
请求验证

简介

本文件面向 DouPHP 后台的请求验证系统,系统性说明表单验证规则的定义与使用、内置与自定义验证器、复合规则、请求对象的数据绑定与类型转换、批量数据验证机制、错误处理与国际化消息、以及性能优化与安全注意事项。文档以代码级实现为依据,提供可视化图示与可操作的开发指引。

项目结构

DouPHP 的后台验证由“请求对象 + 声明式验证器”组成:

  • 请求对象:继承 FormRequest,定义 rules() 与可选的 validationData(),用于场景化校验与白名单字段提取。
  • 验证器:Validator 负责解析规则串、执行校验、抛出异常并返回错误集合(支持收集全部错误)。
  • 语言包:validator_* 键名提供默认错误消息,可按 field.rule 覆盖。
graph TB
Controller["控制器"] --> FR["FormRequest<br/>rules()/validationData()"]
FR --> V["Validator<br/>validate()"]
V --> DB["数据库连接<br/>唯一性/存在性检查"]
V --> Lang["语言包<br/>validator_* / {field}_{rule}"]
V --> Check["Check工具类<br/>格式校验"]

核心组件

  • 表单请求基类 FormRequest
    • 职责:封装场景化校验流程;从 POST 读取数据;按 rules() 白名单过滤输出。
    • 关键点:validated() 内部构造 Validator 并执行 validate();validationData() 可被重写以合并路由/查询参数到校验数据。
  • 声明式验证器 Validator
    • 职责:解析规则串、逐项执行规则、生成错误键、统一抛出 DomainException(支持收集全部错误)。
    • 能力:内置大量规则(必填、长度、数值、邮箱、URL、IP、日期、布尔、唯一性、存在性、确认、正则、枚举、前缀后缀、手机号、密码、非法字符、用户名、别名、身份证、QQ、邮编、JSON、数组、接受、文件/图片/扩展名/大小/尺寸等)。
    • 错误消息优先级:messages[field.rule] > 语言包 {field}{rule} > 语言包 validator{rule} > 开发占位符。

架构总览

请求进入控制器后,通过容器注入的 FormRequest 子类完成校验与白名单提取;随后将已验证数据交给服务层或模型层持久化。

sequenceDiagram
participant C as "控制器"
participant R as "FormRequest子类"
participant V as "Validator"
participant DB as "数据库"
participant L as "语言包"
C->>R : validated()
R->>R : validationData()
R->>V : validate(data, rules)
V->>V : splitRules()/applyRule(...)
V->>DB : unique/exists 检查(必要时)
V->>L : 获取错误消息
V-->>R : 通过或抛出DomainException
R-->>C : 返回白名单数据

详细组件分析

表单请求对象设计模式

  • 数据绑定
    • 默认仅绑定 POST 数据;可通过重写 validationData() 合并路由/查询参数(如 update 场景的 id/user_id)。
  • 类型转换与默认值
    • 在 validationData() 中可使用 request()->integer('id', 0) 等方式进行类型转换与默认值设置,确保 rules() 能正确触发 integer/min_value 等规则。
  • 白名单字段
    • validated() 返回 array_intersect_key($data, $rules),即仅包含 rules() 中定义的字段,天然实现白名单过滤。
  • 场景化规则
    • 通过 scene(store/update)动态增减规则,例如更新时要求 id 必填且为整数。

验证规则体系

  • 内置规则概览
    • 基础:required、required_if、same、different、accepted、array、json
    • 文本:alpha_dash、alpha、alpha_num、max/min/between、starts_with、ends_with、regex/not_regex
    • 数值:numeric、integer、float、price、digits、digits_between、max_value/min_value/between_value
    • 地址与标识:email、url、domain、ip、phone、password、username、admin_account、slug、idcard、qq、postcode
    • 业务:unique、exists、confirmed
    • 文件:file、image、mimes、max_kb、dimensions
  • 规则解析
    • 以 | 分隔,支持带参数的规则(如 max:150、unique:table,field[,excludeField])。
    • 对 regex 规则中的 | 做了保护,避免误拆分。
  • 复合规则
    • 可在同一字段组合多个规则,如 'required|price'、'email|unique:user,email'。
  • 条件规则
    • required_if:field,val1,val2 当其他字段命中指定值时才必填。
  • 自定义规则
    • 通过 messages['field.rule'] 覆盖错误消息;或通过新增规则分支扩展 Validator::applyRule()。

批量数据验证

  • 数组字段
    • 使用 array 规则可校验字段是否为数组;结合 min/max/between 可实现数组长度约束。
  • 动态规则生成
    • 在 rules() 中根据场景或配置动态追加规则(如 slug 是否启用、update 场景追加 id 必填)。
  • 条件验证
    • 使用 required_if 实现基于其他字段的条件必填;配合 same/different 做跨字段一致性校验。
  • 示例参考
    • 商品表单:根据 features.slug 开关决定是否启用 slug 的唯一性校验。
    • 用户表单:update 场景下 password 留空表示不修改,confirmed 在空值时短路。

上传文件验证

  • file/image/mimes/max_kb/dimensions
    • 自动识别 UploadedFile 实例或从 $_FILES 解析。
    • image 会校验扩展名是否在允许列表(回退至文件系统配置)。
    • mimes 支持显式扩展名清单,为空时回退到全局允许扩展名。
    • max_kb 支持传入上限或回退到全局配置。
    • dimensions 支持宽高范围、精确宽高、比例 ratio 等约束。
  • 注意
    • 未提供有效文件时,file/image/mimes/max_kb/dimensions 会短路通过(需在前置 required 控制)。

错误处理与国际化

  • 错误消息优先级
    • 优先使用 messages['field.rule'] 覆盖;其次查找语言包 {field}{rule};再回退到 validator{rule};最后显示开发占位符。
  • 收集全部错误
    • validate(..., collectAll=true) 可聚合所有字段错误并在末尾一次性抛出,便于前端展示完整问题。
  • confirmed 映射
    • confirmed 失败时错误默认映射到 {field}_confirm,便于定位确认输入框。
  • 语言包
    • 通用消息位于 common.lang.php 的 validator_* 键名;可按模块/字段细化。

开发示例指引

  • 创建自定义验证器
    • 在 Validator::applyRule() 新增 case 分支,复用 Check 工具方法或数据库查询。
    • 在语言包添加 validator_{rule} 或按 field.rule 覆盖。
  • 复杂验证场景
    • 使用 required_if/same/different 表达跨字段依赖;使用 unique/exists 进行数据库一致性校验。
  • 国际化消息
    • 在对应语言文件中补充 validator* 或 {module}{field}_{rule} 键值,确保多语言提示。

依赖关系分析

  • 组件耦合
    • FormRequest 依赖 Validator 与 Request(读取 POST/路由参数)、语言包(lang_all)。
    • Validator 依赖数据库连接(唯一性/存在性)、Check 工具(格式校验)、UploadedFile(文件校验)。
  • 外部依赖
    • 数据库:用于 unique/exists 规则。
    • 文件系统配置:用于图片扩展名与最大上传大小回退。
  • 潜在循环依赖
    • 当前结构清晰,无直接循环依赖。
graph LR
FR["FormRequest"] --> V["Validator"]
V --> DB["数据库连接"]
V --> CK["Check工具"]
V --> UF["UploadedFile"]
V --> LG["语言包"]

性能考虑

  • 规则解析优化
    • 不含 regex/not_regex 时走快速路径;含正则时智能保护 | 不被误切分。
  • 数据库访问最小化
    • unique/exists 仅在需要时访问数据库;建议在高并发场景对热点表加索引。
  • 文件校验开销
    • dimensions 会读取图片元信息,建议在必要场景使用,并结合 max_kb 限制大文件。
  • 批量错误收集
    • collectAll=true 会遍历全部规则后再抛错,适合前端一次性展示;高频接口建议首错即抛以减少开销。

故障排查指南

  • 常见问题
    • 规则未生效:确认字段存在于 rules() 中;update 场景需在 validationData() 合并 id/user_id。
    • 唯一性冲突:检查 unique 规则的 table/field/exclude 参数是否正确。
    • 文件校验失败:确认 file/image/mimes/max_kb/dimensions 前置 required 是否合理;检查允许扩展名与文件大小配置。
    • 错误消息不显示:检查 messages['field.rule'] 或语言包键名是否匹配;确认模块名前缀是否影响翻译。
  • 调试建议
    • 使用 collectAll=true 收集全部错误,定位多字段问题。
    • 在日志中记录异常信息与上下文,辅助定位。

结论

DouPHP 后台验证系统通过 FormRequest + Validator 的组合,提供了声明式、可扩展、易用的请求校验能力。借助丰富的内置规则、场景化规则、文件校验与国际化消息机制,开发者可以高效构建健壮的后端入口。遵循本文的性能与安全建议,可进一步提升系统的稳定性与安全性。

附录

  • 常用规则速查
    • 必填与条件:required、required_if
    • 文本与格式:alpha_dash、email、url、domain、ip、date/date_format、boolean、regex
    • 数值与范围:numeric、integer、float、price、digits/digits_between、max/min/between、max_value/min_value/between_value
    • 业务校验:unique、exists、confirmed、same、different、in/not_in、starts_with/ends_with
    • 身份与标识:phone、password、username、admin_account、slug、idcard、qq、postcode
    • 文件:file、image、mimes、max_kb、dimensions
  • 最佳实践
    • 始终在 rules() 中明确白名单字段;敏感字段尽量在后端再次校验。
    • 对外部输入一律视为不可信,结合 XSS/SQL 注入防护策略。
    • 对文件上传严格限制类型与大小,避免恶意文件。
    • 使用 collectAll=false 提升常见接口的响应速度;批量提交时使用 collectAll=true 改善用户体验。
添加日期:2026-10-05