@@ -564,3 +564,216 @@ application handlers.
564
564
->addTag('app.handler', ['priority' => 20]);
565
565
566
566
Note that any other custom attributes will be ignored by this feature.
567
+
568
+
569
+ Tagged Services Collection with Index
570
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
571
+
572
+ What if you want to retrieve a specific service within the injected collection previously?
573
+ The solution is to use the ``index_by `` and ``default_index_method `` options of the argument
574
+ in combination with ``!tagged ``.
575
+
576
+ In the following example, all services tagged with ``app.handler `` are passed as
577
+ first constructor argument to the ``App\Handler\HandlerCollection `` service, like previously,
578
+ but we can now access to a specific injected service :
579
+
580
+ .. configuration-block ::
581
+
582
+ .. code-block :: yaml
583
+
584
+ # config/services.yaml
585
+ services :
586
+ App\Handler\One :
587
+ tags :
588
+ - { name: 'app.handler', key: 'handler_one' }
589
+
590
+ App\Handler\Two :
591
+ tags :
592
+ - { name: 'app.handler', key: 'handler_two' }
593
+
594
+ App\HandlerCollection :
595
+ # inject all services tagged with app.handler as first argument
596
+ arguments : [!tagged { tag: 'app.handler', index_by: 'key' }]
597
+
598
+ .. code-block :: xml
599
+
600
+ <!-- config/services.xml -->
601
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
602
+ <container xmlns =" http://symfony.com/schema/dic/services"
603
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
604
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
605
+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
606
+
607
+ <services >
608
+ <service id =" App\Handler\One" >
609
+ <tag name =" app.handler" key =" handler_one" />
610
+ </service >
611
+
612
+ <service id =" App\Handler\Two" >
613
+ <tag name =" app.handler" key =" handler_two" />
614
+ </service >
615
+
616
+ <service id =" App\HandlerCollection" >
617
+ <!-- inject all services tagged with app.handler as first argument -->
618
+ <argument type =" tagged" tag =" app.handler" index-by =" key" />
619
+ </service >
620
+ </services >
621
+ </container >
622
+
623
+ .. code-block :: php
624
+
625
+ // config/services.php
626
+ use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
627
+
628
+ $container->register(App\Handler\One::class)
629
+ ->addTag('app.handler', ['key' => 'handler_one']);
630
+
631
+ $container->register(App\Handler\Two::class)
632
+ ->addTag('app.handler', ['key' => 'handler_two']);
633
+
634
+ $container->register(App\Handler\HandlerCollection::class)
635
+ // inject all services tagged with app.handler as first argument
636
+ ->addArgument(new TaggedIteratorArgument('app.handler', 'key'));
637
+
638
+ After compilation the ``HandlerCollection `` service is able to iterate over your
639
+ application handlers. But we want to retrieve a specific service by it's
640
+ ``key `` attribute. As it's an iterator, we can use ``iterator_to_array ``
641
+ to get an array and then retrieve the ``handler_two `` handler :
642
+
643
+ .. code-block :: php
644
+
645
+ // src/Handler/HandlerCollection.php
646
+ namespace App\Handler;
647
+
648
+ class HandlerCollection
649
+ {
650
+ public function __construct(iterable $handlers)
651
+ {
652
+ $handlers = iterator_to_array($handlers);
653
+
654
+ $handler_two = $handlers['handler_two']:
655
+ $handler_one = $handlers['handler_one'];
656
+ }
657
+ }
658
+
659
+
660
+ .. tip ::
661
+
662
+ You can omit the ``index_attribute_name `` attribute, by implementing a static
663
+ method named like this : ``getDefaultIndexAttributeNameName ``
664
+
665
+ Based on the previous example ``App\Handler\One `` should look like :
666
+
667
+ .. code-block :: php
668
+
669
+ // src/Handler/One.php
670
+ namespace App\Handler;
671
+
672
+ class One
673
+ {
674
+ public static function getDefaultIndexName() {
675
+ return 'handler_one';
676
+ }
677
+ }
678
+
679
+ And the configuration :
680
+
681
+ .. configuration-block ::
682
+
683
+ .. code-block :: yaml
684
+
685
+ # config/services.yaml
686
+ services :
687
+ App\Handler\One :
688
+ tags :
689
+ - { name: 'app.handler', priority: 20 }
690
+
691
+ ....
692
+
693
+ .. code-block :: xml
694
+
695
+ <!-- config/services.xml -->
696
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
697
+ <container xmlns =" http://symfony.com/schema/dic/services"
698
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
699
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
700
+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
701
+
702
+ <services >
703
+ <service id =" App\Handler\One" >
704
+ <tag name =" app.handler" priority =" 20" />
705
+ </service >
706
+
707
+ ...
708
+ </services >
709
+ </container >
710
+
711
+ .. code-block :: php
712
+
713
+ // config/services.php
714
+ $container->register(App\Handler\One::class)
715
+ ->addTag('app.handler', ['priority' => 20]);
716
+
717
+ ...
718
+
719
+ You also can define the name of the static method to implement on each service
720
+ with the ``default_index_method `` attribute on the argument.
721
+
722
+ Based on the previous example ``App\Handler\One `` should look like :
723
+
724
+ .. code-block :: php
725
+
726
+ // src/Handler/One.php
727
+ namespace App\Handler;
728
+
729
+ class One
730
+ {
731
+ public static function someFunctionName()
732
+ {
733
+ return 'handler_one';
734
+ }
735
+ }
736
+
737
+ And the configuration :
738
+
739
+ .. configuration-block ::
740
+
741
+ .. code-block :: yaml
742
+
743
+ # config/services.yaml
744
+ services :
745
+ ...
746
+
747
+ App\HandlerCollection :
748
+ # inject all services tagged with app.handler as first argument
749
+ arguments : [!tagged { tag: 'app.handler', index_by: 'key', default_index_method: 'someFunctionName' }]
750
+
751
+ .. code-block :: xml
752
+
753
+ <!-- config/services.xml -->
754
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
755
+ <container xmlns =" http://symfony.com/schema/dic/services"
756
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
757
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
758
+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
759
+
760
+ <services >
761
+
762
+ ...
763
+
764
+ <service id =" App\HandlerCollection" >
765
+ <!-- inject all services tagged with app.handler as first argument -->
766
+ <argument type =" tagged" tag =" app.handler" index-by =" key" default-index-method =" someFunctionName" />
767
+ </service >
768
+ </services >
769
+ </container >
770
+
771
+ .. code-block :: php
772
+
773
+ // config/services.php
774
+ ...
775
+
776
+ $container->register(App\HandlerCollection::class)
777
+ // inject all services tagged with app.handler as first argument
778
+ ->addArgument(new TaggedIteratorArgument('app.handler', 'key', 'someFunctionName'));
779
+
0 commit comments