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)
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 ofMyDependency
. The easiest approach, as you suggested, would just be to donew MyDependency()
and be done with it. In a lot of scenarios, that's totally sufficient!But the tricky part comes if you want to make
MyClass
be able to use lots of different versions ofMyDependency
- what ifMyDependency
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 ofMyClass
decide which version to use. Again, in a lot of cases this will suffice!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 useMyClass
!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 ofMyClass
, you have to do it through the container's API rather than simply callingnew
.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!
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?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.Thanks so much for making it clear.