LaravelAPI怎么验证请求_Laravel使用验证器校验参数【指南】
LaravelAPI验证常见陷阱:rules()返回空数组将跳过校验;validated()仅返回声明字段,safe()->all()返回所有通过字段;自定义错误消息键名需加引号避免语法错误;API路由验证失败默认返回HTML而非JSON,需显式指定JSON响应。
Lara vel 的 API 验证,看着简单,但真正用起来,暗坑一个接一个。有些问题你平时未必留意,等上线了才发现:校验没走通、返回格式不对、数组键名报错……今天就来拆解几个最容易让人翻车的细节。
验证器类里 rules() 返回空数组会直接跳过校验
不少开发者把验证逻辑写在 FormRequest 里,改着改着,一个不注意就把 rules() 写成了 return [];,或者条件分支没兜住导致返回空数组。结果请求直接进入控制器,连 422 都不触发——你以为校验了,其实完全没生效。
- 核心原则:
rules()必须返回一个非空数组,哪怕简单到['id' => 'required|integer']都行,空数组等于关掉了校验。 - 如果真有需求动态开关校验,用
withValidator()做拦截,而不是把rules()清空。 - 测试时别只看代码有没有写
validate,最好手动发一个缺失必填字段的请求,看是否真的返回 422 和错误信息。
Lara vel 10+ 的 validated() 和 safe()->all() 行为不同
validated() 只返回你在 rules() 里声明过的字段(比如你写了 'email' => 'required|email',它就只返回 email)。而 safe()->all() 则把所有通过了校验的字段一股脑全吐出来——即使某些字段没在 rules() 里定义,只要没被 only() 限制,也一样会出现在结果里。
- 如果你习惯用
request->validated()['xxx']取值,但实际传了xxx却没在rules()中声明,这里会直接报Undefined array key错误。 - 想要严格按规则来取值,用
validated();想兼容前端传的额外参数(比如埋点字段),用safe()->all()并在业务层自己做字段白名单判断。 - 注意:
safe()从 Lara vel 9.28 才开始稳定,低版本调用它会抛Method does not exist错误,升级时得格外小心。
自定义错误消息写在 messages() 里,但中文键名要加引号
写成 'title.required' => '标题不能为空' 没问题,但如果你偷懒写成 title.required => '标题不能为空'(不加引号),PHP 解析器直接报 ParseError: syntax error,页面都白了。
- 所有含点号、中划线、中文的数组键名,必须用单引号或双引号包裹,这是 PHP 的语法红线。
- 如果用了
trans()来做多语言,一定要确保对应语言文件存在且键名无误,否则前端看到空字符串,既不好排查也不容易定位。 - 批量替换错误消息时,嵌套规则里的通配键名(比如
'tags.*.required')也别忘了加引号,一个疏忽就可能整段代码跑不起来。
API 验证失败默认返回 HTML 页面,不是 JSON
开箱即用的 FormRequest,如果放在 API 路由里且没有显式指定响应格式,Lara vel 依然可能返回重定向或 HTML 错误页——尤其在 web 和 api 中间件组混用的项目里,这个坑最容易踩。
- 首先确认路由写在
routes/api.php里,并且没有被web中间件污染(比如全局绑定了web)。 - 在
App\Exceptions\Handler.php的render()方法里检查是否对ValidationException做了 JSON 包装,没做的话默认会走网页重定向逻辑。 - 最简单的兜底方案:在
FormRequest里显式添加public function response(array $errors) { return response()->json($errors, 422); },保证前端永远收到 JSON 格式的错误。
验证器本身并不复杂,复杂的是那些“看起来跑通了,实际上漏校验”或者“返回格式不对导致前端一直收不到错误”的隐性断点。尤其是跨版本升级后,safe() 和 validated() 的边界特别容易模糊。上线前最好用 Postman 完整跑一遍非法请求,确保每个细节都到位。


































