@@ -394,6 +394,212 @@ will share identical locators amongst all the services referencing them::
394394
395395.. _`Command pattern` :https://en.wikipedia.org/wiki/Command_pattern
396396
397+ Tagged Services Locator Collection with Index
398+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
399+
400+ If you want to retrieve a specific service within the injected service collector
401+ you can use the ``index_by `` and ``default_index_method `` options of the argument
402+ in combination with ``!tagged_locator `` to define an index.
403+
404+ In the following example, all services tagged with ``app.handler `` are passed as
405+ first constructor argument to ``App\Handler\HandlerCollection ``,
406+ but we can now access a specific injected service:
407+
408+ ..configuration-block ::
409+
410+ ..code-block ::yaml
411+
412+ # config/services.yaml
413+ services :
414+ App\Handler\One :
415+ tags :
416+ -{ name: 'app.handler', key: 'handler_one' }
417+
418+ App\Handler\Two :
419+ tags :
420+ -{ name: 'app.handler', key: 'handler_two' }
421+
422+ App\HandlerCollection :
423+ # inject all services tagged with app.handler as first argument
424+ arguments :[!tagged_locator { tag: 'app.handler', index_by: 'key' }]
425+
426+ ..code-block ::xml
427+
428+ <!-- config/services.xml-->
429+ <?xml version =" 1.0" encoding =" UTF-8" ?>
430+ <container xmlns =" http://symfony.com/schema/dic/services"
431+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
432+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
433+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
434+
435+ <services >
436+ <service id =" App\Handler\One" >
437+ <tag name =" app.handler" key =" handler_one" />
438+ </service >
439+
440+ <service id =" App\Handler\Two" >
441+ <tag name =" app.handler" key =" handler_two" />
442+ </service >
443+
444+ <service id =" App\HandlerCollection" >
445+ <!-- inject all services tagged with app.handler as first argument-->
446+ <argument type =" tagged_locator" tag =" app.handler" index-by =" key" />
447+ </service >
448+ </services >
449+ </container >
450+
451+ ..code-block ::php
452+
453+ // config/services.php
454+ use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
455+ use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
456+
457+ $container->register(App\Handler\One::class)
458+ ->addTag('app.handler', ['key' => 'handler_one']);
459+
460+ $container->register(App\Handler\Two::class)
461+ ->addTag('app.handler', ['key' => 'handler_two']);
462+
463+ $container->register(App\Handler\HandlerCollection::class)
464+ // inject all services tagged with app.handler as first argument
465+ ->addArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('app.handler', 'key')));
466+
467+ After compilation the ``HandlerCollection `` to retrieve a specific service by it's ``key `` attribute
468+ from the service locator injected, we just have to do ``$serviceLocator->get('handler_two'); `` to
469+ retrieve the ``handler_two `` handler::
470+
471+ // src/Handler/HandlerCollection.php
472+ namespace App\Handler;
473+
474+ use Symfony\Component\DependencyInjection\ServiceLocator;
475+
476+ class HandlerCollection
477+ {
478+ public function __construct(ServiceLocator $locator)
479+ {
480+ $handlerTwo = $locator->get('handler_two'):
481+ }
482+ }
483+
484+ ..tip ::
485+
486+ You can omit the ``index_attribute_name `` attribute, by implementing a static
487+ method ``getDefaultIndexAttributeName `` to the handler.
488+
489+ Based on the previous example ``App\Handler\One `` should look like this::
490+
491+ // src/Handler/One.php
492+ namespace App\Handler;
493+
494+ class One
495+ {
496+ public static function getDefaultIndexName(): string
497+ {
498+ return 'handler_one';
499+ }
500+ }
501+
502+ And the configuration:
503+
504+ ..configuration-block ::
505+
506+ ..code-block ::yaml
507+
508+ # config/services.yaml
509+ services :
510+ App\Handler\One :
511+ tags :
512+ -{ name: 'app.handler', priority: 20 }
513+
514+ # ...
515+
516+ ..code-block ::xml
517+
518+ <!-- config/services.xml-->
519+ <?xml version =" 1.0" encoding =" UTF-8" ?>
520+ <container xmlns =" http://symfony.com/schema/dic/services"
521+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
522+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
523+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
524+
525+ <services >
526+ <service id =" App\Handler\One" >
527+ <tag name =" app.handler" priority =" 20" />
528+ </service >
529+
530+ <!-- ...-->
531+ </services >
532+ </container >
533+
534+ ..code-block ::php
535+
536+ // config/services.php
537+ $container->register(App\Handler\One::class)
538+ ->addTag('app.handler', ['priority' => 20]);
539+
540+ // ...
541+
542+ You also can define the name of the static method to implement on each service
543+ with the ``default_index_method `` attribute on the argument.
544+
545+ Based on the previous example ``App\Handler\One `` should look like::
546+
547+ // src/Handler/One.php
548+ namespace App\Handler;
549+
550+ class One
551+ {
552+ public static function someFunctionName(): string
553+ {
554+ return 'handler_one';
555+ }
556+ }
557+
558+ And the configuration:
559+
560+ ..configuration-block ::
561+
562+ ..code-block ::yaml
563+
564+ # config/services.yaml
565+ services :
566+ # ...
567+
568+ App\HandlerCollection :
569+ # inject all services tagged with app.handler as first argument
570+ arguments :[!tagged_locator { tag: 'app.handler', index_by: 'key', default_index_method: 'someFunctionName' }]
571+
572+ ..code-block ::xml
573+
574+ <!-- config/services.xml-->
575+ <?xml version =" 1.0" encoding =" UTF-8" ?>
576+ <container xmlns =" http://symfony.com/schema/dic/services"
577+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
578+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
579+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
580+
581+ <services >
582+
583+ <!-- ... --!>
584+
585+ <service id="App\HandlerCollection">
586+ <!-- inject all services tagged with app.handler as first argument-->
587+ <argument type =" tagged_locator" tag =" app.handler" index-by =" key" default-index-method =" someFunctionName" />
588+ </service >
589+ </services >
590+ </container >
591+
592+ ..code-block ::php
593+
594+ // config/services.php
595+ // ...
596+
597+ $container->register(App\HandlerCollection::class)
598+ // inject all services tagged with app.handler as first argument
599+ ->addArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('app.handler', 'key', 'someFunctionName')));
600+
601+ See also:doc: `tagged services </service_container/tags >`
602+
397603Service Subscriber Trait
398604------------------------
399605