@@ -699,3 +699,209 @@ in the configuration of the collecting service:
699699 )
700700 ;
701701 };
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 ``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 >`