@Validate 注解不生效的根本原因有三:未配置 ValidationMiddleware 中间件、未注册 ValidationExceptionHandler 异常处理器、规则字段名与实际传参位置不匹配;它仅校验 query/body/form,不校验路径参数,中文提示需发布并编辑语言包文件。

@Validate 注解不是开箱即用的,缺中间件或异常处理器,它就完全不生效
为什么加了 @Validate 却没拦住非法参数?
常见现象是请求照常进控制器、返回 500 而非 422,或者压根不校验。根本原因只有三个:
-
config/autoload/middlewares.php里没给httpserver 配置\Hyperf\Validation\Middleware\ValidationMiddleware::class -
config/autoload/exceptions.php没注册\Hyperf\Validation\ValidationExceptionHandler::class,导致ValidationException被全局兜底成 500 - 规则字段名和实际传参位置不匹配:比如 POST 是 JSON,但规则写了
username,而实际 body 是{"user_name": "xxx"};或误把路径参数{id}当作 body 字段写进@Validate
@Validate 只校验 query/body/form,不碰路由参数
它默认只处理三类输入:
-
query:URL 查询字符串,如?page=1&limit=10 -
body:JSON 请求体(Content-Type: application/json) -
form:表单提交(Content-Type: application/x-www-form-urlencoded或multipart/form-data)
但 /users/{id} 这种路径参数,@Validate 完全无视。想校验它,得手动在控制器里取 $request->route()->parameters(),再调 validator()->make();或者用自定义 AOP 切面 + 新注解(比如 @ValidatePath)补足。
规则写法和中文提示怎么配?
规则支持两种格式,但行为有差异:
- 字符串写法:
"email" => "required|email",简洁但难复用、难调试 - 数组写法:
"email" => [new \Hyperf\Validation\Rule\Email(), 'required'],可调用Rule类方法,也方便动态拼接
错误信息默认英文。要中文提示,必须做两件事:
- 执行
php bin/hyperf.php vendor:publish --tag=validation发布语言文件 - 修改
storage/languages/zh_CN/validation.php,补充对应规则的提示文案,比如'required' => ':attribute 不能为空'
SwaggerRequest 和 @Validate 能混用吗?
能,但别指望自动合并。SwaggerRequest 是另一套机制:它从 @QueryParameter、@JsonContent、@MediaType 这些 Swagger 注解里提取规则,通过 ValidationCollector 动态组装 rules() 方法。它和 @Validate 互不感知——一个走中间件链,一个走 FormRequest 生命周期。如果你同时用了两者,得自己确保规则一致,否则文档和实际校验行为会脱节。更稳妥的做法是选其一并贯彻到底,避免维护两套规则。
最容易被忽略的是:路由参数校验必须手动介入,@Validate 的“自动”二字,只覆盖它明确声明的那三类输入源;还有,中文提示不是改个配置就行,必须发布语言包并真实编辑 zh_CN/validation.php 文件,否则还是英文。


















