How to use Dependency Injection container when I have a variable non-static parameter that I need to supply?
What I want in my code is this:
$staff = $container->get(Staff::class);
What I have now is this:
$staff = new Staff("my_great_username");
Note that username can change and is supplied at run-time.
I cannot seem to put Staff
into my DI Container, because there is no way to specify a variable parameter there.
My Problem is ...
I am using Factory-based container, namely Zend\\ServiceManager\\ServiceManager
.This is a factory that I use to hide instantiation details:
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;
}
}
The way I set up the container in my config is this:
'factories' => [
Staff::class => StaffFactory::class
]
Note: even though the parameter is a "variable", I want Staff
to be immutable. Namely, once it is created, it stays that way. So I do not particularly wish to make a setter
method for the username as that will imply that the class is mutable, when it is not.
What do you suggest?
My problem was that I had a variable parameter that was being passed to the constructor of my Staff
class.
The solution is to create a StaffCreator
class that does not have variable parameters in its constructor, and then write a StaffCreator::create
method, which takes the variable parameter. Then, instead of injecting Staff
into whatever class where Staff
is needed, inject StaffCreator
instead, and then use it to create a Staff
instance.
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);
}
}
with credit to Steve
Note: You can create and add Interfaces
to the above code to make DI reusable. ie StaffCreatorInterface
, StaffInterface
. In my case I kept it simple, as I do not (yet) have a strong use case for reuse of the interface.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.