This course is archived!

01.

Dependency Injection

Share this awesome video!

|

Hi guys! In this tutorial, we're going to talk about dependency injection, services, and dependency injection containers by looking at a simple one called Pimple. The great news is that understanding these things isn't hard, but it can dramatically increase the quality and maintainability of the code you write.

As always, we'll be coding with a real example. Recently, we noticed that a lot of really nice rich people have been emailing us trying to give away their money. In this tutorial, we're going to create a simple app to help these fine people, we're calling it SendMoneyToStrangers.com.

I've already bootstrapped a small app, which you can download. It uses an Sqlite database, so make sure you have it installed, then chmod 777 the data directory and run a script that creates some dummy data for us:

chmod -R 777 data/
php data/setupDb.php

The app is really simple:

25 lines | app.php
// ... lines 1 - 2
require __DIR__.'/vendor/autoload.php';
use DiDemo\Mailer\SmtpMailer;
$dsn = 'sqlite:'.__DIR__.'/data/database.sqlite';
$pdo = new PDO($dsn);
$mailer = new SmtpMailer('smtp.SendMoneyToStrangers.com', 'smtpuser', 'smtppass', '465');
$sql = 'SELECT * FROM people_to_spam';
foreach ($pdo->query($sql) as $row) {
$mailer->sendMessage(
$row['email'],
'Yay! We want to send you money for no reason!',
sprintf(<<<EOF
Hi %s! We've decided that we want to send you money for no reason!
Please forward us all your personal information so we can make a deposit and don't ask any questions!
EOF
, $row['name']),
'YourTrustedFriend@SendMoneyToStrangers.com'
);
}

It queries the database, then delivers emails to each person using some SmtpMailer class:

60 lines | src/DiDemo/Mailer/SmtpMailer.php
// ... lines 1 - 2
namespace DiDemo\Mailer;
/**
* Sends emails via SMTP
*/
class SmtpMailer
{
private $hostname;
private $user;
private $pass;
private $port;
public function __construct($hostname, $user, $pass, $port)
{
$this->hostname = $hostname;
$this->user = $user;
$this->pass = $pass;
$this->port = $port;
}
// ... lines 26 - 33
public function sendMessage($recipientEmail, $subject, $message, $from)
{
// ... lines 36 - 58
}
}

You could use any mailer library here, and I've made this class fake the sending of emails for simplicity. Instead, it just logs details to a file:

60 lines | src/DiDemo/Mailer/SmtpMailer.php
// ... lines 1 - 33
public function sendMessage($recipientEmail, $subject, $message, $from)
{
// dummy implementation - this class is just used as an example
// hack - just log something so we can see it
$logPath = __DIR__.'/../../../logs/mail.log';
$logLines = array();
$logLines[] = sprintf(
'[%s][%s:%s@%s:%s][From: %s][To: %s][Subject: %s]',
date('Y-m-d H:i:s'),
$this->user,
$this->pass,
$this->hostname,
$this->port,
$from,
$recipientEmail,
$subject
);
$logLines[] = '---------------';
$logLines[] = $message;
$logLines[] = '---------------';
$fh = fopen($logPath, 'a');
fwrite($fh, implode("\n", $logLines)."\n");
// end hack
}

Tip

We're using Composer for autoloading files in our src/ directory with the following composer.json:

11 lines | composer.json
{
// ... lines 2 - 6
"autoload": {
"psr-4": { "": "src/" }
}
}

Tail the log file:

tail -f logs/mail.log

Then run the app via php app.php from the command line:

php app.php

You'll see two emails are sent to two lucky people.