DEV Community

Sumit Wadhwa
Sumit Wadhwa

Posted on

Explain Dependency Injection Container like I'm five

I'm having a hard time wrapping my head around a DI package for PHP (PHP-DI). And why exactly would I want to use it?

Also, how it is different from simply instantiating a class wherever you want?

You can explain the title in regards or regardless to any particular language.

Top comments (4)

Collapse
 
17cupsofcoffee profile image
Joe Clay • Edited

Disclaimer - I'm not hugely familiar with PHP, basing this off my experience of other languages!

Say I'm writing an app and I need MyClass to use an instance of MyDependency. The easiest approach, as you suggested, would just be to do new MyDependency() and be done with it. In a lot of scenarios, that's totally sufficient!

// No dependency injection

class MyClass {
    private $myDependency;

    public function __construct() {
        $this->myDependency = new MyDependency();
    }
}
Enter fullscreen mode Exit fullscreen mode

But the tricky part comes if you want to make MyClass be able to use lots of different versions of MyDependency - what if MyDependency calls out to the network and you want to replace it with a mock? You could add a load of branching logic to decide which version to use, but that gets messy quickly.

A better option is to use the old principle of 'dependency inversion' - rather than constructing the dependency in MyClass, you take it in through the constructor or a setter, letting the parent of MyClass decide which version to use. Again, in a lot of cases this will suffice!

// Manual dependency injection

class MyClass {
    private $myDependency;

    public function __construct(MyDependency $myDependency) {
        $this->myDependency = $myDependency;
    }
}
Enter fullscreen mode Exit fullscreen mode

So where does a DI container like PHP-DI come into things? Well, if you're constantly having to manually inject your dependencies, it can be quite tedious/inflexible - you only ever mock MyDependency in tests, yet suddenly you're having to explicitly pass an instance in every time you want to use MyClass!

A DI container provides an extra layer of wiring on top of this to make things easier and more configurable. For example, PHP-DI offers 'autowiring' functionality that will automatically inject dependencies into your classes' constructors, and a configuration API that lets you set which versions get used. Now rather than having to manually inject your mocks everywhere you use MyClass, you can just change the container config! This does, however, come at a bit of a cost - now if you want to create an instance of MyClass, you have to do it through the container's API rather than simply calling new.

My advice would be, unless you know from the start you're doing to need the flexibility/configuration that a DI container provides for your project, start with one of the simpler ways of doing it - you can always add it later if you find yourself needing it!

Collapse
 
swadhwa16 profile image
Sumit Wadhwa

I'm sorry for my inadequacy. But, what do you mean when you say lots of different versions of MyDependency? Are you referring to polymorphism?

Collapse
 
17cupsofcoffee profile image
Joe Clay

Yep, polymorphism is what I was referring to, apologies if that wasn't clear! In the second example, MyDependency could be an class with multiple sub-classes or an interface with multiple implementors.

Thread Thread
 
swadhwa16 profile image
Sumit Wadhwa

Thanks so much for making it clear.