1

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.

class diagram

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.

yivi
  • 23,845
  • 12
  • 64
  • 89
NanoBreaker
  • 77
  • 10

1 Answers1

2

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).

yivi
  • 23,845
  • 12
  • 64
  • 89