What Is Dependence Injection?


Dependency injection as a concept is similar to the difference between getting your coffee already made for you versus getting a cup of coffee with sugar and cream on the side.

In the latter example, you get to decide how much sugar and cream to use or even forego them altogether.

Dependency injection is similar to the latter where you get to decide or be able to swap out other code your original piece of code depends on.


Without dependency injection

01: <?php
03: class PaymentProcessor {
04:     public function charge($price) {
05:         return "charged customer: ".$price;
06:     }
07: }
09: class CheckOut {
11:     private $processor;
13:     public function __construct() {
14:         $this->processor = new PaymentProcessor();
15:     }
17:     public function makePayment($price) {
18:         return $this->processor->charge($price);
19:     }
20: }
22: $checkout  = new CheckOut();
23: echo $checkout->makePayment(200);
24: ?>

The sample code above shows two classes PaymentProcessor and CheckOut. The CheckOut class depends on the PaymentProcessor class to process payments.

As part of the definition of the CheckOut class it creates an instance of the PaymentProcessor class internally and assigns it to the $processor property (line:14) to later be used in the makePayment method.

In the above example, anyone using the CheckOut class has very little control over the type of PaymentProcessor used as it is internal to the CheckOut class.

Using dependency injection

01: <?php
02: class PaymentProcessor {
03:     public function charge($price) {
04:         return "charged customer: ".$price;
05:     }
06: }
08: class CheckOut {
10:     private $processor;
12:     public function __construct(PaymentProcessor $processor) {
13:         $this->processor = $processor;
14:     }
16:     public function makePayment($price) {
17:         return $this->processor->charge($price);
18:     }
19: }
20: $processor = new PaymentProcessor();
21: $checkout  = new CheckOut($processor);
22: echo $checkout->makePayment(200);
23: ?>

In the second example we see the constructor __construct now requires the user of the CheckOut class to pass in the PaymentProcessor themselves. This allows them to use other payment processors [→]

On line 19 we now instantiate our PaymentProcessor separately and then pass it into the CheckOut class on line 20.


The key concept is our ability to swap out different dependencies in our code. This provides some benefits such as being able to swap out providers and also swap out code during testing, to avoid making non-idempotent [↗] changes.

Here is another article you might like 😊 "What are namespaces?"