Weave Code
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

Tag Bundle Laravel Package

berny/tag-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require xphere/tag-bundle
    

    Add to config/bundles.php:

    return [
        // ...
        xPheRe\Bundle\TagBundle\TagBundle::class => ['all' => true],
    ];
    
  2. First Use Case: Define a service with a tag in config/services.yaml:

    services:
        my_service:
            class: App\Service\MyService
            tags: ['name: my_tag']
    

    Inject tagged services into another service:

    use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
    
    class MyConsumerService
    {
        public function __construct(
            private iterable $myTaggedServices
        ) {}
    
        public function doSomething()
        {
            foreach ($this->myTaggedServices as $service) {
                $service->someMethod();
            }
        }
    }
    

    Key: Use iterable type-hint to automatically inject all services tagged with my_tag.


Implementation Patterns

Tagging Services

  • Basic Tagging:

    services:
        service_one:
            class: App\Service\One
            tags: ['name: my_tag']
        service_two:
            class: App\Service\Two
            tags: ['name: my_tag', 'priority: 10']
    

    Use priority to sort services (higher priority first).

  • Dynamic Tagging: Use autoconfigure_tags to tag services automatically via attributes:

    #[AutoconfigureTag('name: my_tag')]
    class MyService {}
    

Consuming Tagged Services

  • Constructor Injection:

    class ConsumerService {
        public function __construct(
            private iterable $myTaggedServices
        ) {}
    }
    
  • Method Injection:

    class ConsumerService {
        public function setTaggedServices(iterable $services) {
            $this->services = $services;
        }
    }
    

    Configure in YAML:

    services:
        consumer_service:
            class: App\Service\ConsumerService
            calls:
                - [setTaggedServices, ['@my_tag']]
    
  • Lazy Loading: Use TaggedIterator for on-demand access:

    use xPheRe\Bundle\TagBundle\TaggedIterator;
    
    class ConsumerService {
        public function __construct(
            private TaggedIterator $myTaggedServices
        ) {}
    
        public function getService(string $id) {
            return $this->myTaggedServices->get($id);
        }
    }
    

Integration Tips

  • Combining with Other Bundles: Works seamlessly with Symfony’s built-in tagging system. No need for CompilerPass unless extending functionality.

  • Custom Tag Attributes: Access tag attributes in consumers:

    foreach ($myTaggedServices as $id => $attributes) {
        $priority = $attributes['priority'] ?? 0;
    }
    

Gotchas and Tips

Pitfalls

  • Namespace Change: Pre-0.4.0 used Berny\Bundle\TagBundle. Post-0.4.0 uses xPheRe\Bundle\TagBundle. Ensure your use statements and bundles.php reflect this.

  • Circular Dependencies: Avoid tagging services that depend on the consumer service. This can cause circular references during container compilation.

  • TaggedIterator Behavior: TaggedIterator returns services in registration order (not alphabetical or by priority). Use usort if custom ordering is needed:

    usort($services, fn($a, $b) => ($b['priority'] ?? 0) <=> ($a['priority'] ?? 0));
    

Debugging

  • Missing Services: Verify tags are correctly defined in YAML/XML/PHP. Use:

    php bin/console debug:container --tag=my_tag
    

    to list tagged services.

  • Injection Failures: If iterable injection fails, ensure:

    1. At least one service is tagged with my_tag.
    2. No typos in tag names (case-sensitive).

Extension Points

  • Custom Compiler Passes: Extend the bundle by creating a CompilerPass to modify tagged services before injection:

    use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
    use Symfony\Component\DependencyInjection\ContainerBuilder;
    
    class MyTagCompilerPass implements CompilerPassInterface {
        public function process(ContainerBuilder $container) {
            $tagged = $container->findTaggedServiceIds('my_tag');
            foreach ($tagged as $id => $tags) {
                $definition = $container->getDefinition($id);
                $definition->addMethodCall('customMethod');
            }
        }
    }
    

    Register the pass in services.yaml:

    services:
        my_tag_compiler_pass:
            class: App\Compiler\MyTagCompilerPass
            tags: [compiler_pass]
    
  • Override Default Behavior: Replace the bundle’s TaggedIterator by binding your own implementation:

    services:
        xphere.tag_bundle.tagged_iterator:
            class: App\Service\CustomTaggedIterator
            public: true
    

Performance Tips

  • Avoid Over-Tagging: Tag only services that are actually needed for injection. Excessive tags bloat the container.

  • Use lazy for Large Collections: For services with many tagged dependencies, use lazy loading:

    #[Autowire(service: 'my_tag', lazy: true)]
    private iterable $myTaggedServices;
    
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope