Внедрение зависимостей в 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'));

Но это:

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

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


person S. Roose    schedule 20.11.2019    source источник


Ответы (3)


Не добавляя LoggerInterface в качестве именованной записи в контейнер, не могли бы вы просто внедрить класс LoggerInterface непосредственно в промежуточное ПО через $container->get()? т.е. в функции приложения routes.php:

$container = $app->getContainer();
$app->add(new MiddleWare\MyAuthentication(..., $container->get(LoggerInterface::class)));
person Woodrow    schedule 20.11.2019
comment
Красиво, это именно то, что мне было нужно! (хотя это кажется не лучшей практикой, для меня это выглядит довольно чисто) - person S. Roose; 21.11.2019

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

person Alex Barker    schedule 20.11.2019
comment
Привет, спасибо за ваш ответ. Как конкретно будет работать инъекция метода? Означает ли это передачу регистратора в качестве параметра для каждого вызова класса? - person S. Roose; 21.11.2019
comment
LoggerAwareInterface дает довольно хорошую идею. Просто используйте NullHandler или NoOpHandler для переменной-члена регистратора классов в конструкторе. Затем метод установки просто устанавливает элемент объекта, если это необходимо. Возможно, вы сможете использовать фабрику PHP-DI для автоматического подключения конструктора. - person Alex Barker; 21.11.2019

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

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

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

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

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

Это все.

person odan    schedule 23.11.2019