Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 126d0f2

Browse files
author
Anthony MARTIN
committed
[DependencyInjection] Doc for #30257 Allow to choose an index for tagged collection
1 parent 8bce8a2 commit 126d0f2

File tree

1 file changed

+239
-0
lines changed

1 file changed

+239
-0
lines changed

service_container/tags.rst

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,3 +564,242 @@ application handlers.
564564
->addTag('app.handler', ['priority' => 20]);
565565
566566
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', index_attribute_name: 'handler_one' }
589+
590+
App\Handler\Two:
591+
tags:
592+
- { name: 'app.handler', index_attribute_name: '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: '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="handler_one" />
610+
</service>
611+
612+
<service id="App\Handler\Two">
613+
<tag name="app.handler" index_attribute_name="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="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' => 'handler_one']);
630+
631+
$container->register(App\Handler\Two::class)
632+
->addTag('app.handler', ['index_attribute_name' => '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', '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 ``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+
.. 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+
- { name: 'app.handler', index: 'handler_two' }
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="handler_two" />
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' => 'handler_two']);
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 'handler_one';
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+
- { name: 'app.handler', index: 'handler_two' }
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="handler_two" />
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' => 'handler_two']);
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 look like :
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+
{
802+
return 'handler_one';
803+
}
804+
}
805+

0 commit comments

Comments
 (0)