Dependency Injection Container
Service lifetimes, bindings, aliases, dependency resolution a praktické patterny pro registraci služeb.
PSR-11 contract
Container implements framework ContainerInterface, which extends PSR-11 Psr\Container\ContainerInterface. Core methods are get() and has(), extended by framework methods set(), singleton() and isBound().
Binding types
Binding concrete can be class-string, factory callable or concrete object. set() is transient, singleton() is shared and cached.
// 1) Transient binding
$container->set(Foo::class, Foo::class);
// 2) Singleton binding
$container->singleton(Bar::class, Bar::class);
// 3) Factory binding
$container->singleton(InvoiceImporter::class, static function (ContainerInterface $container): InvoiceImporter {
return new InvoiceImporter(
$container->get(ApiClient::class),
);
});
// 4) Interface binding
$container->singleton(ApiClientInterface::class, ApiClient::class);
// 5) String alias
$container->singleton('custom.service', new CustomService());
has vs isBound
has($id) returns true for explicit bindings and also for existing class names (autowiring fallback). isBound($id) returns true only for explicit bindings/instances in container state.
$container->has(App\Services\ReportService::class); // can be true via class_exists fallback
$container->isBound(App\Services\ReportService::class); // true only when explicitly bound/resolved singleton
Autowiring limits
Container can autowire only instantiable classes with resolvable class-typed constructor dependencies. Interfaces must be explicitly bound. Builtin/scalar constructor params must have defaults or be resolved via explicit factory binding.
Failure behavior
Missing services and unresolved interface dependencies throw ServiceNotFoundException. Invalid autowiring state (non-instantiable class, unresolved constructor parameter without default, missing dependency class) throws ContainerException.
Explicit container access
Use $container->get() only where the container is explicitly available, typically inside service providers, factories and framework resolver infrastructure. Application runtime code should receive dependencies through constructors.
$container->singleton(ReportExporter::class, static function (ContainerInterface $container): ReportExporter {
return new ReportExporter(
$container->get(LoggerInterface::class),
);
});
Preferred registration model
Prefer constructor injection and explicit registration through service providers. Application runtime code should not use the container as a service locator; provider factories are the normal place for explicit container access.
final class AppServiceProvider implements ServiceProviderInterface
{
public function register(ContainerInterface $container): void
{
$container->singleton(ApiClientInterface::class, ApiClient::class);
}
}