中间件中的 Laravel 依赖注入
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35439234/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel Dependency Injection in Middleware
提问by ajon
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. However I thought the IoC container would also inject the dependency to methods in addition to the constructor.
编辑:我确实通过将 HelioAuthClientInterface 传递给中间件的构造函数来使其工作。但是我认为 IoC 容器除了构造函数之外还会注入对方法的依赖。
回答by Francis.TM
You cannot do dependency injection at handle
method in a Request directly, do that in a constructor.
您不能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
}
}
回答by patricus
Laravel's IoC only handles constructor method injection for all objects by default. The IoC will only inject dependencies into functions/methodshandled by the router. The can be a closure used to handle a route, or more commonly, Controller methods used to handle routes.
Laravel 的 IoC 默认只处理所有对象的构造方法注入。IoC 只会将依赖项注入到由路由器处理的函数/方法中。可以是用于处理路由的闭包,或者更常见的是用于处理路由的 Controller 方法。
The IoC does not do methoddependency injection for any other object by default. You can call methods yourself through the IoC and have it resolve dependencies, but the framework only does this itself for route handlers. 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?.
默认情况下,IoC 不会对任何其他对象进行方法依赖注入。您可以通过 IoC 自己调用方法并让它解析依赖项,但框架本身只为路由处理程序执行此操作。您可以查看此问题/答案,了解有关在控制器外部使用方法依赖注入的更多信息:我可以在控制器外部使用方法依赖注入吗?.
Handling this by injecting your dependency through your constructor is the correct way to go, if you want to continue to use dependency injection.
如果你想继续使用依赖注入,通过你的构造函数注入你的依赖来处理这个是正确的方法。
回答by The Alpha
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
。
回答by Romain 'Maz' BILLtheitroad
The accepted answer doesn't work anymore since Laravel 5.3.4. See complain on GitHuband upgrade guidewhich provide an alternative.
自 Laravel 5.3.4 以来,已接受的答案不再有效。 请参阅 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);
}
}