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

Di Container Laravel Package

sanmai/di-container

A straightforward PSR-11 dependency injection container with zero-configuration autowiring. It resolves constructor dependencies via reflection, reuses created objects, maps interfaces to concrete implementations, and supports builder objects for complex construction.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

  • This is a standalone, PSR-11 autowiring container, not a Laravel package. There is no service provider, no facade, no config file, no publishable assets, no Laravel discovery metadata. It does not integrate with Illuminate\Container — it competes with it.
  • In a Laravel application, the framework container is not an optional utility; it is the backbone of routing, middleware resolution, controller method injection, event dispatch, queue workers, facades, and package providers. Adopting sanmai/di-container as the application container is effectively a framework replacement, not a library adoption. That is out of scope for a product decision.
  • The realistic architectural fit is narrower and legitimate: framework-agnostic code we own or ship — extracted domain libraries, SDKs, CLI tools, internal microservices, and package code that must not depend on illuminate/*. The author's stated motivation (Infection's own wiring) is the same shape of problem.
  • Design posture is conservative and defensible: constructor-only injection, no property/method injection, no naming conventions, no implicit interface guessing unless exactly one factory produces a compatible type. This is good for determinism and static analysis, and bad for teams socialized on Laravel's contextual and tag-based bindings.

Integration feasibility

  • Low as a Laravel container replacement; medium as an internal dependency of a standalone library; high as a candidate only if we first prove the library genuinely cannot accept a PSR-11 container from the caller.
  • The critical feasibility question is whether we need a container at all. If a library only consumes dependencies, it should type-hint Psr\Container\ContainerInterface and let Laravel pass its own container — which already satisfies PSR-11. In that pattern, sanmai/di-container is unnecessary. It adds value only when a component must supply a working default container for non-Laravel consumers.
  • Effort to wire it inside a standalone component: roughly 1–3 engineer-days for registration plus tests. Effort to retrofit it into the Laravel app kernel: weeks, with high regression probability and no product upside. The asymmetry should drive the decision on its own.

Technical risk

  • Adoption risk (highest). 7 stars, 0 dependents, effectively single-maintainer. No downstream ecosystem evidence means no one else is absorbing the integration edge cases for us.
  • Pre-1.0 API surface. Releases are 0.1.x. Semver permits breaking changes in minor bumps; we have already seen iterative churn in set()/bind()/inject() and type-annotation relaxations across 0.1.6–0.1.12. Pin exactly and be prepared to fork.
  • Documented omission of circular dependency detection. This is not a stylistic gap; it converts a composition mistake into unbounded reflection recursion, i.e. a memory-exhaustion crash instead of a clear exception. That is a production failure mode, not a developer convenience.
  • Documentation inconsistency. The README uses DIContainer\Container; internal notes reference Sanmai\DI\Container. Resolve the real namespace from the tag before any spike — a mismatch here signals documentation drift we will be debugging against.
  • No scope/lifecycle model beyond "created once and reused." No request scope, no deferred/lazy proxies, no compile step, no reflection cache. This matters under long-running workers (see Operational Impact).
  • Positive signals. BSD-3-Clause (permissive, commercially safe), PSR-11 v1 and v2 supported, CI exercises PHP 8.5, PHPStan at max level on fixtures, covariant Builder template for static analysis, and a PHPBench suite. Engineering hygiene is better than the star count implies.

Key questions

  1. What concrete problem does this solve that Illuminate\Container or a plain Psr\Container\ContainerInterface type-hint does not?
  2. Is the target component a Laravel application module or a genuinely framework-independent library/service? If the former, this evaluation ends.
  3. Can the consumer accept an injected PSR-11 container rather than requiring us to ship one? If yes, we ship zero container code.
  4. Who owns the fork if the maintainer stops? What is our patch SLA for a pre-1.0 dependency in a shipped artifact?
  5. Does this component run under Octane, Horizon, or queue workers where a singleton container persists across requests?
  6. Does the dependency graph contain any interface with more than one plausible implementation? The container refuses to guess, so every such case becomes mandatory explicit registration.

Integration Approach

Stack fit

  • Poor-to-non-existent inside the Laravel application layer; acceptable-to-good inside a Composer package we publish or a service bootstrapped without the framework.
  • Treat it as an internal implementation detail of a standalone component, never as a peer to Illuminate\Container. Do not register it in a service provider, do not alias it to ContainerInterface in the app, and do not inject it into controllers or jobs — doing so makes it reachable from framework-managed code and invites two competing graphs.
  • Required PHP and PSR-11 constraints are satisfied by any modern Laravel codebase, so there is no compatibility blocker — only an architectural one.

Migration path

  • There is no migration path for an existing Laravel application, and none should be attempted. Any proposal to swap the app container should be rejected at triage.
  • The only legitimate "migration" is extraction: take an existing self-contained module, strip its Illuminate\* imports, introduce a composition root wired with sanmai/di-container, and expose the module to Laravel via a thin adapter that lets Laravel's container satisfy the module's ContainerInterface dependency.
  • For brand-new packages, start with the Builder interface rather than closures — builders get constructor injection, are independently testable, and keep the container configuration declarative.

Compatibility

  • PSR-11 v1 and v2 are both supported, so the artifact can sit behind Psr\Container\ContainerInterface and remain swappable.
  • No Laravel-version coupling exists because nothing in the package touches the framework — which is simultaneously its safety property and its irrelevance to the app layer.
  • Two integration constraints to design around from day one: no variadic/composite constructor parameters, and no property or method injection. Both are common in Laravel-style code and will surface at the seam during extraction.

Sequencing

  1. Spike (1–2 days). Confirm the published namespace from the tag, build a throwaway composition root for one real extracted component, and record every constructor that the container refuses to resolve.
  2. Decide the interface strategy. Walk the graph and enumerate interfaces with more than one candidate implementation; each becomes explicit registration or the component is not a fit.
  3. Extract behind PSR-11. Ship the component with a caller-supplied ContainerInterface; make sanmai/di-container the default used only when no container is provided.
  4. Adapter in Laravel. A single service provider in the host app that maps the component's entry points onto Illuminate\Container. This is the only Laravel-aware code, and it stays ours.
  5. Only then consider a second component. Do not generalize to app-wide usage at any point.

Operational Impact

Maintenance

  • Low code volume, but ownership shifts to us. With one maintainer and zero dependents, we are effectively the upstream. Budget for pinned-version upgrades and a likely local fork; treat composer.json constraints as 0.1.x with a lockfile and a documented upgrade owner.
  • Ongoing cost is dominated by composition-root upkeep: every new constructor dependency in the extracted component needs a resolvable path. That is cheap and explicit, which is the point — but it is a permanent, visible tax that the team must accept rather than discover.
  • Static analysis is a real mitigation: PHPStan at max level with the covariant Builder template catches return-type drift at CI time rather than at container resolution time.

Support

  • No vendor support, no SLA, no security policy documented, no CVE history to review. BSD-3-Clause means we can patch and redistribute, which is the mitigation — but the patch capability must exist on the team before adoption, not after.
  • Internal support burden is concentrated in one or two engineers who understand the composition root. That is a single point of failure for a component that may be consumed by other teams; require a written runbook as an exit criterion for the pilot.

Scaling

  • Resolution is reflection-based with no compile step and no cache. Cost is per-object-creation, not per-request, so it amortizes to near-zero in a short-lived PHP-FPM request that resolves each service once. That is acceptable.
  • Under long-running workers (Octane, Horizon, queue daemons), "objects are created once and reused" becomes a state-retention hazard. Singletons and inject()-provided instances persist for the worker's lifetime. Any service holding request-scoped state — authenticated user, correlation ID, request payload, open transaction — will leak across jobs and requests. This must be an explicit design rule or the pilot will fail in a way that is hard to diagnose.
  • Horizontal scale: irrelevant — the container is in-process and adds no shared state. The scaling concern is entirely about worker lifetime.

Failure modes

  • Circular dependency → unbounded recursion, memory exhaustion, worker death. No guard exists by design. Mitigation: a CI test that resolves every registered service, plus a hard memory limit on workers.
  • Ambiguous interface → container refuses to guess and throws at resolution time. Deterministic but late; a missing registration surfaces as a runtime failure on the resolution path, not at boot. Mitigation: a container-compile smoke test in CI.
  • Unresolvable constructor parameter (variadic, scalar without binding, union type) → exception on first resolution of the affected graph, typically during a request. Mitigation: eager resolution of the full graph in a health check.
  • Doc/namespace drift → integration written against the wrong class name, failing at autoload. Cheap to detect, but a signal to verify against the tagged release rather than the README.
  • Upstream break in a 0.1.x bump → silent behavioral change in a pinned but auto-updated dependency. Mitigation: hard pin plus renovate review gate.

Ramp-up

  • API surface is small (get, set, bind, inject, Builder), so mechanical onboarding is under a day for a mid-level engineer.
  • The real ramp is conceptual: engineers fluent in Laravel's implicit autowiring and contextual binding will expect the container to resolve ambiguities for them. It will not, and it will fail at runtime when it cannot. Invest in one design note covering (a) explicit registration for ambiguous interfaces, (b) constructor-only injection, (c) request-state discipline under long-running workers.
  • Recommend a hard gate on the pilot: one component, one owner, one runbook, full-graph resolution test in CI, and a documented fork plan — before a second team touches it.
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.
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log