FormRequest 不会自动运行,必须显式注入控制器参数类型;authorize() 默认返回 false 导致 403 拦截;手动调用 validate() 会绕过生命周期钩子;required_if 和自定义消息键名易出错;其核心价值在于整合验证、授权、预处理与错误定制。

FormRequest 不是自动运行的,必须显式注入控制器参数
很多人写完 StorePostRequest 就以为验证会自动触发,结果表单提交后 rules() 完全没执行。根本原因:Laravel 不会扫描所有 FormRequest 类并“自动启用”,它只在控制器方法参数中**明确类型提示时才加载并运行该类**。
- ✅ 正确写法:
public function store(StorePostRequest $request) - ❌ 错误写法:
public function store(Request $request)或public function store($request) - ⚠️ 即使类存在、
rules()写得再全,只要参数不是具体 FormRequest 类型,Laravel 就当它不存在
authorize() 默认返回 false,请求直接 403 拦截
authorize() 方法默认实现就是 return false;,这不是占位符,而是真实生效的拦截逻辑。一旦返回 false,请求连验证环节都不会进,直接返回 403 —— 你甚至看不到验证错误,日志里也查不到规则校验痕迹。
- 必须显式改成
return true;,或按业务逻辑判断(如return $this->user()->can('create', Post::class);) - 若暂时不想做权限控制,就写死
return true;,别留空或注释掉 - 注意:Laravel 5.5 不支持
authorize()中使用$this->user()以外的 Eloquent 关系,避免 N+1 或未初始化报错
手动调用 $request->validate() 会绕过整个生命周期
哪怕参数类型正确、authorize() 返回 true,只要你在控制器里写了 $request->validate(),就会跳过 prepareForValidation()、withValidator()、自定义消息绑定等全部钩子——等于把 FormRequest 当成了普通 Request 使用。
- ✅ 正确姿势:依赖 Laravel 自动验证,方法体内直接用
$request->validated()取数据 - ❌ 常见翻车:
public function store(StorePostRequest $request) { $request->validate(); ... }—— 多此一举且破坏流程 - ? 如果真需要动态加规则,应在
rules()方法里根据$this->input('xxx')判断,而不是中途打断流程
required_if 和错误消息键名是高频翻车点
这两个地方不报错、不抛异常,但行为完全不符合预期,排查起来最耗时间。
-
required_if:status,active对"status": " active "(带空格)失效 → 必须配'status' => 'required|trim|string' -
required_if:is_paid,true在前端传"true"字符串时失效 → 改成required_if:is_paid,1或 Laravel 9+ 的required_if:is_paid,==,1 - 自定义消息必须严格匹配
'email.required' => '邮箱不能为空',写成'required' => '不能为空'会导致所有字段共用一条提示,且$errors->first('email')取不到
真正容易被忽略的是:FormRequest 的价值不在“多写一个类”,而在于把验证、授权、预处理、错误定制这四件事绑在一个可测试、可复用、可版本管理的单元里——漏掉任意一环,它就退化成一堆难以维护的散装规则。


















