В настоящее время я тестирую phalcon php для проекта и ищу способ автоматического внедрения определенных классов автоматически на основе реализованного интерфейса.
Ссылка на внедрение зависимостей есть пример, где, если класс реализует Phalcon\DI\InjectionAwareInterface
, он автоматически вставит DI в этот класс.
То, что я хочу сделать, похоже. Если класс имеет, например, Aranea\Db\DbAdapterAware
, он должен автоматически внедрить DbAdapter в этот класс. Я ищу что-то похожее на то, что делает Zend Framework 2 (https://juriansluiman.nl/article/121/interface-injection-with-initializers-in-zend-servicemanager), где во время настройки DI вы можете указать инициализаторы следующим образом:
'initializers' => array(
'logger' => function($service, $sm) {
if ($service instanceof LoggerAwareInterface) {
$logger = $sm->get('logger');
$service->setLogger($logger);
}
}
),
Если это не возможно автоматически в PhalconPHP, я думал об отмене FactoryDefault
Класс и реализовать его сам. Каково было бы правильное место, чтобы ввести эту логику? В методах get *, точнее в set * методов? Я предполагаю, что метод инициализируется не во время инициализации DI, а при первом вызове, так что get * будет более подходящим?
Спасибо за совет,
Йерун
Ссылка на внедрение зависимостей содержит пример, где, если класс реализует
Phalcon\DI\InjectionAwareInterface
, он автоматически вставит DI в этот класс.
Это не совсем верно, это означает, что DI вводится (автоматически), когда служба разрешается, если она реализует этот интерфейс, DI волшебным образом не появляется там только потому, что класс реализует некоторый интерфейс.
Если класс имеет, например,
Aranea\Db\DbAdapterAware
, он должен автоматически внедрить DbAdapter в этот класс.
Вот как это работает (не технически), если ваш класс расширяет Phalcon\DI\Injectable
(или реализует InjectionAwareInterface
так же, как Phalcon\DI\Injectable
). внутри Injectable
Eсть __get
magic, которая возвращает сервис из DI, если сервис существует. Другими словами, вещи вводятся только в DI, а другие классы ищут там службы.
Чтобы внедрить ваши собственные сервисы, вы можете либо передать их в вашей конфигурации DI, либо расширить DI
или же FactoryDefault
, Разница между ними заключается в том, что FactoryDefault
уже поставляется с предварительно настроенными полезными службами, которые вам могут не понадобиться.
Я предполагаю, что метод инициализируется не во время инициализации DI, а при первом вызове, так что get * будет более подходящим?
Да, есть Phalcon\DI\Service
объект, который представляет службу и разрешается при вызове в первый раз (если это общая служба) или разрешается каждый раз (если это не так). Как правило, вы хотите, чтобы все ваши службы были общими, в противном случае это часто становится узким местом, например, при разрешении адаптера для базы данных без общего доступа, который устанавливает соединение каждый раз, когда вы вызываете его…
PS: Обратите внимание, чтобы он работал так, как вы хотите с DbAdapter
Вы можете сделать несколько вещей:
DI::getDefault()->getShared('db')
;Phalcon\DI\Injectable
и установите DI при создании класса, чтобы он мог искать сервисы.Других решений пока нет …