Laravel 5.3 中的控制器构造函数会话更改
发布于 作者 Mohamed Said
在 Laravel 5.2 中,开发人员可以在控制器构造函数中直接与会话进行交互。但是,这在 Laravel 5.3 中发生了改变。
5.3 和 5.2 处理传入请求的不同之处在于,在 5.2 中,请求通过 3 个管道
- 全局中间件管道
- 路由中间件管道
- 控制器中间件管道
默认情况下,全局中间件只包含对维护模式的检查,路由中间件是您在 routes.php 文件中分配给路由的,默认情况下,一个 web 组被分配给所有 web 路由,其中包含几个中间件,包括启动会话的中间件。
最后,Laravel 实例化您的控制器以检查控制器中间件,此时,请求在第一个和第二个管道中完成设置,这就是为什么我们能够在控制器构造函数中使用会话和身份验证的原因,因为请求已准备就绪。
在 5.3 中,请求只通过 2 个管道
- 全局中间件管道
- 路由和控制器中间件在一个栈中
Laravel 首先收集所有路由特定的中间件,然后通过管道运行请求,并且在收集控制器中间件时,会创建控制器的实例,从而调用构造函数,但是此时请求还没有准备好,这就是您在 5.3 中注意到行为变化的地方。
关于这种改变的原因,如 Taylor 所述
在构造函数中使用会话或身份验证非常糟糕,因为还没有发生任何请求,会话和身份验证本质上与 HTTP 请求绑定在一起。您应该在实际的控制器方法中接收此请求,您可以用多个不同的请求多次调用此方法。通过强制您的控制器在构造函数中解析会话或身份验证信息,您现在强制您的整个控制器忽略实际的传入请求,这在测试等情况下会导致严重的问题。
在 5.3 中的构造函数中使用会话
也许在控制器的构造函数中使用会话变量是一种不好的做法。但是,看起来很多 Laravel 开发人员都在使用这种方法,并将构造函数视为一个内联中间件,他们可以在其中检查用户是否可以访问此控制器中的某些方法。
因此核心团队为这个问题找到了一个解决方案,在升级指南中描述如下
作为替代方案,您可以在控制器的构造函数中直接定义一个基于闭包的中间件。在使用此功能之前,请确保您的应用程序运行的是 Laravel 5.3.4 或更高版本
以下是文档中的示例
<?php namespace App\Http\Controllers; use App\User;use Illuminate\Support\Facades\Auth;use App\Http\Controllers\Controller; class ProjectController extends Controller{ public function __construct() { $this->middleware(function ($request, $next) { $this->projects = Auth::user()->projects; return $next($request); }); }}