当我有一个我需要提供的可变非静态参数时,如何使用Dependency 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
方法,因为这意味着该类是可变的,而不是。
你有什么建议?
答案 0 :(得分: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);
}
}
归功于Steve
注意:您可以在上面的代码中创建并添加Interfaces
以使DI可重复使用。即StaffCreatorInterface
,StaffInterface
。在我的情况下,我保持简单,因为我(还)没有强大的用例来重用接口。