Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Container Laravel Package

league/container

League/Container is a fast, lightweight, PSR-11 compliant dependency injection container for PHP. It offers constructor autowiring, service providers, inflectors, and lazy loading out of the box, requires no configuration, and supports PHP 8.3, 8.4, and 8.5.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. The central architectural fact is that Laravel already ships a first-class DI container (Illuminate\Container\Container), and it is PSR-11 compliant via Illuminate\Contracts\Container\Container extends Psr\Container\ContainerInterface. Adopting league/container therefore does not "add DI" — it adds a second container. That is defensible only in bounded contexts: framework-agnostic libraries you publish or share across services, extracted domain packages that must not depend on Illuminate, CLI/worker binaries outside the HTTP app, and test harnesses that need a clean PSR-11 graph without booting the framework. Wholesale replacement of the Laravel container is not an architecture fit; it invalidates facades, contextual binding, route-model binding, queue payload hydration, and Octane request scoping.

Integration feasibility. High mechanically, low semantically. The API surface is small and PSR-11 standard: add/addShared, get, has, delegates, ServiceProviderInterface with provides(), ReflectionContainer for auto-wiring, Container::call, plus v5.1 #[Inject]/#[Resolve] attributes and the v5.2 event system (OnDefineEvent, BeforeResolveEvent, DefinitionResolvedEvent, ServiceResolvedEvent). Because both sides speak PSR-11, a bidirectional delegate bridge is trivial to write. The hard part is governance: once two containers exist, "which container owns this service" becomes an unwritten convention that decays into a defect class.

