league/container
PSR-11–compliant dependency injection container from The PHP League. Register services, factories and shared instances, then resolve dependencies with autowiring support. Modern PHP (8.3+) with full docs, tests, and MIT license.
Installation:
composer require league/container
Requires PHP 8.3+.
Basic Setup:
use League\Container\Container;
$container = new Container();
First Use Case: Register a service with its dependencies:
$container->add(\App\Services\UserService::class)
->addArgument(\App\Repositories\UserRepository::class);
$container->add(\App\Repositories\UserRepository::class);
$userService = $container->get(\App\Services\UserService::class);
Constructor Injection:
$container->add(\App\Services\OrderService::class)
->addArgument(\App\Services\PaymentService::class)
->addArgument(\App\Services\ShippingService::class);
Interface Binding:
$container->add(\App\Contracts\LoggerInterface::class, \App\Services\MonologLogger::class);
Aliases for Flexibility:
$container->add('logger', \App\Contracts\LoggerInterface::class);
$logger = $container->get('logger'); // Resolves to MonologLogger
Laravel Integration:
Use League\Container alongside Laravel's service container by extending Illuminate\Container\Container or using it as a fallback delegate:
$laravelContainer->delegate(new Container());
Middleware/Event Dispatchers: Register handlers as services:
$container->add(\App\Middleware\AuthMiddleware::class);
$authMiddleware = $container->get(\App\Middleware\AuthMiddleware::class);
Configuration Management: Bind config objects early:
$container->add(\App\Config\AppConfig::class);
Testing: Mock dependencies by overriding bindings in tests:
$container->add(\App\Services\UserService::class, \App\Mocks\MockUserService::class);
Group related bindings in a provider:
use League\Container\ServiceProvider\AbstractServiceProvider;
class AppServiceProvider extends AbstractServiceProvider {
protected $provides = [
\App\Services\UserService::class,
\App\Repositories\UserRepository::class,
];
public function register() {
$this->container->add(\App\Repositories\UserRepository::class)
->addArgument(\App\Database\Connection::class);
$this->container->add(\App\Services\UserService::class)
->addArgument(\App\Repositories\UserRepository::class);
}
}
Register the provider:
$container = new Container();
$container->addServiceProvider(new AppServiceProvider());
Circular Dependencies:
League\Container\Exception\NotFoundException when services depend on each other.DatabaseConnection shared across services).Overly Broad Bindings:
$container->add(\App\Contracts\LoggerInterface::class, \App\Services\MonologLogger::class);
Performance with addArgument():
addArgument() for complex constructors can slow resolution.LiteralArgument for static values:
use League\Container\Argument\LiteralArgument;
$container->add(\App\Services\EmailService::class)
->addArgument(new LiteralArgument('contact@example.com'));
Delegate Containers:
$container->debug(true); // Logs resolution steps to stderr
if (!$container->has(\App\Services\UserService::class)) {
throw new \RuntimeException('Service not registered');
}
$bindings = $container->getBindings();
print_r($bindings);
Custom Argument Resolvers:
Extend League\Container\Argument\ArgumentInterface for custom logic (e.g., environment-based values):
class EnvArgument implements ArgumentInterface {
public function __invoke(ContainerInterface $container) {
return $_ENV['APP_DEBUG'] ?? false;
}
}
Inflectors: Modify resolved objects post-construction:
$container->addInflector(function ($object) {
if ($object instanceof \App\Services\UserService) {
$object->setLogger($container->get('logger'));
}
return $object;
});
PSR-11 Compliance:
Implement Psr\Container\ContainerInterface for third-party integration:
$container->delegate(new \Your\Psr11Container());
addShared() for singletons:
$container->addShared(\App\Database\Connection::class);
php-di/php-di or implement a custom resolver.LiteralArgument for Primitives:
$container->add(\App\Services\CacheService::class)
->addArgument(new LiteralArgument(3600)); // TTL
register(), boot()) don’t clash with League’s ServiceProvider interface.How can I help you explore Laravel packages today?