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

Symfony Static Di Bundle Laravel Package

rvlt-digital/symfony-static-di-bundle

A Symfony bundle that adds static dependency injection support, helping you keep service wiring explicit and container configuration predictable. It integrates static DI patterns into Symfony applications for clearer setup, easier maintenance, and less runtime magic.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the bundle with Composer and register it in config/bundles.php:

composer require rvlt-digital/symfony-static-di-bundle
// config/bundles.php
return [
    // ...
    RvltDigital\StaticDiBundle\StaticDiBundle::class => ['all' => true],
];

Where to look first, in this order:

  1. The bundle's DependencyInjection/ directory — this is where the compiler pass (or passes) live. The pass is what decides which services get "exported" into the generated static container, so read the tag/attribute it looks for before you write any code against it.
  2. The Configuration.php / Extension class — this lists the actual config keys (output_dir, container_class, namespace, exclude, etc.). Do not assume defaults; the README is likely thin given the package's age, so treat the extension class as the source of truth.
  3. The generated output directory after a cache warmup — this is the artifact you'll actually consume at runtime. Run bin/console cache:clear (or whatever warms the container), then open the generated PHP file to confirm the shape of the API you're about to call.

First use case: replace a runtime ContainerInterface lookup in a long-running entrypoint (RoadRunner, Swoole, FrankenPHP worker script, or a plain CLI command) with a generated static accessor. The typical pattern is that after warmup you call something like:

$handler = \App\Generated\StaticContainer::get(App\Handler\OrderHandler::class);

Confirm the exact method name (get, getService, make) against the generated file before committing to it — this is the single API surface the rest of your code will depend on.

Implementation Patterns

Tag what you want exported, don't export everything. Static containers are usually intended for a curated set of entrypoints (message handlers, consumers, HTTP handlers in a worker), not the whole graph. A common pattern is to tag services explicitly:

services:
    App\Handler\OrderHandler:
        tags: ['static_di.export']

and let the bundle's compiler pass collect only those. If the bundle supports an attribute instead, prefer the attribute — it keeps the export list next to the class and survives service-id refactors.

Warm at build time, consume at runtime. The generated container is a deploy artifact. Wire it into your build pipeline:

bin/console cache:warmup --env=prod
# copy var/cache/prod (or configured output_dir) into the image

Treat the generated file as immutable in production. Any pattern that regenerates it on boot defeats the performance argument and reintroduces the cold-start cost you were trying to remove.

Bridge from existing autowiring. Keep normal Symfony DI for construction; use the static container only at the edge — the worker loop, the message consumer, the command dispatcher. Inside services, keep constructor injection. This keeps your code testable and means the static container is a thin adapter rather than a second, parallel DI system.

Integrate with a worker loop. The canonical workflow:

while ($payload = $transport->next()) {
    $handler = StaticContainer::get($payload['handler']);
    $handler($payload['message']);
}

Pre-resolve a map of message class => static accessor at worker boot to avoid a per-message lookup, and to keep the dependency on the generated class confined to one file.

Testing. Because the generated container is a plain PHP class, you can assert against it in a smoke test — instantiate each exported service and verify it's not null and implements the expected interface. This is the cheapest regression test for a compiler-pass-driven package and catches breakage when exports change.

Gotchas and Tips

  • The container is frozen at build time. Parameters resolved via %env()%, runtime feature flags, or anything computed at boot will not reflect changes unless you re-run the compiler pass. If you rely on env vars that differ per environment, verify they're baked correctly per image build.
  • Private services and inlining. Symfony aggressively inlines and removes private, unreferenced services. If an export target isn't public or isn't referenced by another public service, the compiler pass may not be able to reach it. Expect to mark exported services public: true in config or add a !public-aware reference in the pass.
  • Circular references. Static accessors constructed eagerly at first call can surface circular dependency errors that the lazy runtime container tolerated. If you see a resolution loop, resolve services lazily (a callable accessor) rather than at static init.
  • Debugging is manual. There's no debug:container for the generated class. When a service is missing, inspect the generated file directly and re-run cache:warmup -vvv to see compiler-pass output. Add a temporary dump() in the bundle's pass if the export logic is unclear.
  • Extension points. The two useful hooks are a custom compiler pass ordered before the bundle's export pass (to register additional tags/services) and overriding the output namespace/directory via the bundle config. If neither exists in this version, that's your first PR — the package is at 0 stars, so expect to own maintenance.
  • Maturity caveat. With no dependents and no stars, treat the bundle as experimental. Pin the exact version in composer.json, vendor a fork if you need to patch the compiler pass, and keep your own integration test around the generated output. Do not build your application's architecture on assumptions about its API stability.
  • Swoole/worker caveat. Static state survives between requests in a worker. If the generated container caches singleton instances statically, request-scoped services will leak across requests. Confirm whether exported services are re-instantiated per get() call or memoized, and keep stateful services out of the export list.
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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin