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