@@ -699,3 +699,209 @@ in the configuration of the collecting service:
699
699
)
700
700
;
701
701
};
702
+
703
+ Tagged Services Collection with Index
704
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
705
+
706
+ If you want to retrieve a specific service within the injected collection
707
+ you can use the ``index_by `` and ``default_index_method `` options of the argument
708
+ in combination with ``!tagged ``.
709
+
710
+ In the following example, all services tagged with ``app.handler `` are passed as
711
+ first constructor argument to ``App\Handler\HandlerCollection ``,
712
+ but we can now access a specific injected service:
713
+
714
+ .. configuration-block ::
715
+
716
+ .. code-block :: yaml
717
+
718
+ # config/services.yaml
719
+ services :
720
+ App\Handler\One :
721
+ tags :
722
+ - { name: 'app.handler', key: 'handler_one' }
723
+
724
+ App\Handler\Two :
725
+ tags :
726
+ - { name: 'app.handler', key: 'handler_two' }
727
+
728
+ App\HandlerCollection :
729
+ # inject all services tagged with app.handler as first argument
730
+ arguments : [!tagged { tag: 'app.handler', index_by: 'key' }]
731
+
732
+ .. code-block :: xml
733
+
734
+ <!-- config/services.xml -->
735
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
736
+ <container xmlns =" http://symfony.com/schema/dic/services"
737
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
738
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
739
+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
740
+
741
+ <services >
742
+ <service id =" App\Handler\One" >
743
+ <tag name =" app.handler" key =" handler_one" />
744
+ </service >
745
+
746
+ <service id =" App\Handler\Two" >
747
+ <tag name =" app.handler" key =" handler_two" />
748
+ </service >
749
+
750
+ <service id =" App\HandlerCollection" >
751
+ <!-- inject all services tagged with app.handler as first argument -->
752
+ <argument type =" tagged" tag =" app.handler" index-by =" key" />
753
+ </service >
754
+ </services >
755
+ </container >
756
+
757
+ .. code-block :: php
758
+
759
+ // config/services.php
760
+ use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
761
+
762
+ $container->register(App\Handler\One::class)
763
+ ->addTag('app.handler', ['key' => 'handler_one']);
764
+
765
+ $container->register(App\Handler\Two::class)
766
+ ->addTag('app.handler', ['key' => 'handler_two']);
767
+
768
+ $container->register(App\Handler\HandlerCollection::class)
769
+ // inject all services tagged with app.handler as first argument
770
+ ->addArgument(new TaggedIteratorArgument('app.handler', 'key'));
771
+
772
+ After compilation the ``HandlerCollection `` is able to iterate over your
773
+ application handlers. To retrieve a specific service by it's ``key `` attribute
774
+ from the iterator, we can use ``iterator_to_array `` and retrieve the ``handler_two ``:
775
+ to get an array and then retrieve the ``handler_two `` handler::
776
+
777
+ // src/Handler/HandlerCollection.php
778
+ namespace App\Handler;
779
+
780
+ class HandlerCollection
781
+ {
782
+ public function __construct(iterable $handlers)
783
+ {
784
+ $handlers = iterator_to_array($handlers);
785
+
786
+ $handlerTwo = $handlers['handler_two']:
787
+ }
788
+ }
789
+
790
+ .. tip ::
791
+
792
+ You can omit the
F438
``index_attribute_name `` attribute, by implementing a static
793
+ method ``getDefaultIndexAttributeName `` to the handler.
794
+
795
+ Based on the previous example ``App\Handler\One `` should look like this::
796
+
797
+ // src/Handler/One.php
798
+ namespace App\Handler;
799
+
800
+ class One
801
+ {
802
+ public static function getDefaultIndexName(): string
803
+ {
804
+ return 'handler_one';
805
+ }
806
+ }
807
+
808
+ And the configuration:
809
+
810
+ .. configuration-block ::
811
+
812
+ .. code-block :: yaml
813
+
814
+ # config/services.yaml
815
+ services :
816
+ App\Handler\One :
817
+ tags :
818
+ - { name: 'app.handler', priority: 20 }
819
+
820
+ # ...
821
+
822
+ .. code-block :: xml
823
+
824
+ <!-- config/services.xml -->
825
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
826
+ <container xmlns =" http://symfony.com/schema/dic/services"
827
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
828
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
829
+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
830
+
831
+ <services >
832
+ <service id =" App\Handler\One" >
833
+ <tag name =" app.handler" priority =" 20" />
834
+ </service >
835
+
836
+ <!-- ... -->
837
+ </services >
838
+ </container >
839
+
840
+ .. code-block :: php
841
+
842
+ // config/services.php
843
+ $container->register(App\Handler\One::class)
844
+ ->addTag('app.handler', ['priority' => 20]);
845
+
846
+ // ...
847
+
848
+ You also can define the name of the static method to implement on each service
849
+ with the ``default_index_method `` attribute on the argument.
850
+
851
+ Based on the previous example ``App\Handler\One `` should look like::
852
+
853
+ // src/Handler/One.php
854
+ namespace App\Handler;
855
+
856
+ class One
857
+ {
858
+ public static function someFunctionName(): string
859
+ {
860
+ return 'handler_one';
861
+ }
862
+ }
863
+
864
+ And the configuration:
865
+
866
+ .. configuration-block ::
867
+
868
+ .. code-block :: yaml
869
+
870
+ # config/services.yaml
871
+ services :
872
+ # ...
873
+
874
+ App\HandlerCollection :
875
+ # inject all services tagged with app.handler as first argument
876
+ arguments : [!tagged { tag: 'app.handler', index_by: 'key', default_index_method: 'someFunctionName' }]
877
+
878
+ .. code-block :: xml
879
+
880
+ <!-- config/services.xml -->
881
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
882
+ <container xmlns =" http://symfony.com/schema/dic/services"
883
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
884
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
885
+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
886
+
887
+ <services >
888
+
889
+ <!-- ... --!>
890
+
891
+ <service id="App\HandlerCollection">
892
+ <!-- inject all services tagged with app.handler as first argument -->
893
+ <argument type =" tagged" tag =" app.handler" index-by =" key" default-index-method =" someFunctionName" />
894
+ </service >
895
+ </services >
896
+ </container >
897
+
898
+ .. code-block :: php
899
+
900
+ // config/services.php
901
+ // ...
902
+
903
+ $container->register(App\HandlerCollection::class)
904
+ // inject all services tagged with app.handler as first argument
905
+ ->addArgument(new TaggedIteratorArgument('app.handler', 'key', 'someFunctionName'));
906
+
907
+ See also :doc: `tagged locator services </service_container/service_subscribers_locators >`
0 commit comments