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

Dependency Injection Extra Laravel Package

maba/dependency-injection-extra

Extra compiler passes for Symfony Dependency Injection that register tagged services into a registry or other service, optionally passing tag attributes, service IDs, or priority-based ordering. Deprecated; use paysera/lib-dependency-injection instead.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a thin set of Symfony CompilerPass implementations. Before anything else, note the README's first line: it is deprecated in favour of paysera/lib-dependency-injection. Last tagged release was February 2020, it has 6 stars and zero known dependents. As a Laravel developer, treat this as something you read to understand a legacy Symfony bundle you inherited, not something you add to a new project.

Install (if you must, e.g. maintaining an old Symfony 4/5 bundle):

composer require maba/dependency-injection-extra

Look first at src/CompilerPass/AddTaggedCompilerPass.php — it is the entire package. There is one compiler pass, and it does one thing: take every service tagged with $tagName and call $methodName on $serviceId with the tagged service as the first argument.

Minimal first use case — a registry that collects providers:

// src/SomeBundle.php
use Maba\Component\DependencyInjection\CompilerPass\AddTaggedCompilerPass;

public function build(ContainerBuilder $container): void
{
    parent::build($container);

    $container->addCompilerPass(new AddTaggedCompilerPass(
        'acme.provider_registry', // service that receives the calls
        'acme.provider',          // tag name to collect
        'addProvider',            // method to call on the registry
        ['name', 'theme' => 'default'] // optional tag attributes, in order
    ));
}

Tag a service with the matching name and attributes:

# config/services.yaml
Acme\Provider\AwesomeProvider:
    tags:
        - { name: acme.provider, name: awesome, theme: dark }

When the container compiles, acme.provider_registry->addProvider($awesomeProvider, 'awesome', 'dark') is invoked. That's it.

Implementation Patterns

Registry / collection pattern. The intended use is plugin registries: you define an interface, tag every implementation, and let the compiler pass wire them into a single registry service. This is the Symfony equivalent of Laravel's tagged bindings:

// Laravel equivalent you already know:
$this->app->tag([StripeGateway::class, PaypalGateway::class], 'payments');
$this->app->when(Checkout::class)->needs('$gateways')->giveTagged('payments');

The Symfony version is the same idea, but the registry is a concrete class rather than a closure. Keep your registry dumb — just a private array $providers plus an addProvider() method. Do not put lazy resolution or container lookups in there; the compiler pass hands you real instances.

Passing tag attributes. The fourth argument is the reason this package exists. Symfony gives you raw tag attributes; this pass maps them positionally into method arguments so your registry signature stays clean:

new AddTaggedCompilerPass('acme.registry', 'acme.provider', 'addProvider', [
    'name',              // required — compilation fails if a tagged service omits it
    'theme' => 'default',// optional — falls back if the attribute is absent
]);

Order of the array maps to the order of parameters after the service. Use associative keys to declare defaults, list them in the order you want them passed.

Registration point. Always register the pass in Bundle::build(), never at runtime. If you are auditing a Symfony bundle that already does this, search for addCompilerPass( — that is the only call site you need to understand.

Bridging into Laravel. If you are writing a Laravel package that needs to consume a Symfony bundle which uses this pass, resist the urge to make it work. Symfony's DI container and Illuminate\Container are unrelated. Instead, read the tag declarations out of the bundle's XML/YAML config and re-register them as tagged bindings in a Laravel service provider — that's a mechanical translation and far less fragile than embedding the Symfony container.

Method signature contract. The registry method receives (object $taggedService, ...$attributes). Type-hint the first parameter against your interface (ProviderInterface $provider), not object, so a mis-tagged service fails at compile time rather than at first dispatch.

Gotchas and Tips

Deprecation is the headline. This library is superseded and unmaintained since early 2020. Anything you build on it locks you to Symfony's DI internals as they were then. Even the package you're maintaining with it should be migrated to paysera/lib-dependency-injection, and if that's not possible, inline the ~40-line compiler pass directly — you'll have less risk than a dependency on an abandoned artifact.

Required attributes fail late and loudly. A required tag attribute missing from any tagged definition throws at container compilation, which means bin/console cache:clear — not at the point of use. During development this is great; in a CI pipeline that only runs tests against a warm cache, it silently slips. Always compile the container from scratch in CI (--env=test with rm -rf var/cache).

Compiler pass ordering matters. Compiler passes run in priority order within a phase (TYPE_BEFORE_OPTIMIZATION by default). If your registry service is itself created by another pass, or if a service's class is only resolved by a later pass, your pass may see it too early. Pass a priority: $container->addCompilerPass($pass, PassConfig::TYPE_BEFORE_OPTIMIZATION, 10) — lower runs later.

The container is cached in prod. After adding or removing tags, nothing changes until the container is recompiled (cache:clear). In Symfony this is the classic "why isn't my provider showing up" bug. In a Docker image, make sure cache warm-up happens at build time and re-runs on code change.

Tag names are global. Two bundles using acme.provider will collide, and this pass will happily call addProvider() on your registry with their services. Namespace your tag names with a vendor prefix.

Debugging tools that actually help. bin/console debug:container --tag=acme.provider lists everything tagged — this is the fastest way to prove a tag is or is not being applied. debug:container acme.provider_registry --show-arguments shows the resolved registry wiring.

Extension point. There's essentially one: write your own compiler pass. Extending this package means copying its structure (CompilerPassInterface, iterate findTaggedServiceIds, Reference per id, Definition::addMethodCall), and Symfony's own docs describe that pattern better and more currently than anything here. For a Laravel developer, the conceptual takeaway — "defer discovery of implementations to compile time, not runtime" — is the only durable lesson; the code itself is not.

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.
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
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator