Dependency Injection in PHP

Sélom
2 min readMay 5, 2018

Have you ever encountered a situation where you need to pass a dependency to a constructor which has nothing to do with that class?

Let us take this scenario. You have two classes as shown below:

//Author class
class Author {
private $firstName;
private $lastName;

public function __construct($firstName, $lastName){
$this->firstName = $firstName;
$this->lastName = $lastName;
} public function getFullName(){
return $this->firstName .' '. $this->lastName;
}}
//Blog class
class Blog {
private $title;
private $author;
private $firstName;
private $lastName;
//Notice that both $firstName and $lastName have nothing to do inside the Blog Scope public function __construct($title, $authorFirstName, $authorLastName){$this->title = $title;
$this->author = new Author($authorFirstName, $authorLastName); //Notice that we've used the new operator right in the Blog constructor.
}public function getBlogDetails(){
return $this->title .' is written by '. $this->author->getFullName();
}}

Now to use the classes above, we can create another file like this:

$firstName = "Lom";
$lastName = "Se";
$blogTitle = "Awesome blog title";
$blog = new Blog($blogTitle, $fistName, $lastName);echo $blog->getBlogDetails(); //This will output Awesome blog title is written by Lom Se

Technically, the code above will work just fine. However it presents a few problems listed below:

  1. The first thing to notice is that the variables $authorFirstName and $authorLastName have nothing to do inside Blog scope. They are only needed to create an instance of the Author class
  2. Another thing to notice is that the Author class is tightly coupled with the Blog class. If a new property is added to Author’s constructor, every single class where an object of Author is created has to be modified as well. Imagine what you will have to go through if you need to do this in a large application. This shouldn’t be fun at all.
  3. Lastly, to unit test the Blog class, you will need to unit test the Author class as well, even if you don’t want to.

To solve the issues listed above, we need to make use of dependency injection.

With dependency injection, we can pass an instance of the Author class to the Blog constructor like this:

//Blog class
class Blog {
private $title;
private $author;
public function __construct($title, Author $author){ //Notice that an instance of Author is passed to the constructor $this->title = $title;
$this->author = $author;
} public function getBlogDetails(){
return $this->title .' is written by '. $this->author- >getFullName();
}}

With this approach, the code is easier to maintain and test. Also note that Dependency Injection can also be used with methods. In my next post, I will illustrate this.

Have you ever had to deal with the issues highlighted in this post? Feel free to share your experience below.

--

--

Sélom

Software Engineer | Fullstack Web Dev | Node.js ~ Laravel ~ React.js