根本原因是未显式渲染$errors和old(),导致验证失败后页面不显示错误、数据丢失、控制器未执行;需在Blade中用@error输出错误、用old()回填值,并确保FormRequest的rules()返回array、authorize()返回true。

验证失败时 Laravel 默认跳转回上一页,但页面不显示错误、数据不保留、控制器方法没执行——根本不是“没处理”,而是你没显式渲染 $errors,也没用 old() 拿回输入值。
表单提交后空白页或跳回 show 方法?检查验证是否静默失败
这是最常见的假象:你以为表单提交进了 update 方法,其实根本没进去。原因往往是自定义 Form Request(如 UpdateUserRequest)里写了 email、password 等字段规则,但前端只传了 name,验证失败后 Laravel 自动 back(),而上一个 GET 请求是 /user/1,于是又走了一遍隐式模型绑定,调用了 show()。
- 临时注释掉 Form Request 中非表单字段的规则(比如把
'email' => 'required'注释掉),再提交,看能否进到update() - 在
App\Exceptions\Handler.php的register()里加日志:\Log::error('Validation failed:', $e->errors());,然后查storage/logs/laravel.log - 别依赖 dd() 在控制器里断点——验证失败时控制器方法压根不会执行
Blade 模板里不写 @error 就等于没验证
Laravel 不会自动把错误塞进视图变量,$errors 是个 MessageBag 实例,必须手动调用才可见。
- 每个输入框下方必须配
@error('email'){{ $message }}@enderror,不能只靠 CSS 类或 JS 提示 - 输入框的 value 要用
{{ old('email') }},否则用户填错后刷新,所有内容全丢 - 如果用了
redirect()->back()->withInput()手动跳转,必须同时链式调用withErrors($validator),否则$errors为空
Form Request 的 rules() 必须返回 array 类型
PHP 8.1+ 对返回类型更严格,rules() 方法漏写类型声明会导致白屏或 500 错误。
- 正确写法:
public function rules(): array,不是public function rules() -
authorize()必须返回true,否则直接 403,连验证都不跑 - 规则里想拒绝空字符串(比如用户只输空格),不能只用
required|string,得加filled:'name' => ['required', 'string', 'filled', 'max:255'] - 规则若依赖当前用户(如“只能改自己的文章”),别在
rules()里写auth()->id()—— 此时认证可能未完成,应改用withValidator()钩子
AJAX 提交时后端不返回 JSON 错误?验证失败默认跳转会破坏流程
用 axios 或 fetch 提交表单时,Laravel 默认的验证失败行为是重定向,这会让 AJAX 收到 302 响应而非 JSON,前端无法解析错误。
- 确保控制器方法接收的是
Request或 Form Request,且没手动 catchValidationException - 不要在 AJAX 场景下用
$request->validate()—— 它对非 AJAX 请求抛异常触发重定向;改用Validator::make()手动判断:if ($validator->fails()) { return response()->json(['errors' => $validator->errors()], 422); } - 前端需检查 HTTP 状态码 422,并读取
response.data.errors渲染提示,而不是只看response.data.msg
最易被忽略的一点:验证规则写错格式,比如 'mimes: jpeg,jpg,png' 里多了一个空格,Laravel 就会静默跳过该规则,导致本该拦截的文件上传成功——这种问题不会报错,但业务逻辑已失控。


















