@Validate注解需同时启用ValidationMiddleware中间件和ValidationExceptionHandler异常处理器才生效,否则无效;它仅校验query、body、form参数,不校验路由路径参数;规则支持字符串和数组两种写法,后者可调用Rule类方法;错误信息默认英文,需发布语言文件并修改storage/languages/zh_CN/validation.php实现中文提示。

Hyperf 里用 @Validate 注解做参数校验,确实能自动拦截并返回 422 错误,但前提是必须配对启用 ValidationMiddleware 中间件和 ValidationExceptionHandler 异常处理器,缺一不可——否则注解形同虚设,请求直接透传进控制器。
为什么 @Validate 注解没生效?
常见现象是加了注解但参数乱传也不报错,或者报错是 500 而非标准的 422 JSON 响应。根本原因通常有三个:
-
config/autoload/middlewares.php里没给httpserver 配\Hyperf\Validation\Middleware\ValidationMiddleware::class -
config/autoload/exceptions.php没注册\Hyperf\Validation\ValidationExceptionHandler::class,导致ValidationException被上层兜底成 500 - 规则里写的字段名和实际请求参数不匹配(比如 POST body 是 JSON,但规则按 form 表单字段写;或路由参数
{id}被当成 body 字段校验)
@Validate 支持哪些参数位置?
它默认只校验 query(URL 查询参数)、body(JSON 或表单提交体)和 form(application/x-www-form-urlencoded),**不校验路由路径参数(如 /users/{id} 中的 id)**。
如果你需要校验路径参数,得手动在控制器里取 $request->route()->parameters() 再调用 validator()->make(),或者用自定义 AOP 切面 + 注解(如 @ValidateParams)补足。
示例:以下规则只对 POST /users 的 JSON body 生效:
#[Validate([
'name' => 'required|string|min:2',
'email' => 'required|email',
])]
规则字符串和数组写法差异在哪?
规则支持两种写法,但行为不同:
- 字符串形式(如
'email'=>'required|email|unique:users,email'):解析快,适合简单规则,但无法动态拼接或复用逻辑 - 数组形式(如
'phone'=>['required','string',Rule::regex('/^1[3-9]\d{9}$/')]):支持调用Rule类方法、闭包、运行时变量,适合手机号正则、条件性必填等复杂场景
注意:数组写法里不能混用字符串规则(如 'required|email'),必须拆成独立数组项,否则会跳过校验。
验证失败时错误信息怎么控制?
默认返回英文提示,要中文需两步:
- 执行
php bin/hyperf.php vendor:publish hyperf/validation发布语言文件到storage/languages/zh_CN/validation.php - 在验证器类(
FormRequest)里重写messages()方法,键名为"字段名.规则名",例如'email.required' => '邮箱不能为空'
如果只用 @Validate 注解,就只能靠改语言文件全局生效;想 per-request 定制,必须切到 FormRequest 类方式。
真正容易被忽略的是:路由参数永远不在 @Validate 覆盖范围内,哪怕你写了 'id'=>'required|integer',只要它来自路径,就不会被触发——这点在写 RESTful 接口时极易踩坑。


















