@@ -564,3 +564,241 @@ 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
+ But you doesn't want to walk through the whole collection. The solution is to use the ``index_by ``
574
+ and ``default_index_method `` options of the argument 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\H andlerCollection 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
+ - { tag: 'app.handler', index_attribute_name : 'hOne' }
589
+
590
+ App\Handler\Two :
591
+ tags :
592
+ - { tag: 'app.handler', index_attribute_name: 'hTwo' }
593
+
594
+ App\HandlerCollection :
595
+ # inject all services tagged with app.handler as first argument
596
+ arguments : [!tagged { tag: 'app.handler', index_by: 'index_attribute_name' }]
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" index_attribute_name =" hOne" />
610
+ </service >
611
+
612
+ <service id =" App\Handler\Two" >
613
+ <tag name =" app.handler" index_attribute_name =" hTwo" />
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 =" index_attribute_name" />
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', ['index_attribute_name' => 'hOne']);
630
+
631
+ $container->register(App\Handler\Two::class)
632
+ ->addTag('app.handler', ['index_attribute_name' => 'hTwo']);
633
+
634
+ $container->register(App\HandlerCollection::class)
635
+ // inject all services tagged with app.handler as first argument
636
+ ->addArgument(new TaggedIteratorArgument('app.handler', 'index_attribute_name'));
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
+ ``index_attribute_name ``. As it's an iterator, we can use ``iterator_to_array ``
641
+ to get an array and then retrieve the ``hTwo `` handler :
642
+
643
+ .. code-block :: php
644
+
645
+ // src/HandlerCollection.php
646
+ namespace App;
647
+
648
+ class HandlerCollection
649
+ {
650
+ public function __construct(iterable $handlersIt)
651
+ {
652
+ $handlers = iterator_to_array($handlersIt);
653
+
654
+ $hTwo = $handlers['hTwo']:
655
+ $hOne = $handlers['hOne'];
656
+ }
657
+ }
658
+
659
+
660
+ .. tip ::
661
+
662
+ You can omit the ``index_attribute_name `` attribute, to do this you
663
+ have, by default, to implement a static method named like this : ``getDefaultIndexAttributeNameName ``
664
+
665
+ .. configuration-block ::
666
+
667
+ .. code-block :: yaml
668
+
669
+ # config/services.yaml
670
+ services :
671
+ App\Handler\One :
672
+ tags :
673
+ - { name: 'app.handler', priority: 20 }
674
+
675
+ App\Handler\Two :
676
+ tags :
677
+ - { tag: 'app.handler', index : 'hTwo' }
678
+
679
+ App\HandlerCollection :
680
+ # inject all services tagged with app.handler as first argument
681
+ arguments : [!tagged { tag: 'app.handler', index_by: 'index' }]
682
+
683
+ .. code-block :: xml
684
+
685
+ <!-- config/services.xml -->
686
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
687
+ <container xmlns =" http://symfony.com/schema/dic/services"
688
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
689
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
690
+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
691
+
692
+ <services >
693
+ <service id =" App\Handler\One" >
694
+ <tag name =" app.handler" priority =" 20" />
695
+ </service >
696
+
697
+ <service id =" App\Handler\Two" >
698
+ <tag name =" app.handler" index =" hTwo" />
699
+ </service >
700
+
701
+ <service id =" App\HandlerCollection" >
702
+ <!-- inject all services tagged with app.handler as first argument -->
703
+ <argument type =" tagged" tag =" app.handler" index-by =" index" />
704
+ </service >
705
+ </services >
706
+ </container >
707
+
708
+ .. code-block :: php
709
+
710
+ // config/services.php
711
+ $container->register(App\Handler\One::class)
712
+ ->addTag('app.handler', ['priority' => 20]);
713
+
714
+ $container->register(App\Handler\One::class, ['index' => 'hTwo']);
715
+
716
+ $container->register(App\HandlerCollection::class)
717
+ // inject all services tagged with app.handler as first argument
718
+ ->addArgument(new TaggedIteratorArgument('app.handler', 'index'));
719
+
720
+ And here is how your ``App\Handler\One `` should now be :
721
+
722
+ .. code-block :: php
723
+
724
+ // src/Handler/One.php
725
+ namespace App\Handler;
726
+
727
+ class One
728
+ {
729
+ public static function getDefaultIndexName() {
730
+ return 'hOne';
731
+ }
732
+ }
733
+
734
+ You also can define the name of the static method to implement on each service with the ``default_index_method `` attribute on the argument.
735
+
736
+ .. configuration-block ::
737
+
738
+ .. code-block :: yaml
739
+
740
+ # config/services.yaml
741
+ services :
742
+ App\Handler\One :
743
+ tags :
744
+ - { name: 'app.handler', priority: 20 }
745
+
746
+ App\Handler\Two :
747
+ tags :
748
+ - { tag: 'app.handler', index : 'hTwo' }
749
+
750
+ App\HandlerCollection :
751
+ # inject all services tagged with app.handler as first argument
752
+ arguments : [!tagged { tag: 'app.handler', index_by: 'index', default_index_method: 'someFunctionName' }]
753
+
754
+ .. code-block :: xml
755
+
756
+ <!-- config/services.xml -->
757
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
758
+ <container xmlns =" http://symfony.com/schema/dic/services"
759
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
760
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
761
+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
762
+
763
+ <services >
764
+ <service id =" App\Handler\One" >
765
+ <tag name =" app.handler" priority =" 20" />
766
+ </service >
767
+
768
+ <service id =" App\Handler\Two" >
769
+ <tag name =" app.handler" index =" hTwo" />
770
+ </service >
771
+
772
+ <service id =" App\HandlerCollection" >
773
+ <!-- inject all services tagged with app.handler as first argument -->
774
+ <argument type =" tagged" tag =" app.handler" index-by =" index" default-index-method =" someFunctionName" />
775
+ </service >
776
+ </services >
777
+ </container >
778
+
779
+ .. code-block :: php
780
+
781
+ // config/services.php
782
+ $container->register(App\Handler\One::class)
783
+ ->addTag('app.handler', ['priority' => 20]);
784
+
785
+ $container->register(App\Handler\One::class, ['index' => 'hTwo']);
786
+
787
+ $container->register(App\HandlerCollection::class)
788
+ // inject all services tagged with app.handler as first argument
789
+ ->addArgument(new TaggedIteratorArgument('app.handler', 'index', 'someFunctionName'));
790
+
791
+ And here is how your ``App\Handler\One `` should now be :
792
+
793
+ .. code-block :: php
794
+
795
+ // src/Handler/One.php
796
+ namespace App\Handler;
797
+
798
+ class One
799
+ {
800
+ public static function someFunctionName() {
801
+ return 'hOne';
802
+ }
803
+ }
804
+
0 commit comments