I am using PHP-DI 6 Container in my PHP Project. At the very begging of my program I just initialize the container and get Application
class with all dependencies injected.
$container = new Container();
$application = $container->get(Application::class);
$application->initialize();
$application->run();
On the image below you can see classes that I use in my project.
Asterisk Dispatcher gets injected into Application class.
private $asteriskDispatcher;
public function __construct(AsteriskDispatcher $asteriskDispatcher)
{
$this->asteriskDispatcher = $asteriskDispatcher;
}
Then, inside AsteriskDispatcher
class I need to create a list of Asterisk Manager instances, which is going to contain some dependencies as well in near future.
I don't want to inherit container through the all classes. Is there a way to initialize PHP-DI container as singleton, so I can use it any moment I want to create some objects?
This is how I am doing this right now, I just create a new instance of PHP-DI container inside my AsteriskDispatcher
class and this looks so damn awful.
class AsteriskDispatcher implements AsteriskDispatcherInterface
{
private $listOfAsteriskManagers;
public function __construct()
{
$configurations = AsteriskConnectionsConfiguration::$connectionsConfiguration;
$this->listOfAsteriskManagers = new \SplDoublyLinkedList();
$container = new Container();
foreach ($configurations as $configuration)
{
$this->listOfAsteriskManagers->push($container->make(AsteriskManager::class,
array('configuration' => $configuration)));
}
}
}
I really want to understand how can I use PHP-DI container without breaking SOLID principles.
From the documentation:
If you need to use the make() method inside a service, or a controller, or whatever, it is recommended that you type-hint against FactoryInterface *. That avoids coupling your code to the container. DI\FactoryInterface is automatically bound to DI\Container so you can inject it without any configuration.
*emphasis mine
So you should change your AsteriskDispatcher
constructor to be like:
public function __construct(FactoryInterface $factory) {
// your code ...
// more of your code ...
$factory->make(AsteriskManager::class, ['configuration' => $configuration]);
// the rest of your code.
}
PS: Singletons are evil (mostly).