Laravel重定向后ViewErrorBag为空、验证错误不显示问题
Laravel 8 重定向后ViewErrorBag为空的排查与解决方案
问题核心链路说明
Laravel的验证错误传递是固定流程:重定向时withErrors()会把验证错误信息闪存到当前会话的errors专属键下 → 跳转到目标路由时,ShareErrorsFromSession中间件会读取session里的错误内容,实例化为ViewErrorBag对象共享给所有Blade模板 → 模板里的全局$errors变量才能正常读取错误。出现#bags: []的空结果,本质是这条链路上某一环中断了。
可落地排查步骤
- 检查
/prox_login所属路由的中间件组
哪怕全局配置了StartSession中间件,如果该路由被归类到api中间件组下,就不会加载web组专属的会话、错误共享逻辑,自然读不到之前闪存的错误:- 确认路由定义在
routes/web.php中,而非routes/api.php - 检查路由是否手动追加了
->middleware('api')这类会覆盖web组默认配置的代码,确保路由走默认web中间件组
- 确认路由定义在
- 校验web中间件的执行顺序
打开app/Http/Kernel.php,查看web组内StartSession和ShareErrorsFromSession的顺序,必须保证StartSession::class排在ShareErrorsFromSession::class前面。顺序颠倒会导致读取session时尚未完成会话初始化,就算闪存了错误也读不出来,最终生成空的ViewErrorBag。 - 验证会话读写功能是否正常
在重定向逻辑中临时追加一个测试闪存值:
临时把if ($validator->fails()) { return redirect('/prox_login') ->withErrors($validator) ->withInput() ->with('session_test', 'test_content'); }/prox_login路由改成匿名闭包输出全量session内容:
根据输出结果定位问题:Route::get('/prox_login', function() { dd(session()->all()); });- 如果输出的session数组完全看不到之前写入的
session_test、或者出现session读取报错,说明会话本身在该路由下失效,需要检查config/session.php的存储配置、APP_KEY是否和当前环境匹配(升级Laravel 8后如果更换了APP_KEY,原有加密的session会完全读不出来;如果使用文件驱动存储session,还要检查storage目录下session文件夹的写入权限) - 如果session数组里能看到
session_test,但看不到errors键,说明withErrors()的逻辑被项目自定义实现覆盖,没有正常把错误写入session - 如果session数组里能看到
errors键,但视图中的$errors依然是空的,说明ShareErrorsFromSession中间件没有正确加载执行
- 如果输出的session数组完全看不到之前写入的
- 特殊场景排查
如果项目中对重定向类做了全局自定义宏、覆盖了默认的Redirector实现,需要检查自定义的withErrors()方法是否把错误写入了session默认的errors键,写入其他键会导致中间件读不到对应内容。
内容的提问来源于stack exchange,提问作者Maxwell Newberry
相关产品推荐
相关产品推荐

