-
Notifications
You must be signed in to change notification settings - Fork 0
Migration Guide
This guide is for early adopters who pulled the container as a pre-release
dev-main snapshot before its first tagged, PSR-11-compliant release. The
stable API tightened several behaviours that the early snapshot got wrong or left
loose. Most call sites need only small adjustments.
If you are installing the package for the first time, you can skip this page — the rest of the wiki documents the current behaviour.
| Area | Early snapshot | Now |
|---|---|---|
| Minimum PHP | 7.4 | 8.1 |
set() return |
returned the resolved value | returns void
|
set() timing |
resolved the class eagerly | stores a definition, resolved lazily |
get() on unknown id |
returned the id string | throws NotFoundException
|
Closures passed to set()
|
stored and returned as-is | invoked as lazy factories, result cached |
| Resolution exceptions | implemented NotFoundExceptionInterface
|
implement ContainerExceptionInterface
|
DependencyIsNotInstantiable |
class name without Exception suffix |
renamed DependencyIsNotInstantiableException
|
| Union/intersection typed params | could fatal | safely fall back to default / null
|
| Circular dependencies | recursed until exhaustion | throw CircularDependencyException
|
The library uses mixed types and modern reflection handling. Update your
platform (and your own composer.json constraint) to PHP ^8.1.
The early snapshot built the class immediately inside set() and returned the
instance. The stable version stores a definition and builds it on first
get().
// Early snapshot
$service = $container->set(Service::class); // returned the instance
// Now
$container->set(Service::class); // returns void
$service = $container->get(Service::class); // build happens here, lazilyIf you relied on set()'s return value, switch to a get() immediately after,
or simply resolve when you actually need the service.
Previously, get('something-unregistered') silently returned the string
'something-unregistered'. That violated PSR-11. The stable version throws
NotFoundException:
// Early snapshot
$container->get('typo.key'); // 'typo.key' (silent, surprising)
// Now
$container->get('typo.key'); // throws NotFoundExceptionGuard with has() if an identifier may legitimately be absent:
if ($container->has('optional.key')) {
$value = $container->get('optional.key');
}Passing a Closure to set() used to store the closure itself, so get()
handed the closure back uninvoked. Now a closure is treated as a factory: it
is invoked with the container on first get(), and its return value is cached.
$container->set('pdo', fn ($c) => new PDO('sqlite::memory:'));
// Early snapshot
$container->get('pdo'); // the Closure object
// Now
$container->get('pdo'); // a PDO instance (closure invoked once)If you genuinely stored a closure as a value and want it back verbatim, wrap it so the definition is not itself a closure — for example return it from a factory:
$callable = fn () => 'hi';
$container->set('callable', fn () => $callable); // get('callable') === $callableDependencyIsNotInstantiableException and DependencyHasNoDefaultValueException
used to implement NotFoundExceptionInterface, which was semantically wrong —
they are build failures, not "missing entry" errors. They now extend
ContainerException and implement ContainerExceptionInterface.
// If you previously caught build failures as "not found":
catch (\Psr\Container\NotFoundExceptionInterface $e) { /* ... */ }
// Catch the base container interface (or ContainerException) instead:
catch (\Psr\Container\ContainerExceptionInterface $e) { /* ... */ }NotFoundException still implements NotFoundExceptionInterface, so genuine
"missing entry" catches are unaffected. See Exceptions.
InitPHP\Container\Exception\DependencyIsNotInstantiable →
InitPHP\Container\Exception\DependencyIsNotInstantiableException.
Update any use/catch referencing the old name. A new base
ContainerException and a CircularDependencyException were also added.
A constructor parameter typed as a union (A|B) or intersection (A&B) is no
longer passed to reflection methods that assume a single named type. Such
parameters now fall back to their default value or null. See
Autowiring → Union and intersection types.
A dependency cycle that previously recursed until PHP exhausted memory now throws
CircularDependencyException early with
a clear message.
- Bump your platform constraint to PHP
^8.1. - Replace any use of
set()'s return value with a followingget(). - Wrap optional lookups in
has()so they don't hitNotFoundException. - Re-check anywhere you passed a closure to
set()— it now runs as a factory. - Update
catchblocks: build failures areContainerExceptionInterface, notNotFoundExceptionInterface. - Rename
DependencyIsNotInstantiable→DependencyIsNotInstantiableException.
- Resolution & Caching — the current lifecycle in full.
- Exceptions — the current hierarchy and catching strategy.
- Binding & Factories — how definitions are interpreted now.
initphp/container · MIT License · part of the InitPHP family
Source · Issues · Discussions · Packagist · Contributing · Security Policy
Getting Started
Core Usage
Reference
Practical Guides
Migration & Help