Core

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);
    }
}