di
-
DI Canon
One canonical DI path for container-managed classes — protected property attributes, no constructor arguments, validated at boot and enforced by lint:di.
-
Declaring a Service
#[AsService] makes a plain class a worker-scoped singleton the container will build and inject — and when you do not need it.
-
Readonly Injection
The default tier — one instance per worker, injected into a protected property, with optional injection for dependencies that may not be installed.
-
Mutable Injection
#[ExecutionScoped] opts a class into a per-execution clone; #[InjectAsMutable] marks the properties re-injected on that clone.
-
Factory Injection
#[InjectAsFactory] injects a factory that selects among a contract's implementations by backed-enum key — not a closure; execution-scoped implementations come back as a fresh per-execution instance.
-
Configuration Injection
#[Config] reads a scalar from the environment into a typed property, with a default in code — the only supported way a container-managed class reads env.
-
Service Contracts
One module declares an interface, implementations advertise themselves with SatisfiesServiceContract, and the active one is visible in contracts:list.
-
Resolving Service Contracts
Seeing which implementation is bound to a contract, using a resolver as a factory, and the Factory* naming convention for choosing by key.
-
Discovery Contributors
How a package teaches boot-time discovery to recognise its own attribute, with priority ordering and per-class error isolation.