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

Skip to content

Commit 6db79cd

Browse files
author
Anthony MARTIN
committed
[DependencyInjection] Doc for #30257 Allow to choose an index for tagged collection
1 parent f034d99 commit 6db79cd

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

0 commit comments

Comments
 (0)
0