繁体   English   中英

中间件中的 Laravel 依赖注入

[英]Laravel Dependency Injection in Middleware

我正在使用 Laravel-5.0 的默认Authentication中间件,但我将句柄函数的签名更改为:

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

我还在服务提供者中注册了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')
        );
    });
}

但是,尽管如此,我还是看到了以下错误:

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...

谁能看到我做错了什么?

编辑:我确实通过将 HelioAuthClientInterface 传递给中间件的构造函数来使其工作。 但是我认为 IoC 容器除了构造函数之外还会注入对方法的依赖。

您不能直接在 Request 中的handle方法中进行依赖注入,而是在构造函数中进行。

中间件由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 的 IoC 仅处理所有对象的构造函数方法注入。 IoC 只会将依赖项注入到由路由器处理的函数/方法中 可以是用于处理路由的闭包,或者更常见的是用于处理路由的 Controller 方法。

默认情况下,IoC 不会对任何其他对象进行方法依赖注入。 您可以通过 IoC 自己调用方法并让它解析依赖项,但框架本身只为路由处理程序执行此操作。 您可以查看此问题/答案,了解有关在控制器外部使用方法依赖注入的更多信息: 我可以在控制器外部使用方法依赖注入吗? .

如果你想继续使用依赖注入,通过你的构造函数注入你的依赖来处理这个是正确的方法。

此处不允许更改方法签名。 简单地你可以使用这样的东西:

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
}

此外,您可以使用__construct方法来实现这一点,请检查 - Francis.TM给出的答案。

自 Laravel 5.3.4 以来,接受的答案不再有效。 请参阅 GitHub 上的抱怨和提供替代方案的升级指南

例如,我为解决当前问题而实现的片段:

<?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