Dependency injection is a design pattern which helps to reduce tight coupling.
Letβs check the example, where we link an author to the book:
<?php
class Author
{
/**
* @var string
*/
private $firstName;
/**
* @var string
*/
private $lastName;
/**
* Constructor.
*
* @param string $firstName
* @param string $lastName
*/
public function __construct($firstName, $lastName)
{
$this->firstName = $firstName;
$this->lastName = $lastName;
}
}
class Book
{
/**
* @var string
*/
private $title;
/**
* @var string
*/
private $author;
/**
* Constructor.
*
* @param string $firstName
* @param string $lastName
* @param string $title
*/
public function __construct($firstName, $lastName, $title)
{
$this->title = $title;
$this->author = new Author($firstName, $lastName);
}
}
As you can see, we have a class Author
with $firstName
and $lastName
properties, and in the class Book
constructor, we inject the properties of
the Author
class along with the Book
class properties and create an object
of the Author
class and store it. You may think it is great code, but it is
not.
Why?
Book
class does
more than representing a Book
.Author
class constructor, then you will break the Book
class.Therefore, to solve this issue, we use dependency injection, and this is how you use it:
<?php
class Author
{
/**
* @var string
*/
private $firstName;
/**
* @var string
*/
private $lastName;
/**
* Constructor.
*
* @param string $firstName
* @param string $lastName
*/
public function __construct($firstName, $lastName)
{
$this->firstName = $firstName;
$this->lastName = $lastName;
}
}
class Book
{
/**
* @var string
*/
private $title;
/**
* @var Author
*/
private $author;
/**
* Constructor.
*
* @param string $title
* @param Author $author
*/
public function __construct($title, Author $author)
{
$this->title = $title;
$this->author = $author;
}
}
$author = new Author('John', 'Doe');
$book = new Book('Some legendary book', $author);
So, as you can see, we created an object of the Author
class, and passed the
variable referring to the object into the Book
class. So basically, that is
it about dependency injection.
Most common types of dependency injection are:
Dependency gets injected via class constructor as shown in above example:
$author = new Author('John', 'Doe');
$book = new Book('Some legendary book', $author);
Dependency gets injected with class setter method:
<?php
class Author
{
/**
* @var string
*/
private $firstName;
/**
* @var string
*/
private $lastName;
/**
* Constructor.
*
* @param string $firstName
* @param string $lastName
*/
public function __construct($firstName, $lastName)
{
$this->firstName = $firstName;
$this->lastName = $lastName;
}
}
class Book
{
/**
* @var string
*/
private $title;
/**
* @var Author
*/
private $author;
/**
* Set book author.
*
* @param Author $author
*/
public function setAuthor(Author $author)
{
$this->author = $author;
}
/**
* Set book title.
*
* @param string $title
*/
public function setTitle($title)
{
$this->title = $title;
}
}
$author = new Author('John', 'Doe');
$book = new Book();
$book->setAuthor($author);
$book->setTitle('Some legendary book');
Client uses interface for dependency injection.
In projects with a large number of classes utilizing the dependency injection pattern, managing these dependencies can be solved nicely with dependency injection container