【问题标题】:Laravel Dependency Injection in Middleware中间件中的 Laravel 依赖注入
【发布时间】:2016-05-28 03:01:41
【问题描述】:

我使用的是 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 容器还会将依赖项注入到方法中。

【问题讨论】:

    标签: php laravel ioc-container middleware


    【解决方案1】:

    自 Laravel 5.3.4 以来,已接受的答案不再有效。 See complain on GitHubupgrade guide 提供了替代方案。

    例如,我为解决当前问题而实施的一个 sn-p:

    <?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);
        }
    }
    

    【讨论】:

      【解决方案2】:

      您不能直接在 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
        }
      }
      

      【讨论】:

      • OP 可以使用 IoC 容器从抽象中解析实现。 App::make() 在这种情况下是你的朋友。
      • @Burimi 这很棘手,我认为使用构造函数对于这种用法已经足够清楚了
      【解决方案3】:

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

      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 给出的答案。

      【讨论】:

        【解决方案4】:

        Laravel 的 IoC 默认只处理所有对象的构造方法注入。 IoC 只会将依赖项注入路由器处理的函数/方法。可以是用于处理路由的闭包,或者更常见的是用于处理路由的 Controller 方法。

        默认情况下,IoC 不会为任何其他对象执行方法依赖注入。您可以通过 IoC 自己调用方法并让它解决依赖关系,但框架只为路由处理程序执行此操作。您可以查看此问题/答案,了解有关在控制器外部使用方法依赖注入的更多信息:can I use method dependency injection outside of a controller?

        如果您想继续使用依赖注入,则通过构造函数注入依赖项来处理此问题是正确的方法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-08-02
          • 2016-10-05
          • 1970-01-01
          • 2022-01-16
          • 2016-07-19
          • 1970-01-01
          • 2023-03-23
          • 2014-02-02
          相关资源
          最近更新 更多