4

当我有一个需要提供的可变非静态参数时,如何使用依赖注入容器?

我在我的代码中想要的是:

$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为用户名创建一个方法,因为这意味着该类是可变的,而实际上它不是。

你有什么建议?

4

1 回答 1

2

我的问题是我有一个变量参数被传递给我的Staff类的构造函数。

解决方法是在其构造函数中创建一个StaffCreator没有可变参数的类,然后编写一个StaffCreator::create方法,该方法接受可变参数。然后,与其注入Staff任何Staff需要的类,不如注入StaffCreator,然后使用它来创建一个Staff实例。

IE

//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 可重用。即StaffCreatorInterfaceStaffInterface。就我而言,我保持简单,因为我(还)没有一个强大的用例来重用接口。

于 2017-09-06T23:20:16.030 回答