php · level 3 · unit 6 · lesson 1
- meet it
- guess first
- your turn
- fix it
- nailed it
Tap a green word if you get lost.
meet it
Hand a class its tools instead of letting it build its own.
A sign-up class needs a mailer to send welcome emails. That mailer is a . If the class writes new SmtpMailer() inside itself, it is welded to real email forever, and every test sends a real message to a real person.
flips it round. The class asks for a Mailer in its constructor, and whoever builds it hands one in. Because Mailer is an interface, any class keeping the promise fits. In a test, hand in a that writes to the screen instead.
<?php
interface Mailer {
public function send(string $to, string $text): void;
}
class ScreenMailer implements Mailer {
public function send(string $to, string $text): void { echo "To $to: $text\n"; }
}
class SignUp {
public function __construct(private Mailer $mailer) {}
public function register(string $email): void {
$this->mailer->send($email, "Welcome aboard!");
}
}
$signUp = new SignUp(new ScreenMailer());
$signUp->register("leo@example.com"); Wrap new in brackets, as in (new SignUp($mailer))->register(...), to call a method on the new object straight away.
guess first
Two greeters, two pretend clocks. What will this show?
Guess before you run it. Wrong guesses are how you learn, and nothing is marked.
<?php
interface Clock { public function hour(): int; }
class FixedClock implements Clock {
public function __construct(private int $hour) {}
public function hour(): int { return $this->hour; }
}
class Greeter {
public function __construct(private Clock $clock) {}
public function greet(): string {
return $this->clock->hour() < 12 ? "Good morning" : "Good afternoon";
}
}
$morning = new Greeter(new FixedClock(9));
$later = new Greeter(new FixedClock(15));
echo $morning->greet() . " then " . $later->greet() . "\n";
your turn
Your turn. Fake the card machine.
Make the fake keep the Payments promise, hand it to the checkout, then type a price in pence. For a twist, make it return false.
fix it
The test reminder still costs real money. Fix it.
- A fake is handed in on the last line, yet the output says Charged 5p. Which
Smsdoesremind()really use? - Line 12 builds its own
RealSms, ignoring the one that was injected into$this->sms. - Delete line 12 and change line 13 to
return $this->sms->send("Dentist at 3pm");, then run it.
nailed it
your classes take their tools from outside. :D
- A dependency is an object a class needs to do its job.
- Inject dependencies through the constructor, typed by an interface.
- Fakes keep the same promise, so tests stay quick and safe.
new words in your collection
- dependency
- dependency injection
- fake
This lesson isn’t saved. A free account remembers every lesson you finish.