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.