PHP / CHAPTER 09
Interfaces and replaceable collaborators
AdvancedDefine behavior contracts that make services testable.
By the end of this chapter
- Express required methods with an interface
- Inject a collaborator rather than constructing it internally
- Separate transformation from external effects
The idea
An interface names a behavior contract through method signatures. Different classes can implement it while using different storage or delivery mechanisms. A consumer that accepts the interface depends on the required capability instead of one concrete implementation. This is especially helpful for testing code that normally performs external effects, such as writing a report or reading from a service.
Supply the collaborator to the consumer rather than hiding construction inside the operation. Tests can then provide a predictable implementation and inspect the requested behavior. Keep calculation separate from persistence so the core transformation remains easy to test. An interface does not guarantee correct behavior by itself: document ordering, failures, and side effects, and test implementations against those expectations.
<?php
interface Formatter { public function format(int $value): string; }
final class CountFormatter implements Formatter {
public function format(int $value): string { return "Count: " . $value; }
}
function report(Formatter $formatter, int $value): string {
return $formatter->format($value);
}
echo report(new CountFormatter(), 6), "
";Count: 6
The report function requires Formatter behavior. Another compatible implementation can be supplied without changing report’s calculation or call site structure.
Try it yourself
Define a text sink interface and inject it into a function that writes one already-formatted report.
Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.
CHECK YOUR UNDERSTANDING