@@ -562,3 +562,210 @@ application handlers::
562
562
->addTag('app.handler', ['priority' => 20]);
563
563
564
564
Note that any other custom attributes will be ignored by this feature.
565
+
566
+
567
+ Tagged Services Collection with Index
568
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
569
+
570
+ If you want to retrieve a specific service within the injected collection
571
+ you can use the ``index_by `` and ``default_index_method `` options of the argument
572
+ in combination with ``!tagged ``.
573
+
574
+ In the following example, all services tagged with ``app.handler `` are passed as
575
+ first constructor argument to ``App\Handler\HandlerCollection ``,
576
+ but we can now access a specific injected service:
577
+
578
+ .. configuration-block ::
579
+
580
+ .. code-block :: yaml
581
+
582
+ # config/services.yaml
583
+ services :
584
+ App\Handler\One :
585
+ tags :
586
+ - { name: 'app.handler', key: 'handler_one' }
587
+
588
+ App\Handler\Two :
589
+ tags :
590
+ - { name: 'app.handler', key: 'handler_two' }
591
+
592
+ App\HandlerCollection :
593
+ # inject all services tagged with app.handler as first argument
594
+ arguments : [!tagged { tag: 'app.handler', index_by: 'key' }]
595
+
596
+ .. code-block :: xml
597
+
598
+ <!-- config/services.xml -->
599
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
600
+ <container xmlns =" http://symfony.com/schema/dic/services"
601
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
602
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
603
+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
604
+
605
+ <services >
606
+ <service id =" App\Handler\One" >
607
+ <tag name =" app.handler" key =" handler_one" />
608
+ </service >
609
+
610
+ <service id =" App\Handler\Two" >
611
+ <tag name =" app.handler" key =" handler_two" />
612
+ </service >
613
+
614
+ <service id =" App\HandlerCollection" >
615
+ <!-- inject all services tagged with app.handler as first argument -->
616
+ <argument type =" tagged" tag =" app.handler" index-by =" key" />
617
+ </service >
618
+ </services >
619
+ </container >
620
+
621
+ .. code-block :: php
622
+
623
+ // config/services.php
624
+ use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
625
+
626
+ $container->register(App\Handler\One::class)
627
+ ->addTag('app.handler', ['key' => 'handler_one']);
628
+
629
+ $container->register(App\Handler\Two::class)
630
+ ->addTag('app.handler', ['key' => 'handler_two']);
631
+
632
+ $container->register(App\Handler\HandlerCollection::class)
633
+ // inject all services tagged with app.handler as first argument
634
+ ->addArgument(new TaggedIteratorArgument('app.handler', 'key'));
635
+
636
+ After compilation the ``HandlerCollection `` is able to iterate over your
637
+ application handlers. To retrieve a specific service by it's ``key `` attribute
638
+ from the iterator, we can use ``iterator_to_array `` and retrieve the ``handler_two ``:
639
+ to get an array and then retrieve the ``handler_two `` handler::
640
+
641
+ // src/Handler/HandlerCollection.php
642
+ namespace App\Handler;
643
+
644
+ class HandlerCollection
645
+ {
646
+ public function __construct(iterable $handlers)
647
+ {
648
+ $handlers = iterator_to_array($handlers);
649
+
650
+ $handlerTwo = $handlers['handler_two']:
651
+ }
652
+ }
653
+
654
+ .. tip ::
655
+
656
+ You can omit the ``index_attribute_name `` attribute, by implementing a static
657
+ method ``getDefaultIndexAttributeName `` to the handler.
658
+
659
+ Based on the previous example ``App\Handler\One `` should look like this::
660
+
661
+ // src/Handler/One.php
662
+ namespace App\Handler;
663
+
664
+ class One
665
+ {
666
+ public static function getDefaultIndexName(): string
667
+ {
668
+ return 'handler_one';
669
+ }
670
+ }
671
+
672
+ And the configuration:
673
+
674
+ .. configuration-block ::
675
+
676
+ .. code-block :: yaml
677
+
678
+ # config/services.yaml
679
+ services :
680
+ App\Handler\One :
681
+ tags :
682
+ - { name: 'app.handler', priority: 20 }
683
+
684
+ # ...
685
+
686
+ .. code-block :: xml
687
+
688
+ <!-- config/services.xml -->
689
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
690
+ <container xmlns =" http://symfony.com/schema/dic/services"
691
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
692
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
693
+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
694
+
695
+ <services >
696
+ <service id =" App\Handler\One" >
697
+ <tag name =" app.handler" priority =" 20" />
698
+ </service >
699
+
700
+ <!-- ... -->
701
+ </services >
702
+ </container >
703
+
704
+ .. code-block :: php
705
+
706
+ // config/services.php
707
+ $container->register(App\Handler\One::class)
708
+ ->addTag('app.handler', ['priority' => 20]);
709
+
710
+ // ...
711
+
712
+ You also can define the name of the static method to implement on each service
713
+ with the ``default_index_method `` attribute on the argument.
714
+
715
+ Based on the previous example ``App\Handler\One `` should look like::
716
+
717
+ // src/Handler/One.php
718
+ namespace App\Handler;
719
+
720
+ class One
721
+ {
722
+ public static function someFunctionName(): string
723
+ {
724
+ return 'handler_one';
725
+ }
726
+ }
727
+
728
+ And the configuration:
729
+
730
+ .. configuration-block ::
731
+
732
+ .. code-block :: yaml
733
+
734
+ # config/services.yaml
735
+ services :
736
+ # ...
737
+
738
+ App\HandlerCollection :
739
+ # inject all services tagged with app.handler as first argument
740
+ arguments : [!tagged { tag: 'app.handler', index_by: 'key', default_index_method: 'someFunctionName' }]
741
+
742
+ .. code-block :: xml
743
+
744
+ <!-- config/services.xml -->
745
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
746
+ <container xmlns =" http://symfony.com/schema/dic/services"
747
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
748
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
749
+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
750
+
751
+ <services >
752
+
753
+ <!-- ... --!>
754
+
755
+ <service id="App\HandlerCollection">
756
+ <!-- inject all services tagged with app.handler as first argument -->
757
+ <argument type =" tagged" tag =" app.handler" index-by =" key" default-index-method =" someFunctionName" />
758
+ </service >
759
+ </services >
760
+ </container >
761
+
762
+ .. code-block :: php
763
+
764
+ // config/services.php
765
+ // ...
766
+
767
+ $container->register(App\HandlerCollection::class)
768
+ // inject all services tagged with app.handler as first argument
769
+ ->addArgument(new TaggedIteratorArgument('app.handler', 'key', 'someFunctionName'));
770
+
771
+ See also :doc: `tagged locator services </service_container/service_subscribers_locators >`
0 commit comments