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

Skip to content

Commit dcd44ba

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

File tree

1 file changed

+205
-0
lines changed

1 file changed

+205
-0
lines changed

service_container/tags.rst

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

0 commit comments

Comments
 (0)