Laravel表单验证必须用FormRequest类,因$request->validate()仅适用于简单场景且不触发其生命周期;若未显式注入、authorize()返回false或字段名不匹配,rules()将不生效。

直接用 $request->validate() 最快,但只适合简单场景;复杂表单必须用 FormRequest 类,否则规则不生效、错误消息对不上、嵌套字段验证直接失效。
为什么 $request->validate() 有时不报错也不验证?
它只在 POST/PUT/PATCH 请求中触发,且依赖 CSRF Token 存在。如果表单漏了 @csrf,中间件会先拦截并返回 419 错误,根本到不了验证这步。
- API 请求(
Content-Type: application/json)下,验证失败会直接返回 JSON,而不是重定向回表单 - 手动调用
$request->validate()会绕过FormRequest的生命周期,withValidator()和prepareForValidation()都不会执行 - 字段名大小写不一致(比如前端传
userEmail,规则里写email)会导致该字段完全跳过验证
FormRequest 类的 rules() 不生效?先检查这三件事
不是规则写错了,而是 Laravel 根本没跑这个类。
- 控制器方法参数里没写类型提示,比如
public function store(StorePostRequest $request)—— 写成Request $request就等于没用 -
authorize()方法返回false(默认值),请求会被直接拒绝,连验证都不走 - 规则数组里字段名和实际提交的键名不一致,比如前端发
profile[nickname],规则却写'profile.nickname' => 'required',得改成'profile.nickname' => 'required'并确保profile字段本身声明为'profile' => 'array'
嵌套字段(如 addresses[0][city])怎么验证才不崩?
Laravel 不认方括号语法,必须转成点号路径,且数组字段必须显式声明类型,否则 .* 通配符无效。
- HTML 表单字段名必须是
addresses[0][city],不能写成addresses.0.city或addresses_0_city - 验证规则写成
'addresses.*.city' => 'required|string',但前提是同时存在'addresses' => 'array' - 如果漏掉
addresses => array,Laravel 会把整个addresses当字符串处理,报错Array to string conversion - 前端用 JS 动态增删行时,必须实时更新
name属性索引,比如新增第 3 行就得设为addresses[2][zip],不能留空或重复
多个提交按钮(如“保存”“预览”“删除”)怎么区分?
别靠 JS 拦截或隐藏字段,直接用原生 HTML 的 button 提交机制。
- 每个按钮加相同
name="action",不同value:<button type="submit" name="action" value="save">保存</button> - 后端用
$request->action或$request->input('action')判断操作意图 - 注意:只有被点击的按钮的
name/value才会上送,未点击的不会出现在请求数据中 - 如果按钮是
<input type="image">或带formaction,行为可能不一致,统一用button[type=submit]最稳
最常被忽略的是嵌套字段的 array 规则声明和 FormRequest 的注入方式——这两处一错,整个验证链就断了,但错误现象往往只是“没反应”或“报错位置不对”,很难一眼定位。


















