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 Laravel Package

slince/di

A lightweight, PSR-11 compatible dependency injection container for PHP. Slince DI supports constructor and setter injection, service providers, aliases, lazy loading, and shared instances, giving you a simple, flexible foundation for managing object dependencies in small to medium applications.

Deep Wiki
Context7

Getting Started

composer require slince/di

slince/di is a small PSR-11 container (Slince\Di\Container implements Psr\Container\ContainerInterface). The fastest way to get value is to stop hand-wiring object graphs in your bootstrap/front-controller and let the container build them.

The three files worth reading first:

  • src/Container.php — set(), get(), has(), delegation, parameter handling.
  • src/Definition.php — the object that describes how to build a service (class, arguments, method calls, shared flag).
  • src/Reference.php + src/Exception/ — how one service points at another, and the PSR-11 exception types.

Minimal first use case:

use Slince\Di\Container;

$container = new Container();

// Register by class name; constructor dependencies are autowired via reflection.
$container->set(UserRepository::class);

$repo = $container->get(UserRepository::class);

That is the whole pitch: for simple classes with type-hinted constructor parameters, set(Foo::class) is often optional — get() will auto-resolve a concrete, non-abstract class if your version has autowiring enabled by default. Start by replacing one new Foo(new Bar()) chain in a bootstrap file, run your test suite, and expand outward. Do not attempt to convert the whole application on day one; a container adopted late is a composition-root tool, not a rewrite.

Implementation Patterns

Four registration styles, one for each situation.

// 1. Class name — autowired
$container->set(Mailer::class);

// 2. Closure — when construction needs logic or reads config
$container->set(PDO::class, function (Container $c) {
    return new PDO($c->getParameter('db.dsn'));
});

// 3. Definition object — explicit arguments, setters, sharing
use Slince\Di\Definition;
use Slince\Di\Reference;

$definition = (new Definition(UserRepository::class))
    ->setArguments([new Reference(PDO::class)])
    ->addMethodCall('setLogger', [new Reference(Logger::class)])
    ->setShared(true);

$container->set(UserRepository::class, $definition);

// 4. A ready-made object — useful for mocks, config objects, PDO handles
$container->set('clock', new SystemClock());

Interface → implementation aliasing. Register the concrete class, then point the interface at it with a Reference. Consumers type-hint the interface; only the bootstrap knows the concrete name. This is the single highest-leverage pattern in the package — it is what makes the container worth having in a legacy codebase.

Shared vs. prototype. Services are new instances per get() unless marked shared. Repositories, loggers, and connection objects should be shared; value objects and request-scoped objects should not. Pick this deliberately per service rather than defaulting everything to shared, because a shared service that caches state between requests will bite you in long-running workers.

Group definitions into providers. Rather than one 300-line bootstrap, write small functions or classes that accept the container and register one concern (registerDatabase($c), registerHttp($c)). This keeps the wiring readable and lets tests compose only the providers they need.

Parameters as a config layer. Use setParameter() / getParameter() for DSNs, feature flags, and paths, and reference them from Definition arguments instead of hardcoding. Keep the raw %placeholder% strings out of closure bodies — inside a closure, read getParameter() directly so the failure mode is a clear exception rather than a literal string being injected into a service.

Testing pattern. In setUp(), build a fresh container, register the real graph, then overwrite the leaves with fakes: $container->set(Mailer::class, $fakeMailer). Because get() resolves lazily, one override replaces the dependency everywhere without touching constructors. This is the day-to-day payoff — assert against the container-built graph, not against manually assembled objects.

Integration point. Instantiate the container once in the front controller (or in a framework service provider), pass it to the router/console kernel, and resolve controllers/handlers through it. If the framework already has its own container, use slince/di as the delegation target for the parts of the app you control and bridge only at the boundary — running two containers side by side with interleaved get() calls is a debugging tax.

Gotchas and Tips

  • Autowiring dies on scalars. Untyped parameters, scalar parameters, union types, and nullable-without-default parameters cannot be resolved by reflection. Any class with such a constructor must have an explicit Definition with arguments, or it will fail at get() time — usually deep in a request, not at boot. Smoke-test every top-level service in CI (foreach ($ids as $id) { $container->get($id); }).
  • Circular dependencies produce confusing failures. A → B → A will recurse or throw depending on the version. Break the cycle with setter injection (addMethodCall) or by injecting a factory closure instead of the service itself.
  • has() is cheap, get() is not. Use has() for optional integrations and get() only when you are sure the service exists. PSR-11 requires has() not to throw, and get() on a missing ID to throw NotFoundExceptionInterface — catch the interfaces, not the concrete exception classes, so container swaps in tests keep working.
  • ID consistency. Foo::class and 'Foo' and 'foo' are different IDs unless your version normalizes them. Pick FQCNs as the canonical ID and alias anything else; mixed casing produces "class not found" errors that look like autoloading bugs.
  • Object registrations are de facto singletons. set('x', new Foo()) returns the same instance forever and is not autowired — don't use it as a shortcut for a service that should be prototype-scoped.
  • Exact set() signature varies by version. In some releases the third argument is a shared flag; in others sharing lives only on Definition. Check Container::set() in your installed tag before relying on it, and pin the version in composer.json — this package moves and the README lags.
  • Reflection cost. Autowiring reflects on every uncached resolution. For hot paths or high-throughput endpoints, either pre-register Definitions or build the graph once at boot and cache the container construction. Profile before optimizing, but know the cost exists.
  • Debugging is silent by default. When a resolution chain fails deep in the graph, the thrown exception rarely names the full path. Wrap get() in your bootstrap with a log line of the requested ID, or subclass Container and override the instance-creation step to trace resolution order. Subclassing is also the supported extension point for custom instantiation (e.g., proxying, decorators).
  • Resist the service locator. The container is a composition-root tool. Passing Container into domain classes and calling get() inside business logic trades constructor injection for invisible dependencies. Keep get() calls in bootstrap, controllers, and console commands only.
  • Long-lived workers need scrutiny. Under RoadRunner/Swoole/queue workers, shared services survive between jobs. Anything holding request state, DB transactions, or user context must be explicitly reset or made prototype-scoped.
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.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle