8000 [DependencyInjection] Doc for #30257 Allow to choose an index for tag… · symfony/symfony-docs@2b8df41 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2b8df41

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

File tree

1 file changed

+213
-0
lines changed

1 file changed

+213
-0
lines changed

service_container/tags.rst

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,3 +564,216 @@ 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', 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

Comments
 (0)
0