@@ -562,3 +562,216 @@ 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
+ .. code-block :: php
642
+
643
+ // src/Handler/HandlerCollection.php
644
+ namespace App\Handler;
645
+
646
+ class HandlerCollection
647
+ {
648
+ public function __construct(iterable $handlers)
649
+ {
650
+ $handlers = iterator_to_array($handlers);
651
+
652
+ $handlerTwo = $handlers['handler_two']:
653
+ }
654
+ }
655
+
656
+
657
+ .. tip ::
658
+
659
+ You can omit the ``index_attribute_name `` attribute, by implementing a static
660
+ method ``getDefaultIndexAttributeName `` to the handler.
661
+
662
+ Based on the previous example ``App\Handler\One `` should look like this:
663
+
664
+ .. code-block :: php
665
+
666
+ // src/Handler/One.php
667
+ namespace App\Handler;
668
+
669
+ class One
670
+ {
671
+ public static function getDefaultIndexName(): string
672
+ {
673
+ return 'handler_one';
674
+ }
675
+ }
676
+
677
+ And the configuration:
678
+
679
+ .. configuration-block ::
680
+
681
+ .. code-block :: yaml
682
+
683
+ # config/services.yaml
684
+ services :
685
+ App\Handler\One :
686
+ tags :
687
+ - { name: 'app.handler', priority: 20 }
688
+
689
+ # ...
690
+
691
+ .. code-block :: xml
692
+
693
+ <!-- config/services.xml -->
694
+ <?xml version =" 1.0" encoding=" UTF-8" ?>
695
+ <container xmlns =" http://symfony.com/schema/dic/services"
696
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
697
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
698
+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
699
+
700
+ <services >
701
+ <service id =" App\Handler\One" >
702
+ <tag name =" app.handler" priority =" 20" />
703
+ </service >
704
+
705
+ <!-- ... -->
706
+ </services >
707
+ </container >
708
+
709
+ .. code-block :: php
710
+
711
+ // config/services.php
712
+ $container->register(App\Handler\One::class)
713
+ ->addTag('app.handler', ['priority' => 20]);
714
+
715
+ // ...
716
+
717
+ You also can define the name of the static method to implement on each service
718
+ with the ``default_index_method `` attribute on the argument.
719
+
720
+ Based on the previous example ``App\Handler\One `` should look like :
721
+
722
+ .. code-block :: php
723
+
724
+ // src/Handler/One.php
725
+ namespace App\Handler;
726
+
727
+ class One
728
+ {
729
+ public static function someFunctionName(): string
730
+ {
731
+ return 'handler_one';
732
+ }
733
+ }
734
+
735
+ And the configuration:
736
+
737
+ .. configuration-block ::
738
+
739
+ .. code-block :: yaml
740
+
741
+ # config/services.yaml
742
+ services :
743
+ # ...
744
+
745
+ App\HandlerCollection :
746
+ # inject all services tagged with app.handler as first argument
747
+ arguments : [!tagged { tag: 'app.handler', index_by: 'key', default_index_method: 'someFunctionName' }]
748
+
749
+ .. code-block :: xml
750
+
751
+ <!-- config/services.xml -->
752
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
753
+ <container xmlns =" http://symfony.com/schema/dic/services"
754
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
755
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
756
+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
757
+
758
+ <services >
759
+
760
+ <!-- ... --!>
761
+
762
+ <service id="App\HandlerCollection">
763
+ <!-- inject all services tagged with app.handler as first argument -->
764
+ <argument type =" tagged" tag =" app.handler" index-by =" key" default-index-method =" someFunctionName" />
765
+ </service >
766
+ </services >
767
+ </container >
768
+
769
+ .. code-block :: php
770
+
771
+ // config/services.php
772
+ // ...
773
+
774
+ $container->register(App\HandlerCollection::class)
775
+ // inject all services tagged with app.handler as first argument
776
+ ->addArgument(new TaggedIteratorArgument('app.handler', 'key', 'someFunctionName'));
777
+