简体   繁体   English

PHP (slim, php-di) 中的依赖注入

[英]Dependency injection in PHP (slim, php-di)

I have a Slim Php (slim4) application to which I added Monolog for logging purposes.我有一个 Slim Php (slim4) 应用程序,我在其中添加了 Monolog 以进行日志记录。 I'm adding the logger to the application like this:我将记录器添加到应用程序中,如下所示:

$containerBuilder->addDefinitions([
  LoggerInterface::class => function (ContainerInterface $c) {
     $logger = new Logger('appname');
     ...
     return $logger

This works fine for injecting the logger in most of my classes, by just doing:这适用于在我的大多数课程中注入记录器,只需执行以下操作:

public function __construct(ContainerInterface $container = null, LoggerInterface $logger)
{
    // I can use $logger here

Now I'd also like to use the logger in the middleware like authentication.现在我还想在中间件中使用记录器,如身份验证。 I don't see how I can properly do this.我不知道如何正确地做到这一点。 I can get this working by adding the logger as a named entry in the container like this:可以通过将记录器添加为容器中的命名条目来实现此功能,如下所示:

$containerBuilder->addDefinitions([
  "LoggerInterface" => function (ContainerInterface $c) {

and then passing it to the middleware as a constructor parameter by getting it back from the container:然后通过从容器中取回它作为构造函数参数将其传递给中间件:

$middlewares[] = new MyAuthentication(..., $container->get('LoggerInterface'));

But this:但是这个:

  • a) breaks the injection by classname for the other classes a) 按类名中断其他类的注入
  • b) is apparently not a best practice b)显然不是最佳实践

So what is the correct way to get this logger injected in the middleware?那么将这个记录器注入中间件的正确方法是什么?

Without adding the LoggerInterface as a named entry to the container, could you just inject the LoggerInterface class directly to your middleware via $container->get() ?如果不将LoggerInterface作为命名条目添加到容器中,您是否可以通过$container->get()LoggerInterface class 直接注入中间件? IE in a routes.php App function: IE 在路由中routes.php App function:

$container = $app->getContainer();
$app->add(new MiddleWare\MyAuthentication(..., $container->get(LoggerInterface::class)));

In short, I do not think you are going to be able to auto-wire the dependencies for the middleware as they need to be constructed before being appended to the router.简而言之,我不认为您将能够自动连接中间件的依赖关系,因为它们需要在附加到路由器之前构建。 You would need to explicitly inject the dependency as suggested by @Woodrow, although I would opt for method injection instead of constructor injection for the LoggerInterface as it would adhere to the LoggerAwareInterface.您需要按照@Woodrow 的建议显式注入依赖项,尽管我会选择方法注入而不是 LoggerInterface 的构造函数注入,因为它会遵守 LoggerAwareInterface。

You could let the dependency injection container (PHP-DI) resolve and inject all dependencies into your middleware:您可以让依赖注入容器(PHP-DI)解析并将所有依赖注入到您的中间件中:

LoggerInterface::class => function (ContainerInterface $container) {
    return new Logger('name');
},

Then just register the middleware with the class name:然后只需使用 class 名称注册中间件:

$app->add(\MiddleWare\MyAuthentication::class);

(You should not inject the container itself into the middleware) (您不应该将容器本身注入中间件)

That's all.就这样。

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

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