Clean Framework · DOCUMENTATION
Dependency container and service providers
Dependency container and service providers
Bounded candidate reference — 2026-10-20: 0.2.0-rc.1 is committed locally through 84f415b3098af5653577b2c65eea31fca21df79c, unpublished and not production-approved; stable PHP >=8.5.11 <8.6.0 is required. This is documentation, not adoption: this knowledge base retains its installed 0.1.0-rc.1 dependency and PHP 8.2.11 local profile. Dated PHP 8.2 evidence is historical; earlier dirty-source reports retain their original test provenance, not retroactive clean-commit proof. Candidate examples are illustrative: API signatures were reviewed, but candidate code was not executed by this editorial update. See current checkpoint, open criteria and adoption boundary.
Container implements ContainerInterface while retaining the concrete class name used by the extracted framework. New replaceable boundaries may depend on the interface; composition code uses the concrete type when it needs explicit override APIs.
Lifecycles
factory()is transient and returns a new object for each resolution.singleton()andinstance()retain one object for the process.scoped()retains one object only inside an active request or job scope.
Scoped resolution outside beginScope() or runInScope() fails. Kernels and workers must call resetScope() in a finally block; runInScope() provides that guarantee directly. Nested scopes are rejected so identity, transaction, and request ownership cannot become ambiguous.
Aliases map contracts to registered targets. Duplicate identifiers fail by default. Composition code must use an explicitly named overrideFactory(), overrideSingleton(), overrideScoped(), or overrideInstance() method when replacement is intentional. Calling freeze() ends composition and prevents all later graph mutation.
Circular dependency errors include the safe identifier chain when configured for DEV/TEST diagnostics. Zero-argument fallback construction exists for compatibility and can be disabled through the constructor; the container does not perform reflection autowiring.
Providers
ServiceProviderRegistry orders providers by ascending priority and insertion order. It runs every register() method, freezes the container, and only then runs every boot() method. Registration defines dependencies without external I/O. Boot may resolve registered services but cannot rewrite the graph.
$container = new Container(allowZeroArgumentConstruction: false);
$providers = new ServiceProviderRegistry($container);
$providers->add(new ApplicationServiceProvider(), priority: 10);
$providers->registerAndBoot();Provider boot is not permission to connect to a provider or database eagerly. Adapters remain lazy so merely booting a web request or CLI command does not open unused external resources.
Editorial provenance
Source: docs/CONTAINER.md. Source SHA-256: 550ce0f82683cf8742bdeb78315148bba16dffb3bb54a36c8e86d9f18d585562.
Framework candidate reference; editorial checkpoint 2026-10-20. See candidate status and adoption boundary.