Back to results for “Unit Testing with PHPUnit”
PHP › Dependency Injection & Service Containers

How can overuse of a service container, sometimes called the service locator anti pattern, actually harm code quality despite the container itself being a useful tool?

Advanced

Answer

While a service container is valuable for automatically wiring together a class's declared dependencies, directly calling the container from within business logic code to fetch a dependency on demand, rather than having that dependency properly injected through the constructor, hides a class's true dependencies, makes the class harder to test since its real requirements are no longer visible from its constructor signature, and creates a hidden, implicit coupling to the container itself throughout the codebase, which is why most experienced developers recommend using the container purely for object construction and always relying on proper constructor injection within actual business logic.
// Anti pattern: hides real dependencies, harder to test
class OrderService {
    public function process() {
        $mailer = app(Mailer::class);
    }
}

// Preferred: explicit constructor injection
class OrderService {
    public function __construct(private Mailer $mailer) {}
}
Real-world example A team refactors a codebase where many classes had been directly pulling their dependencies from the service container inside individual methods, discovering that this had been silently hiding true dependencies and made writing isolated unit tests significantly more difficult than it should have been.

Common follow-ups: How do you identify and refactor away from the service locator anti pattern in an existing large codebase?;Are there any legitimate exceptions where directly resolving a dependency from the container is acceptable?