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

slick/di

Slick\DI is a lightweight dependency injection container for PHP that wires services through autowiring, explicit bindings, and lazy resolution. It offers a small, PSR-11 friendly API for managing object lifecycles in Laravel, Slim, and standalone applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Add the package with Composer and remember that slick/di is a PSR-11 container first — almost everything you do day-to-day routes through Psr\Container\ContainerInterface:

composer require slick/di

As of v2.10.0 the things worth reading first are:

  • Slick\Di\Container / Slick\Di\ContainerBuilder — the entry point and where you register definitions.
  • The Definition / definition-builder classes.
  • The #[Autowire] attribute (new in 2.10.0) — used on setters, applied automatically at object creation time.

That attribute is the headline change: it makes setter injection a first-class, container-driven feature rather than something you wire manually.

A minimal first use case — register a service and pull it back:

use Slick\Di\ContainerBuilder;

$container = (new ContainerBuilder())->getContainer();

// Concrete classes resolve with no registration when constructors are type-hinted:
$mailer = $container->get(\App\Mail\Mailer::class);

Then wire it into the rest of your app by type-hinting ContainerInterface wherever you need lazy resolution, or — preferably — inject the services themselves and keep the container at the composition root only.

Implementation Patterns

Constructor injection at the edges. Treat the container as something that only bootstraps the application. Controllers, commands, and services should receive their dependencies via constructor arguments; the container (or the framework's resolver) builds them once at the entry point.

Setter injection with #[Autowire] (2.10.0). For optional collaborators or genuinely circular graphs, mark a setter and let the container invoke it during creation:

use Slick\Di\Attribute\Autowire;

class ReportBuilder
{
    private ?LoggerInterface $logger = null;

    #[Autowire]
    public function setLogger(LoggerInterface $logger): void
    {
        $this->logger = $logger;
    }
}

Prefer this over lazy proxies for cycles, and over a service-locator call inside the class. Keep setters idempotent — they run on creation, so anything they do should be safe to redo.

Bind interfaces to implementations. The core reason to use the container is swapping implementations. Register a definition so MailerInterface resolves to a concrete SmtpMailer, and test doubles can be swapped in tests by rebuilding the container with an override.

Scalars resolve by parameter name (2.10.0). A string argument no longer hard-fails: the container looks up a service under the parameter's name. So a constructor argument $apiKey will pick up a definition registered as apiKey. This turns parameter naming into a wiring contract — see the gotchas.

Nullable dependencies degrade to null (2.10.0). A nullable argument not present in the container is set to null rather than throwing. Use this deliberately for optional integrations; don't let it silently swallow required ones.

Singletons vs. factories. Distinguish shared instances from fresh-per-resolve factories. Register stateless services (a logger, a config bag) as shared; register anything holding per-request state (a request context, a job payload) as a factory so you don't leak state between resolutions.

Autowiring for your own classes. Let reflection resolve concrete classes with type-hinted constructors; only write explicit definitions where you need a specific implementation, a scalar config value, or a named instance. This keeps the registration list small and readable.

Definition builders for complex services. When construction is non-trivial (needs a config array, a callable, or a factory method), define the service with the builder API rather than a closure that does everything — it's easier to test and to override.

Integration in a CLI or queue worker. Because resolution is lazy, you can build the container once per process and resolve only the handlers you actually need; this matters in long-running workers where eagerly instantiating everything is wasteful.

Testing hook. Keep a helper that builds a container with your production definitions plus test overrides. Resolving from that container in tests exercises the same wiring your app uses — including #[Autowire] setters and scalar-by-name lookups — catching missing bindings early.

Gotchas and Tips

  • PSR-11 exceptions are your debugger. A missing binding throws NotFoundExceptionInterface (usually Slick\Di\Exception\...). When you see it, check that the interface — not just the concrete class — was registered, since autowiring cannot guess an interface's implementation.
  • Name-based scalar resolution is convenient and fragile. Since 2.10.0 a string param is looked up by its name, so renaming $apiKey to $key silently changes (or breaks) what gets injected. Register scalar services under names that match your parameter names exactly, or define those arguments explicitly.
  • Nullable now means "optional" — including when you didn't mean it. A nullable argument that is missing becomes null instead of failing. A typo in a binding now yields a null collaborator at runtime rather than an error at resolution. Add your own guard clauses in the constructor/setter if null is not actually acceptable.
  • #[Autowire] setters run at creation time only. If you build the object yourself (new ReportBuilder()) instead of resolving it from the container, the setter is never called and the dependency stays null. Only resolved objects get attribute wiring.
  • Circular dependencies fail at resolution time, not registration time. Two services depending on each other via constructors will blow up only when you call get(). A #[Autowire] setter is now the cleanest fix — prefer it over lazy proxies.
  • Autowiring still needs concrete, resolvable constructor params. Non-nullable scalars with no matching service name and no default still cannot be built — register them explicitly. Union types and untyped params remain unreliable.
  • Beware shared-state singletons in tests. A cached singleton from one test can leak into the next if you reuse the container; rebuild the container per test or reset it, otherwise you get ghost failures.
  • Config quirks. Small Slick packages historically ship with minimal config files (some keys default to null or empty arrays). Dump the resolved config early in a new project to confirm defaults rather than assuming.
  • Removed docs. v2.10.0 removed the in-repo documentation in favour of GitHub Pages. Pin your reference to a specific version — the README no longer describes the shipped behaviour, so verify new features (#[Autowire], scalar-by-name, nullable fallback) against a fresh install rather than older docs.
  • Extension points. The container builder and definition classes are the intended extension surface — subclass or pass definitions there instead of reflecting on the container internals. If you find yourself calling non-interface methods on the container from application code, you've coupled to the implementation.
  • Still a lightweight container. Despite now being at v2.10.0, keep expectations calibrated: treat it as a PSR-11 implementation plus autowiring, not a framework-grade container. Wrap it behind your own factory so you can swap in Symfony DI or PHP-DI later without touching application code, and confirm advanced features (decorators, tags, compile-time checks) actually exist before depending on them.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource