If you are going to develop your software with an object-oriented programming language like C## or Java. The moment will come when you have to think about decoupling components. Hitting up the google search engine and eventually, you are going to find a term called Dependency Injection or in short terms DI.  
One typical example would be a logger or a database component that has to be changed in an existing coding project. It is obvious that you want to do this with the least possible effort and aren’t willing to adjust the implementation for the old components to be adaptative to the new ones.
Normally you could change components easily when they fulfill the same task without too much effort to adapt to the existing codebase. But the real question is:
How much code do I/we have to adapt?
I bet you’ve heard about DI-Container in the past. That’s the term we are searching for. They are responsible for the configuration of the basis. Managing dependencies and giving out the information to every requester.
To sum up this concept real quick: This technique is used to make classes independent of their dependencies. In C## you create an object with the new operator. If class A depends on class B it creates this one with a call of the constructor in a combination with the new operator of class B. Imagine class B gets his state changed by class A and class C comes into the game.
Class C also needs an instance of class B. How does C get the instance of B, if it is already created? Does A create C and pass in the already created instance? Does C create another instance? Does C need the changed state of the instance of B?
You realize we get into trouble here.
Therefore, DI enables you the replacement of dependencies without having to change the class that uses them. It is also capable of reducing the risk for a change of a class just because one of its dependencies changed. 
What is PHP: - Who invented PHP, how it works, answers to all such questions about PHP, and much other information, you are going to