Dependency Injection Explained

Devin Dixon
Helium MVC
5 min readDec 5, 2018

--

Dependency Injection is one of the most common design patterns, especially in languages like PHP. The semi-confusing of the design pattern is “programming technique that makes a class independent of its dependencies” which does not tell beginners anything. In the tutorial, we will go over the basics of Dependency Injection to understand and implement it.

Why Dependency Injection Exists

Before going into Dependency Injection (DI), we need to understand why it is important.

When you are building a solution, the product you start building will not be the product you finish with as your needs and requirements change — and you might be forced to completely rewrite sections of your code. Let’s take sending emails as an example and how you change your code with several different implementations for sending emails.

You might start sending emails from your server using PHP’s generic mail() function. That is when you are defining the headers in a painful archaic way like so:

<?php
ob_start();
?>
— PHP-mixed-<?php echo $section_seperator; ?>
Content-Type: multipart/alternative; boundary=”PHP-alt-<?php echo $section_seperator; ?>”
— PHP-alt-<?php echo $section_seperator; ?>
Content-Type: text/plain; charset=”iso-8859–1"
Content-Transfer-Encoding: 7bit
<?php echo strip_tags($text_message);?> — PHP-alt-<?php echo $section_seperator; ?>
Content-Type: text/html; charset=”iso-8859–1"
Content-Transfer-Encoding: 7bit
<?php echo $html_message;?> — PHP-alt-<?php echo $section_seperator; ?> —
<?php
$message = ob_get_clean();mail( $to, $subject, $message, $headers );
?>

The above is probably the most difficult way to send emails in PHP. Then as you get a little more advanced, you come across PHP’s built-in Mail class and you switch to an SMTP server. Suddenly your code might look like this:

<?php
$mime = new Mail_mime(“\n”);
$mime->setTXTBody($text);
$mime->setHTMLBody($html);
$body = $mime->get();
$headers = $mime->headers($headers);

$smtp = Mail::factory(‘smtp’, $stmp_info);
$mail = $smtp->send($receiver, $headers, $body);
?>

And finally you arrive at libraries such as PHPMailer, which focus just on making sending emails very easy:

<?php
$mail = new PHPMailer(true);
$mail->Host = ‘smtp1.example.com;smtp2.example.com’;
$mail->SMTPAuth = true;
$mail->Username = ‘user@example.com’;
$mail->Password = ‘secret’;
$mail->SMTPSecure = ‘tls’;
$mail->Port = 587;
$mail->setFrom(‘from@example.com’, ‘Mailer’);
$mail->addAddress(‘joe@example.net’, ‘Joe User’);
$mail->Subject = ‘Here is the subject’;
$mail->Body = ‘This is the HTML message body <b>in bold!</b>’;
$mail->AltBody = ‘This is the body in plain text for non-HTML mail clients’;
$mail->send();
?>

This can require re-writing your code several different ways in different sections of your application, which can cause cascading effects around your entire system. However, we can minimize these effects with Dependency Injection by having our code rewrites happen in one place. Working our way up to DI, we are going to start with interfaces.

It Starts With Interfaces

We start by writing depending injection with what is now an interface like below.

<?php
interface MailInterface {
public function setTo();
public function setMessage();
public function send();
}
?>

Interfaces are special constructs in the PHP that set the structure for children classes. For example, the interface above sets up 3 different methods (setTo, setMessage, send) that are *REQUIRED* for any child class that implements MailInterface. This keeps the structure of ourcoding looking the exact same. Examples below:

Mail Class 1

<?phpclass MailClass1 implements MailInterface {
private $mailer = null;
private $to = ‘’;

public function __construct() {
$this ->$mailer = new Mail_mime(“\n”);
}
public function setTo($to) {
$this -> to = $to;
}

public function setMessage($html, $text) {
$mime->setTXTBody($text);
$mime->setHTMLBody($html);
}

public function send() {
$body = $mime->get();
$headers = $mime->headers($headers);

$smtp = Mail::factory(‘smtp’, $stmp_info);
$mail = $smtp->send($this->to, $headers, $body);
}
}//endclass
?>

Our 2nd Mail Class

<?phpclass MailClass2 implements MailInterface {

private $mailer = null;
public function __construct() {
$this -> mailer= new PHPMailer(true);
$this -> mailer->Host = ‘smtp1.example.com;smtp2.example.com’;
$this -> mailer->SMTPAuth = true;
$this -> mailer->Username = ‘user@example.com’;
$this -> mailer->Password = ‘secret’;
$this -> mailer->SMTPSecure = ‘tls’;
$this -> mailer->Port = 587;
}
public function setTo($to) {
$this -> mailer->addAddress($to);
}
public function setMessage($html, $text) {
$this -> mailer->Body = ‘This is the HTML message body <b>in bold!</b>’;
$this -> mailer->AltBody = ‘This is the body in plain text for non-HTML mail clients’;

}

public function send() {
$this -> mailer->send();
}
}//end class
?>

Notice both of the above classes implement the methods setTo, setMessage and send. But each underlying class structure of sending an email is different. When a developer calls each class to send an email, they will appear to function that same way even when under the hood they execute differently.

<?php//Send via MailClass1
$mail = MailClass1();
$mail->setTo(‘jon@example.com’);
$mail->setMessage($html, $text);
$mail->send();
//Send via Mail Class 2
$mail = MailClass2();
$mail->setTo(‘jon@example.com’);
$mail->setMessage($html, $text);
$mail->send();
?>

If we have to change how we want to send an email, we can simply swap MailClass1 with MailClass2 throughout our code, and minimal structural changes have to be done! But it can work easier with dependency injection.

Introducing Dependency Injection

Dependency Injection reduces the amount we would have to rewrite our code almost into 1 line by using a wrapper class like so:

<?phpclass MailWrapper implements MailInterface {
private $mailer = null;

public function __construct($mailer) {
$this -> mailer = $mailer;
}
public function setTo($to) {
$this -> mailer-> setTo($to);
}
public function setMessage($html, $text) {
$this ->mailer->setMessage($html, $text);
}
public function send() {
$this ->mailer ->send();
}
}
?>

In short, our wrapper class is just calling whichever class we pass into the constructor, hence is “wrapping” around another class. To use the wrapper, we would pass in one of the above of our other defined mail classes into the constructor like below.

<?php$mailerWrapper = new MailWrapper(new MailClass1());
$mailerWrapper->setTo(‘jon@example.com’);
$mailerWrapper->setMessage($html, $text);
$mailerWrapper->send();
?>

And it sends emails using MailClass1 methods because we passed it into the MailWrapper constructor. If we swap out MailClass1 with MailClass2, it will use MailClass2 methods. So how can this be useful?

Dependency Injection Sitewide

We want to put the MailWrapper someplace that is accessed universally in our application, like a configuration or bootstrap file. This way we only have to define it once and can easily swap out classes that have a site-wide effect without changing our site.

That is how dependency injection works. In ProdigyViews Toolkit, we can use an adapter pattern that is designed to be more precise than dependency injection when building your app.

--

--