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
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
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
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
make(string $abstract, array $overrides = []): mixed
call(callable|array $callable, array $overrides = []): mixed
makeContextual(string $abstract, ?string $consumer): mixedmake()
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.
$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()
makeContextual(string $abstract, ?string $consumer): mixedThe 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
register(string $providerClass): staticInstantiates $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.
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.
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.
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.
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.
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.