简体   繁体   English

中间件中的 Laravel 依赖注入

[英]Laravel Dependency Injection in Middleware

I am using Laravel-5.0's default Authentication Middleware, but I changed the signature of the handle function to have:我正在使用 Laravel-5.0 的默认Authentication中间件,但我将句柄函数的签名更改为:

public function handle($request, Closure $next, AuthClientInterface $authClient)

I also registered AuthClientInterface in a Service Provider with:我还在服务提供者中注册了AuthClientInterface

public function register()
{
    $this->app->bind('App\Services\Contracts\AuthClientInterface', function()
    {
        return new AuthClient(
            env('AUTH_SERVER_URL'),
            env('AUTH_SESSION_URL'),
            env('AUTH_CLIENT_ID')
        );
    });
}

However, despite this, I am see the following error:但是,尽管如此,我还是看到了以下错误:

Argument 3 passed to HelioQuote\Http\Middleware\Authenticate::handle() 
must be an instance of 
HelioQuote\Services\Contracts\HelioAuthClientInterface, none given, 
called in C:\MyApp\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php on line 125 and defined...

Can anyone see what I am doing wrong?谁能看到我做错了什么?

EDIT: I did get it working by passing the HelioAuthClientInterface into the constructor of the middleware.编辑:我确实通过将 HelioAuthClientInterface 传递给中间件的构造函数来使其工作。 However I thought the IoC container would also inject the dependency to methods in addition to the constructor.但是我认为 IoC 容器除了构造函数之外还会注入对方法的依赖。

You cannot do dependency injection at handle method in a Request directly, do that in a constructor.您不能直接在 Request 中的handle方法中进行依赖注入,而是在构造函数中进行。

Middleware is invoked by call_user_func , so any injection here will not be work.中间件由call_user_func调用,因此这里的任何注入都不起作用。

<?php

namespace App\Http\Middleware;

use Closure;
use App\Foo\Bar\AuthClientInterface; # Change this package name

class FooMiddleware
{
  protected $authClient;

  public function __construct(AuthClientInterface $authClient)
  {
    $this->authClient = $authClient;
  }

  public function handle(Request $request, Closure $next)
  {
    // do what you want here through $this->authClient
  }
}

Laravel's IoC only handles constructor method injection for all objects by default.默认情况下,Laravel 的 IoC 仅处理所有对象的构造函数方法注入。 The IoC will only inject dependencies into functions/methods handled by the router. IoC 只会将依赖项注入到由路由器处理的函数/方法中 The can be a closure used to handle a route, or more commonly, Controller methods used to handle routes.可以是用于处理路由的闭包,或者更常见的是用于处理路由的 Controller 方法。

The IoC does not do method dependency injection for any other object by default.默认情况下,IoC 不会对任何其他对象进行方法依赖注入。 You can call methods yourself through the IoC and have it resolve dependencies, but the framework only does this itself for route handlers.您可以通过 IoC 自己调用方法并让它解析依赖项,但框架本身只为路由处理程序执行此操作。 You can take a look at this question/answer for a little more information on using method dependency injection outside of a controller: can I use method dependency injection outside of a controller?您可以查看此问题/答案,了解有关在控制器外部使用方法依赖注入的更多信息: 我可以在控制器外部使用方法依赖注入吗? . .

Handling this by injecting your dependency through your constructor is the correct way to go, if you want to continue to use dependency injection.如果你想继续使用依赖注入,通过你的构造函数注入你的依赖来处理这个是正确的方法。

You are not allowed to change the method signature here.此处不允许更改方法签名。 Simply you may use something like this:简单地你可以使用这样的东西:

public function handle($request, Closure $next) {

    // Get the bound object to this interface from Service Provider
    $authClient = app('App\Services\Contracts\AuthClientInterface');

    // Now you can use the $authClient
}

Also, you may use a __construct method to achieve that, check the answer given by - Francis.TM .此外,您可以使用__construct方法来实现这一点,请检查 - Francis.TM给出的答案。

The accepted answer doesn't work anymore since Laravel 5.3.4.自 Laravel 5.3.4 以来,接受的答案不再有效。 See complain on GitHub and upgrade guide which provide an alternative.请参阅 GitHub 上的抱怨和提供替代方案的升级指南

For example, a snippet from what I implemented to solve the current problem:例如,我为解决当前问题而实现的片段:

<?php

namespace App\Http\Middleware;

use Closure;
use App\Models\Website;
use \Illuminate\Http\Request;

class CheckPropertyOfWebsite
{

    protected $website_owner_id;

    public function __construct(Request $request)
    {
        $this->website_owner_id = Website::findOrFail($request->website)->first()->user_id;
    }

    public function handle($request, Closure $next)
    {
        if ($request->user()->id !== $this->website_owner_id) {
            return response(null, 500);
        }
        return $next($request);
    }
}

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

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