PHP 8: Modern PHP Development · Composer, Autoloading and PSR Standards
Dependency Injection and Containers
Wire services through constructors and let a container build object graphs.
Dependency injection means classes receive collaborators (usually via the constructor) instead of creating them or reaching for globals. This makes code testable and swappable. A DI container (Symfony DI, Laravel's container, PHP-DI) builds object graphs automatically, often via autowiring based on type hints. Keep container access at the application's edges (composition root); business classes shouldn't call $container->get().
<?php
final class RegisterUser
{
public function __construct(
private UserRepository $users,
private PasswordHasher $hasher,
private EventDispatcherInterface $events,
) {}
public function __invoke(string $email, #[\SensitiveParameter] string $password): User
{
$user = User::register(new EmailAddress($email), $this->hasher->hash($password));
$this->users->save($user);
$this->events->dispatch(new UserRegistered($user->id));
return $user;
}
}
// PHP-DI autowiring
$container = (new DI\ContainerBuilder())
->addDefinitions([UserRepository::class => DI\autowire(PdoUserRepository::class)])
->build();
$handler = $container->get(RegisterUser::class);
Common pitfalls
- Service locator anti-pattern: injecting the container itself.
- Constructors with 10+ dependencies — a sign the class does too much.
- Hidden dependencies through static calls and globals.
Key points
- Inject collaborators through constructors
- Depend on interfaces for swappability
- Use the container only at the composition root
Further reading: PHP-DI: understanding DI
Practice questions
Why is injecting the container into a service considered an anti-pattern?
Answer
It hides the real dependencies (they're fetched at runtime), makes classes harder to test and understand, and couples code to the container. Inject the specific services instead.
How does dependency injection improve testability?
Answer
Tests can pass fakes or mocks for collaborators like repositories and HTTP clients, testing a class in isolation without databases or network calls.
Open in the app to mark lessons complete, take notes and track your progress.