Technical risk.

  • Dual-container drift. A service registered in both graphs, or resolved from the wrong one, produces a silently different instance — the worst failure mode because it looks like a state bug, not a wiring bug.
  • Deprecation debt on arrival. v5.2.0 deprecates Container::inflector() in favour of afterResolve()/events, scheduled for removal in v6.0, and removes EventAwareContainerInterface from the contract surface (EventAwareTrait on the concrete class only). Any code typed against that interface is already broken; adopting the deprecated inflector now guarantees a v6 migration.
  • Version floor. v5.x requires PHP >=8.1, README targets 8.3–8.5. If any service in the fleet is on 8.0, you are pinned to 4.x.
  • Long-running process state. ReflectionContainer caches resolutions; shared definitions and event listeners persist. Under Octane or queue workers this needs explicit reset per request/job — a real operational hazard, not a theoretical one.
  • Bus factor. Single primary maintainer and a low ecosystem signal in the supplied data (dependents: 0, which contradicts League's real-world usage and should be verified against Packagist before it informs any decision). MIT licence and a clean history mitigate this — forkability is the escape hatch.
  • No container compilation yet. v5.0.0 describes "prep for future updates and container compilation"; there is no AOT-compiled container today, so no performance argument for adoption.

Key questions.

  1. Which services, concretely, are being resolved today by something that cannot use the Laravel container?
  2. Is the driver portability (library must run outside Laravel) or capability (something Laravel's container cannot do)? Only the first justifies the cost.
  3. What is the PHP floor across all target services, and does the chosen version's psr/container constraint resolve cleanly against each Laravel version in the matrix?
  4. Who owns the bridge, and who is paged when resolution fails in production?
  5. Are we adopting the v5.2 event system or the deprecated inflector, and what is the v6.0 timeline?

Integration Approach

Stack fit. Position league/container as an inner container for portable code, with Laravel's container as the outer composition root. Recommended pattern: league/container owns definitions inside extracted domain packages and shared libraries; Laravel's container owns the application, HTTP layer, and everything framework-coupled. The bridge is one adapter registered as a Laravel singleton, not a fleet of ad-hoc get() calls.

Migration path. Do not migrate the application container. Migrate packages, one at a time, each of which:

  1. Declares definitions in a ServiceProviderInterface implementation with an explicit provides() list (mandatory since 4.0.0 — no class-property shortcut).
  2. Exposes a thin Laravel ServiceProvider that registers those definitions into the bridge.
  3. Keeps Illuminate out of its composer.json beyond illuminate/support for the adapter.

For existing Orno\Di-era or 3.x/4.x code, use the changelog as a migration ledger: 4.0.0 changed shared → addShared and dropped the third $shared argument from add; 5.0.0 made definition overwriting opt-in (disabled by default) and moved the floor to PHP 8.1.

Compatibility. Confirm the psr/container constraint resolves against your Laravel versions before anything else — history here is instructive: 3.3.5 added ^2.0.0, 3.4.0 removed it as irreconcilable, 4.0.0 re-adopted it. Also note auto-wiring moved out of the core Container into the ReflectionContainer delegate in 2.0.0 and is off by default; teams expecting Laravel-style implicit resolution will be surprised. Union types are explicitly unsupported for auto-wiring (5.1.0) — that constraint will surface in real domain code.

Sequencing.

  1. Spike (1 week). Build the bridge both directions; prove get() interop, shared-instance identity, and Octane reset behaviour. Decide bridge direction explicitly and document it.
  2. Inventory. Enumerate every resolution site; classify as framework-coupled (stays) or portable (candidate). Expect the portable set to be much smaller than assumed.
  3. Pilot. One extracted domain package, definition-based, no attributes, no events. Ship it.
  4. Standardise. Publish the "which container" decision rule and the provides() contract as team convention; add static analysis so missing definitions fail in CI, not at runtime.
  5. Adopt attributes/events only after the pilot is stable — #[Inject]/#[Resolve] and the v5.2 event API are new surface area and the inflector is already deprecated.
  6. Reassess at v6.0. Budget the inflector removal now.

Operational Impact

Maintenance. Every new service forces a routing decision between two containers; that decision cost is permanent and is the dominant long-run expense, dwarfing the package's own upgrade churn. Definitions live in PHP rather than Laravel's config, so they are greppable and reviewable — an advantage over service-provider sprawl. The changelog is unusually disciplined (per-release files back to 1.0.0), which makes upgrade forecasting cheap. Budget one minor upgrade per quarter and one major every ~18–24 months.

Support. Documented at container.thephpleague.com with a versioned 5.x doc tree, Jekyll-built from docs/. Test suite is Pest with PHPStan at level 8 — strong signal for a small package. PER-CS, PSR-4, PSR-11 compliance are stated and CI-enforced. Security contact is a personal email rather than a private disclosure channel; for an internal dependency that is acceptable, but it should be an explicit accepted risk. MIT licence means the ultimate support fallback is a fork.

Scaling. Resolution is cheap and ReflectionContainer caches, so throughput is not the concern. The scaling concern is process lifetime: under Octane, Swoole, or long-lived queue workers, shared definitions and registered event listeners accumulate across requests unless you reset the container (or scope it per-request/per-job). Treat "the container is request-scoped" as an invariant enforced by the bridge, not by convention. Tag-based resolution (addTag, plus the automatic 'shared' tag introduced in 5.2.0) is the lever for batch resolution without N lookups.

Failure modes.

  • NotFoundException / ContainerException from PSR-11 interfaces — good, typed, catchable. Since 5.2.0, unsatisfied constructor dependencies raise a ContainerException with actionable guidance instead of a raw ArgumentCountError, which materially shortens incident triage.
  • Silent dual-container divergence — highest-severity, lowest-visibility. Mitigate with a single bridge and a grep-able rule that application code never touches the inner container directly.
  • Recursive definitions — historically painful (fixed in 4.2.1, 3.3.0), so pin a floor of >=4.2.4 or, preferably, 5.x.
  • Provider contract violations — a provider claiming a service it does not register previously caused stack overflow (3.3.0) and duplicate aggregation (3.2.2); ensure provides() is generated from or tested against the actual definitions.
  • Test leakage — shared instances persisting between test cases; the container must be rebuilt per test.
  • Attribute-based wiring failures fail at resolution time, not compile time; add a smoke test that resolves every registered definition.

Ramp-up. The API is small enough that a mid-level PHP developer is productive in one to two days; the organisational ramp-up is the real cost — the team must internalise PSR-11 semantics, the definition-vs-reflection distinction, and the two-container routing rule. Estimate ~1 engineer-week of documentation and pairing to make the pattern self-sustaining, and designate a single owner for the bridge. Because the supplied scores show low opportunity (53.56) against a modest composite (25.7), treat adoption as an enabler for portability, not as a modernization win in its own right: for a Laravel-only estate the correct recommendation is usually to decline, and to revisit only when a concrete framework-agnostic distribution requirement exists.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log