PHP Course : What Is Dependency Injection
In this first PHP Lesson serie, we will cover what could be one of the first thing that any programmer must understand. It's probably the most basic yet complicated thing about programming, and it will help you greatly to understand how any framework work.
I remember one technical interview I had to pass for a job, and the first question I was asked was "What is dependency injection ?". We will cover several aspects on how to answer this question.
From Wikipedia : "Dependency injection is a technique whereby one object supplies the dependencies of another object"
Dependency Injection is simply passing an argument to a function, or a constructor.
... an IoC Container, or a Dependency Injection Container, or DI Container, which is a tool to help injecting dependencies.
To demonstrate what is dependency injection and what is it for, we first need to write some code that we will try to refactor.
For our little demo, we will use an FileService class. This class will be able to store a file that was uploaded by a user.
We can illustrate it like this
class FileService
{
public function store($uploadedFile) {
$fileSystem = new DiskFileSystem();
// or $fileSystem = new S3FileSystem();
return $fileSystem->storeUploadedFile($uploadedFile);
}
}
Now imagine that, one day, you must use AWS S3 Cloud Storage instead of the Disk System. What do you do? You have to change the code of FileService and all other classes that use "DiskFileSystem", and specify to use the other class instead.
As you can understand, DiskFileSystem is thightly coupled with FileService.
Dependency Injection solves this issue.
class FileService
{
private $fileSystem;
public function __construct(FileSystemInterface $fileSystem) {
$this->fileSystem = $fileSystem;
}
public function store($uploadedFile) {
return $this->fileSystem->storeUploadedFile($uploadedFile);
}
}
The FileSystem is injected into FileService.
The filesystems are now defined using an interface:
interface FileSystemInterface
{
public function storeUploadedFile($uploadedFile);
}
class DiskFileSystem implements FileSystemInterface { ...
class S3FileSystem implements FileSystemInterface { ...
Our FileService class now doesn't know anything about DiskFile and S3 systems. It is no more dependent on those classes
What we just demonstrate is called Inversion of Control.
The control of the dependencies is inverted from one being called to the one calling.
Uh.. what?! Well instead of using new DiskFileSystem
you will simply use a $filesystem
property, that your controller doesn't need to worry about.
It allows you to replace a dependency by another.
In other words, instead of putting your Controller (business domain) in charge of the dependencies, it's the application configuration that handles the dependencies.
For example what if Library X uses Logger Y and you want to make it use your logger Z? With dependency injection, you don't have to change the code of Library X.
The code sample we just wrote with the FileSystem is actually an implementation of the "Dependency Inversion Principle" which is different from Dependency Injection
Dependendy Injection is simply passing the dependency class in the class constructor.
And Dependency Inversion is the Interface solution where what you put in the class Constructor is actually an Interface.
Yes! Dependency Injection is simply passing an argument to a function, or a constructor. At this point in the PHP theory, we don't speak about Inversion of Control yet.
So, transferring the task of creating the object to someone else and directly using the dependency is called dependency injection.
Speaking of which, you can also use Dependency Injection outside the constructor:
class Profile {
private $setting;
public function setSetting(Setting $setting)
{
$this->setting = $setting;
}
}
This is called a setter injection and it is very useful to write tests.
Dependency Injection is actually a very simple thing. What's more complicated to understand is Inversion of Control, and Dependency Inversion, which I quickly demonstrated with the FileSystem code sample.
If you'd have to remember one thing about Dependency Injection, it's this example:
BAD
class FileService {
public function store($uploadedFile)
{
$fileSystem = new DiskFileSystem();
return $fileSystem->storeUploadedFile($uploadedFile);
}
}
GOOD
class FileService {
private $fileSystem;
public function setFileSystem(FileSystem $fileSystem) // or __constructor()
{
$this->fileSystem = $fileSystem;
}
public function store($uploadedFile)
{
return $this->fileSystem->storeUploadedFile($uploadedFile);
}
}
Let someone else worry about creating the class instance.
In the next lesson we will have a look at DI Container and how it works. How does injecting an interface gives me a class? We will cover that in the next lesson!
I consider myself as an IT Business Artisan. Or Consultant CTO. I'm a self-taught Web Developper, coach and teacher. My main work is helping and guiding digital startups.
more about meBTC
18SY81ejLGFuJ9KMWQu5zPrDGuR5rDiauM
ETH
0x519e0eaa9bc83018bb306880548b79fc0794cd08
XMR
895bSneY4eoZjsr2hN2CAALkUrMExHEV5Pbg8TJb6ejnMLN7js1gLAXQySqbSbfzjWHQpQhQpvFtojbkdZQZmM9qCFz7BXU
2024 © My Dynamic Production SRL All rights Reserved.