Dependency Injection & Containers
Prerequisites: Advanced OOP patterns
Rather than a class constructing its own dependencies, they're provided ("injected") from outside — usually through the constructor.
interface EmailSender
{
public function send(string $to, string $message): void;
}
class OrderService
{
public function __construct(private EmailSender $emailSender) {}
public function placeOrder(string $customerEmail): void
{
$this->emailSender->send($customerEmail, 'Order confirmed!');
}
}
A dependency injection container (built into Laravel and Symfony) automatically resolves and constructs these dependencies based on type hints, so you rarely wire things up by hand in a framework-based project — but the underlying idea is exactly the constructor injection shown above.