Как использовать контейнер Inpendency Injection, когда у меня есть переменный нестатический параметр, который мне нужно предоставить?
Что я хочу в моем коде это:
$staff = $container->get(Staff::class);
Что у меня сейчас есть, это:
$staff = new Staff("my_great_username");
Обратите внимание, что имя пользователя может меняться и предоставляется во время выполнения.
Я не могу поставить Staff
в мой DI-контейнер, потому что там нет способа указать параметр переменной.
Моя проблема …
Я использую фабричный контейнер, а именно Zend\ServiceManager\ServiceManager
Это фабрика, которую я использую, чтобы скрыть детали реализации:
class StaffFactory
{
function __invoke(ContainerInterface $container): Staff
{
/*
* I do not seem to know how to get my username here
* nor if it is the place to do so here
*/
$staff = new Staff(????????);
return $staff;
}
}
Я настроил контейнер в моей конфигурации следующим образом:
'factories' => [
Staff::class => StaffFactory::class
]
Примечание: хотя параметр является «переменной», я хочу Staff
быть неизменным. А именно, как только он создан, он остается таким. Поэтому я не особо хочу сделать setter
метод для имени пользователя, поскольку это будет означать, что класс является изменяемым, когда это не так.
Что ты предлагаешь?
Моя проблема была в том, что у меня был переменный параметр, который передавался в конструктор моего Staff
учебный класс.
Решение состоит в том, чтобы создать StaffCreator
класс, который не имеет переменных параметров в своем конструкторе, а затем записать StaffCreator::create
метод, который принимает параметр переменной. Затем вместо инъекций Staff
в любой класс, где Staff
нужен, впрыскивать StaffCreator
вместо этого, а затем использовать его для создания Staff
пример.
то есть
//Inject this wherever you need Staff
$staffCreator = $container->get(StaffCreator::class);
//use it:
$staff = $this->staffCreator->create("my_great_username");
//code:
class StaffCreatorFactory
{
function __invoke(ContainerInterface $container)
{
return new StaffCreator();
}
}
class StaffCreator
{
function __construct()
{
//additional creation parameters possible here
}
function create(string $username): Staff
{
return new Staff($username);
}
}
с кредитом Стив
Примечание: вы можете создавать и добавлять Interfaces
к приведенному выше коду, чтобы сделать DI многоразовым. то есть StaffCreatorInterface
, StaffInterface
, В моем случае я оставил это простым, поскольку у меня (пока) нет сильного варианта использования для повторного использования интерфейса.
Других решений пока нет …