Как поместить класс, для которого требуется переменный параметр, в контейнер Dependency Injection?

Как использовать контейнер 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 метод для имени пользователя, поскольку это будет означать, что класс является изменяемым, когда это не так.

Что ты предлагаешь?

2

Решение

Моя проблема была в том, что у меня был переменный параметр, который передавался в конструктор моего 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, В моем случае я оставил это простым, поскольку у меня (пока) нет сильного варианта использования для повторного использования интерфейса.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]