Package · di

API Reference

Complete reference for the public surface of Winter DI. This is the authoritative source for signatures and defaults; the guides and deep-dive pages link here.

Container

final class Container implements Psr\Container\ContainerInterface. The registry and resolver. It self-registers, so Container and ContainerInterface can be injected as dependencies.

Initialisation

php
Container::init(): static
Container::getInstance(): static
Method Description
init() Creates a new container and stores it as the process-wide singleton. Call once at bootstrap. Returns the instance for fluent chaining.
getInstance() Returns the initialised container. Throws ContainerException if init() was never called.

PSR-11

php
get(string $id): mixed
has(string $id): bool
Method Description
get($id) Alias for make($id). Throws NotFoundException if $id has no binding and is not an instantiable class.
has($id) true if $id has a binding, a resolved/set() value, or matches an existing class name (class_exists).

Registration

php
bind(string $abstract, string|callable $concrete): static
singleton(string $abstract, string|callable|null $concrete = null): static
transient(string $abstract, string|callable|null $concrete = null): static
request(string $abstract, string|callable|null $concrete = null): static
contextual(string $abstract, callable $factory): static
set(string $id, mixed $value): static
Method Scope Description
bind() transient Maps $abstract to a concrete class or factory closure. A new instance on every resolution.
singleton() singleton One shared instance per process. $concrete defaults to $abstract (self-bind).
transient() transient Like bind() but allows self-binding when $concrete is null.
request() request One instance per HTTP request / coroutine. $concrete defaults to $abstract.
contextual() Consumer-aware factory fn(Container $c, ?string $consumer). An injection-time overlay; result never cached. See makeContextual().
set() Stores a scalar or pre-built instance under a named key. Retrieve via make($id) or #[Inject('id')].

A factory closure passed to bind() / singleton() / transient() / request() receives the container: fn(Container $c) => new Service($c->make(Dep::class)).

Manual registration overrides attributes

A bind()/singleton()/request() call always takes priority over a class’s scope attribute. Re-registering the same abstract replaces the previous binding.

Resolution

php
make(string $abstract, array $overrides = []): mixed
call(callable|array $callable, array $overrides = []): mixed
makeContextual(string $abstract, ?string $consumer): mixed

make()

Resolves an abstract — a class, interface, or named value.

Parameter Type Default Description
$abstract string Class/interface name or named-value key.
$overrides array [] Named parameter overrides, keyed by parameter name. Bypasses autowiring for those parameters.

Resolution order: (1) already-resolved singleton / set() value, (2) request-scope coroutine cache, (3) manual binding, (4) autowire by class name. Passing $overrides always builds a fresh instance and is never cached. Throws NotFoundException if unresolvable, ContainerException on a circular dependency.

call()

Invokes a method or closure with its parameters resolved from the container.

php
$c->call([UserController::class, 'index']);   // resolve class, then call
$c->call([$controller, 'store']);              // existing instance
$c->call(fn(UserService $s) => $s->all());     // closure
$c->call([ImportJob::class, 'run'], ['chunkSize' => 100]);  // with overrides
Parameter Type Default Description
$callable callable|array [class-string, method], [object, method], or any callable/closure.
$overrides array [] Named parameter overrides, keyed by parameter name.

makeContextual()

php
makeContextual(string $abstract, ?string $consumer): mixed

The resolver’s entry point for contextual injection. If a contextual() factory is registered for $abstract, it is invoked with $consumer (result not cached); otherwise delegates to make($abstract). Application code normally uses make() — this exists for the injection machinery. The contextual overlay applies to injection only (constructor / method / property); a direct make()/get() uses the regular binding.

Providers

php
register(string $providerClass): static

Instantiates $providerClass, verifies it extends ServiceProvider, and runs its register() immediately. Throws ContainerException if the class does not extend ServiceProvider.

Scanner

Walks a project tree once and dispatches every discovered class to all registered collectors.

php
Scanner::run(string $rootDir, ?string $cache = null): static
  ->collect(CollectorInterface $collector): static
  ->exclude(array $dirs): static
  ->execute(): void
Method Description
run($rootDir, $cache) Creates a scanner for $rootDir. When $cache is a path: cache hit loads the FQCN list and skips the FS walk; cache miss walks and writes the list. null (default) always walks, never caches.
collect($collector) Registers a collector that receives every discovered class. Called in registration order.
exclude($dirs) Adds absolute directory paths to exclude. vendor/ is always excluded.
execute() Runs the scan. Abstract classes, interfaces, and traits are skipped before collectors run.

The cache file is a plain PHP file returning a string[] of FQCNs. Delete it to force a rescan. See Scanning & autodiscovery.

DICollector

final readonly class DICollector implements CollectorInterface. The built-in collector that registers classes carrying a scope attribute.

php
new DICollector(Container $container)
collect(string $class, ReflectionClass $ref): void
Class attribute Registration
#[Singleton] $container->singleton($class)
#[Request] $container->request($class)
#[Transient] $container->transient($class)

Classes with no scope attribute are ignored (they remain autowirable as transient).

CollectorInterface

Implement to plug custom logic into a Scanner pass.

php
interface CollectorInterface
{
  // @param class-string $class  FQCN
  // @param ReflectionClass $ref  reflection instance
  public function collect(string $class, ReflectionClass $ref): void;
}

collect() is called once per instantiable class, in a tight loop — keep it lightweight.

ServiceProvider

Abstract base for grouping bindings.

php
abstract class ServiceProvider
{
  abstract public function register(Container $c): void;
}

Register via $container->register(MyProvider::class). See Service providers.

ReflectionCache

Per-process cache for reflection objects — built once, reused for the process lifetime.

php
ReflectionCache::classOf(string $class): ReflectionClass
ReflectionCache::enumOf(string $enum): ReflectionEnum
ReflectionCache::method(string $class, string $method): ReflectionMethod
ReflectionCache::parameters(string $class, string $method): ReflectionParameter[]
Method Returns Notes
classOf($class) ReflectionClass Cached per class.
enumOf($enum) ReflectionEnum Cached per enum.
method($class, $method) ReflectionMethod Cached per class::method.
parameters($class, $method) ReflectionParameter[] Delegates to method(); shares its cache entry.

A public utility — see Reflection cache.

Exceptions

Both implement the PSR-11 exception interfaces and extend \RuntimeException.

Exception Implements Thrown when
NotFoundException Psr\Container\NotFoundExceptionInterface No binding for an id and it is not an instantiable class.
ContainerException Psr\Container\ContainerExceptionInterface Circular dependency, unresolvable parameter, uninitialised container, invalid provider, invalid #[Lazy] target.

Attributes

Reference tables for #[Singleton], #[Request], #[Transient], #[Autowired], #[Inject], and #[Lazy] live on the Attributes page.