我通过检查路由参数在中间件中进行存在检查。 如果检查成功,我将其模型附加到请求,以使其在整个请求周期应用程序的其余部分可用。
// App\Http\Middleware\CheckForExistence.php:
...
public function handle($request, Closure $next)
{
// some checks...
// success
$request->attributes->add([
'company' => $someModel
]);
}
我现在有一个需要的控制器'这些信息有两种方法。所以我的想法是将它添加到控制器的构造中,并将其作为受保护的var添加到整个控制器中:
// App\Http\Controllers\MyController.php
<?php
use Illuminate\Http\Request;
class MyController extends Controller
{
protected $company;
public function __construct(Request $request)
{
$this->company = $request->attributes->get('company');
}
public function index()
{
dd($this->company); // returns null
}
}
此控制器index()
返回null而不是give模型。
如果我将index()
方法更改为:
public function index(Request $request)
{
return $request->attributes->get('company');
}
返回模型;正如所料。
为什么会这样?看起来中间件在构造控制器时没有运行....有没有办法绕过它? 或者我在这里错过了明显的......
我当然可以在每种方法中重复自己;但那不是很干;)
答案 0 :(得分:1)
控制器构造函数将在中间件执行之前初始化。
您可以从控制器函数中的Injected $request
对象获取数据。
答案 1 :(得分:1)
您无法访问控制器构造函数中的会话或经过身份验证的用户,因为中间件还没有运行,所以您可以这样做:
public function __construct()
{
$this->middleware(function ($request, $next) {
$this->company = $request->attributes->get('company');
return $next($request);
});
}
答案 2 :(得分:1)
由于我目前尚不清楚的原因,在请求更改反映在请求对象之前构造控制器对象。简而言之,在构造控制器时,不认为请求是正确构造的。 This post似乎意味着这一点。
有两种方法可以解决这个问题(如果一秒钟我们忽略了你正在尝试做的事情)。
使用请求依赖注入
public function index(Request $request)
{
$compary = $request->attributes->get('company');
}
这不是真的WET,因为你只是用$this->company
与$request->attributes->get('company')
交换它只是一个重构。无论如何,您应该在控制器操作中注入请求,如果您不想这样做,可以使用request()
帮助程序。
现在,如果您想要一个更具体案例的解决方案,尽管您可以使用特定于案例的依赖注入:
如果您需要将模型绑定到特定路由参数,可以使用route model binding并在RouteServiceProvider
(或任何提供商)中添加以下内容。
Route::bind("companyAsARouteVarName", function () {
// this is why more details in the question are invaluable. I don't know if this is the right way for you.
//checks
// success
return $someModel;
});
然后您将路线注册为:
Route::get("/something/{companyAsARouteVarName}", "SomeController@index");
你的控制器将是:
public function index(Company $companyAsARouteVarName) {
//Magic
}