Внедрение зависимостей в PHP (slim, php-di)

У меня есть приложение Slim Php (slim4), в которое я добавил Monolog для ведения журнала. Я добавляю логгер в приложение вот так:

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

Это отлично работает для внедрения регистратора в большинство моих классов, просто выполнив:

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

Теперь я также хотел бы использовать регистратор в промежуточном программном обеспечении, таком как аутентификация. Я не понимаю, как я могу это сделать правильно. Я могу заставить это работать, добавив регистратор в качестве именованной записи в контейнер, например:

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

а затем передать его промежуточному программному обеспечению в качестве параметра конструктора, получив его обратно из контейнера:

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

Но это:

  • а) разбивает инъекцию по имени класса для других классов
  • б) очевидно не лучшая практика

Итак, как правильно внедрить этот регистратор в промежуточное ПО?

3 ответа

Решение

Без добавления LoggerInterface в качестве именованной записи в контейнер, не могли бы вы просто ввести LoggerInterface class напрямую к вашему промежуточному программному обеспечению через $container->get()? IE вroutes.php Функция приложения:

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

Короче говоря, я не думаю, что вы сможете автоматически подключать зависимости для промежуточного программного обеспечения, поскольку они должны быть созданы до добавления к маршрутизатору. Вам нужно будет явно ввести зависимость, как это предлагает @Woodrow, хотя я бы выбрал внедрение метода вместо внедрения конструктора для LoggerInterface, поскольку он будет придерживаться LoggerAwareInterface.

Вы можете позволить контейнеру внедрения зависимостей (PHP-DI) разрешить и внедрить все зависимости в ваше промежуточное ПО:

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

Затем просто зарегистрируйте промежуточное ПО с именем класса:

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

(Вы не должны вставлять сам контейнер в промежуточное ПО)

Вот и все.

Другие вопросы по тегам