简体   繁体   English

Laravel Request:直接在控制器构造函数中注入 Request 是正确的吗?

[英]Laravel Request: it's correct injecting Request directly in the controller constructor?

In a Laravel Controller, if all the functions use Request, it's correct to inject the Request directly in the constructor instead of the function?在 Laravel Controller 中,如果所有函数都使用 Request,那么直接在构造函数中而不是在函数中注入 Request 是正确的吗?

The code below works, I was just wondering if it's correct and if it has side effects...下面的代码有效,我只是想知道它是否正确以及它是否有副作用......

class BananaController extends Controller
{

protected $request; // request as an attribute of the controllers

public function __construct(Request $request)
{
    $this->middleware('auth');
    $this->request = $request; // Request becomes available for all the controller functions that call $this->request
}

public function store()
{
    $this->validate($this->request, [
    'text' => 'required',
    ]);

    // I save the banana attributes and the controller continues...

Go easy on me, first question on stackoverflow ever :-)放轻松,关于stackoverflow的第一个问题:-)

[ADDENDUM] To be clear, the "conventional" code would be: [附录] 需要明确的是,“常规”代码是:

class BananaController extends Controller
{

public function __construct()
{
    $this->middleware('auth');
}

public function store(Request $request)
{
    $this->validate($request, [
    'text' => 'required',
    ]);

    // I save the banana attributes and the controller continues...

I have been using the same technique to protect all my resource controller routes with the request (for instance to check if the logged user is authorised to access this resource)我一直在使用相同的技术来保护我所有的资源控制器路由请求(例如检查登录用户是否有权访问此资源)

However, since Laravel 5.3 the controller constructors now run before middleware get executed and it actually broke route model binding inside the request.然而,从 Laravel 5.3 开始,控制器构造函数现在在中间件执行之前运行,它实际上破坏了请求中的路由模型绑定。

So if you inject a request directly to a controller method, like in Laravel docs and if you have any model bound to you route it would resolve it fine, but if you inject your request in the controller constructor and try to access your model within the request like below - it will return just the resource id instead of the model.因此,如果您将请求直接注入到控制器方法中,就像在 Laravel 文档中一样,并且如果您将任何模型绑定到您的路由,它会很好地解决它,但是如果您在控制器构造函数中注入您的请求并尝试访问您的模型像下面这样的请求 - 它只会返回资源 ID 而不是模型。

//Route service provider
Route::model('resource', MyModel::class);
//Request class
public function authorize()
{
    //We expect to get a resource or null
    //But now it just returns the resource id
    if (!is_null($this->resource))
    {
        return $this->resource->createdBy->id == $this->getLoggedUser()->id;
    }
}

If all or almost of the methods in your controller BananaController are using the Request class, the most common way to inject dependencies is via a class's constructor as shown in your example.如果您的控制器BananaController中的所有或几乎所有方法都使用Request类,则注入依赖项的最常见方法是通过类的构造函数,如您的示例所示。

There are several advantages to using constructor injection:使用构造函数注入有几个优点:

  • If the dependency is a requirement and the class cannot work without it then injecting it via the constructor ensures it is present when the class is used as the class cannot be constructed without it.如果依赖是必需的,并且类没有它就不能工作,那么通过构造函数注入它可以确保在使用类时它存在,因为没有它就不能构造类。

  • The constructor is only ever called once when the object is created, so you can be sure that the dependency will not change during the object's lifetime.构造函数只在创建对象时调用一次,因此您可以确保依赖项在对象的生命周期内不会改变。

Note that these advantages do mean that constructor injection is not suitable for working with optional dependencies.请注意,这些优点确实意味着构造函数注入不适合处理可选依赖项。 It is also more difficult to use in combination with class hierarchies: if a class uses constructor injection then extending it and overriding the constructor becomes problematic.与类层次结构结合使用也更加困难:如果一个类使用构造函数注入,那么扩展它并覆盖构造函数就会成为问题。

如果您使用构造函数来验证或授权,则不php artisan route:list使用php artisan route:list .. 所以最好通过路由模型绑定来获取所需的内容

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM