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