通过Laravel中间件传递Session数据到视图时变量未定义问题求解
问题核心原因
- 中间件执行逻辑顺序错误
你当前在handle方法中先执行了$response = $next($request);,这行代码会直接完成后续的路由解析、控制器逻辑执行、视图渲染全流程,你在视图渲染完成后才执行View::share,自然不会生效,渲染视图时变量还未被共享。 - 中间件注册位置错误
你将中间件注册到了全局$middleware数组中,Laravel的Session初始化是在web中间件组的Illuminate\Session\Middleware\StartSession中完成的,全局中间件执行时Session还未启动,无法正确读取到Session中的购物车数据。
修正方案
第一步:调整中间件执行顺序
将购物车逻辑放在$next($request)之前执行,修正后的中间件代码如下:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\View; use App\Models\Item; class GetCart { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle(Request $request, Closure $next) { // 先执行购物车逻辑,共享变量 $items = Item::all(); $cartItems = []; for($i=0; $i < count($items); $i++){ if(null !== Session::get('cartItem'.$i)){ $item = Session::get('cartItem'.$i); array_push($cartItems, $item); } }; $totalNum = 0; for($i=0; $i < count($cartItems); $i++){ if(isset($cartItems[$i])){ $totalNum += $cartItems[$i]['quantity']; } } View::share('cartItems', $cartItems); View::share('totalNum', $totalNum); // 最后执行后续请求处理、视图渲染流程 return $next($request); } }
第二步:调整中间件注册位置
删掉全局$middleware数组中的中间件注册,改到$middlewareGroups的web组中,且必须放在StartSession中间件之后:
protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \App\Http\Middleware\GetCart::class, // 放在StartSession之后注册 \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'api' => [ // ... ], ];
可选优化
你当前遍历全量商品匹配Session的逻辑性能较低,可以直接将购物车数据存在Session的同一个数组字段cart中,不需要每个商品单独存为cartItem+x的格式,后续读取直接拿Session::get('cart', [])即可,无需遍历全量商品。
内容的提问来源于stack exchange,提问作者Clay Raymond
相关产品推荐
相关产品推荐

