This course is archived!
Dependency Injection
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:
// ... 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:
// ... 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:
// ... 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
:
{ | |
// ... 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.
Hello. When I type php data/setupDb.php I have an error => Panic! could not find drivers . What should I do? Thank you