Laravel5.2 某些版本改动导致 session flash 用不了的坑
楼主现在项目使用的是 laravel 5.2.31版本 , 被一个小坑坑了两三个小时
简单来说 , 我在控制器某个表单提交的方法中使用validator , 跳转页面时
back()->withInput()->withError($validator);
发现withInput 和 withError 不灵了 . 在页面中打印session的数据
$request->session()->all()
看到$session->flash() 方法该存入的数据都没有了 , 真是奇怪
为了解决这个问题探索了各种方法 . 是不是validator不对?是不是控制器自带的validate()方法有问题? 是不是session 的驱动有问题? 又搜google和stackoverflow , 浪费了不少时间 .
后来在测试路由中建了个表单页和提交页 , 发现session 的flash 都是好用的 . 只是在控制器里不能用 . 这就联想到了是不是中间件出了问题 . 在系统自带的StartSession 中加入了一行代码打印$session->all() , 又意外地看到session的结果被打印了两次.
这就找到问题所在了 . 中间件 Illuminate\Session\Middleware\StartSession 被启动了两次 .
laravel运行中间件 , 是由HttpKernel先加载路由 , 然后把中间件的栈用\Illuminate\Pipelin\Pipeline 解析成一个闭包嵌套构成的管道 . 如果一个中间件被启动了两次 , 那肯定是路由调用了它两次.
最后发现问题所在了 . laravel 5.2 在某个版本升级中, 修改了 RouteServiceProvider , 更改了一个方法
public function map(Router $router)
{
$this->mapWebRoutes($router);
//
}
protected function mapWebRoutes(Router $router)
{
$router->group([
'namespace' => $this->namespace, 'middleware' => 'web',
], function ($router) {
require app_path('Http/webRoutes.php');
});
}
这是laravel给开发者做的一个示范 , 让我们知道http和api , 以及其它端可以加载不同的route文件来启动 .
这意味着laravel 可以有多个不同的bootstrap , 启动多个不同的kernel . 比如有HttpKernel , 还可以有RPCKernel或其它APIKernel , 每个Kernel 如同现在的Http 文件夹一样 ,拥有独立的路由文件 , 控制器 和中间件 . 这样就可以做到多端访问的资源隔离.
然而这个改动在RouteServiceProviders 里就把 'web' 中间件加载了 , 我从前面的版本过来 , 并不知道有这么一出, 按习惯在route.php 中仍然写的是
/**
* 注册前端通用路由
*/
Route::group([
'middleware' => 'web',
'as' => 'frontend::',
'domain' => config('domain.frontend'),
'namespace' => 'Frontend',
],$frontendCommonRoutes);
这样 'web' 组的中间件就加载了两次 , 第二次加载的StartSession 把flash 的内容清空了 .
这就是出错的原因 , 希望对其它在5.2.x 版本升级中遇到这个坑的朋友有帮助
:+1: 不错,商业项目在用 5.2?
@xyzget @NauxLiu
我的5.5 遇到了flash的问题 https://stackoverflow.com/questions/512710...