8000 feature #11009 [DependencyInjection] Doc for #30257 Allow to choose a… · symfony/symfony-docs@56dd405 · GitHub
[go: up one dir, main page]

Skip to content

Commit 56dd405

Browse files
committed
feature #11009 [DependencyInjection] Doc for #30257 Allow to choose an index for tagged collection (Anthony MARTIN)
This PR was submitted for the master branch but it was merged into the 4.4 branch instead. Discussion ---------- [DependencyInjection] Doc for #30257 Allow to choose an index for tagged collection Here is the doc for the new feature implemented in : symfony/symfony#30257 Commits ------- 980b3d3 [DependencyInjection] Doc for #30257 Allow to choose an index for tagged collection
2 parents 1170a7c + 980b3d3 commit 56dd405

File tree

1 file changed

+206
-0
lines changed

1 file changed

+206
-0
lines changed

service_container/tags.rst

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,3 +699,209 @@ in the configuration of the collecting service:
699699
)
700700
;
701701
};
702+
703+
Tagged Services Collection with Index
704+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
705+
706+
If you want to retrieve a specific service within the injected collection
707+
you can use the ``index_by`` and ``default_index_method`` options of the argument
708+
in combination with ``!tagged``.
709+
710+
In the following example, all services tagged with ``app.handler`` are passed as
711+
first constructor argument to ``App\Handler\HandlerCollection``,
712+
but we can now access a specific injected service:
713+
714+
.. configuration-block::
715+
716+
.. code-block:: yaml
717+
718+
# config/services.yaml
719+
services:
720+
App\Handler\One:
721+
tags:
722+
- { name: 'app.handler', key: 'handler_one' }
723+
724+
App\Handler\Two:
725+
tags:
726+
- { name: 'app.handler', key: 'handler_two' }
727+
728+
App\HandlerCollection:
729+
# inject all services tagged with app.handler as first argument
730+
arguments: [!tagged { tag: 'app.handler', index_by: 'key' }]
731+
732+
.. code-block:: xml
733+
734+
<!-- config/services.xml -->
735+
<?xml version="1.0" encoding="UTF-8" ?>
736+
<container xmlns="http://symfony.com/schema/dic/services"
737+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
738+
xsi:schemaLocation="http://symfony.com/schema/dic/services
739+
http://symfony.com/schema/dic/services/services-1.0.xsd">
740+
741+
<services>
742+
<service id="App\Handler\One">
743+
<tag name="app.handler" key="handler_one" />
744+
</service>
745+
746+
<service id="App\Handler\Two">
747+
<tag name="app.handler" key="handler_two" />
748+
</service>
749+
750+
<service id="App\HandlerCollection">
751+
<!-- inject all services tagged with app.handler as first argument -->
752+
<argument type="tagged" tag="app.handler" index-by="key" />
753+
</service>
754+
</services>
755+
</container>
756+
757+
.. code-block:: php
758+
759+
// config/services.php
760+
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
761+
762+
$container->register(App\Handler\One::class)
763+
->addTag('app.handler', ['key' => 'handler_one']);
764+
765+
$container->register(App\Handler\Two::class)
766+
->addTag('app.handler', ['key' => 'handler_two']);
767+
768+
$container->register(App\Handler\HandlerCollection::class)
769+
// inject all services tagged with app.handler as first argument
770+
->addArgument(new TaggedIteratorArgument('app.handler', 'key'));
771+
772+
After compilation the ``HandlerCollection`` is able to iterate over your
773+
application handlers. To retrieve a specific service by it's ``key`` attribute
774+
from the iterator, we can use ``iterator_to_array`` and retrieve the ``handler_two``:
775+
to get an array and then retrieve the ``handler_two`` handler::
776+
777+
// src/Handler/HandlerCollection.php
778+
namespace App\Handler;
779+
780+
class HandlerCollection
781+
{
782+
public function __construct(iterable $handlers)
783+
{
784+
$handlers = iterator_to_array($handlers);
785+
786+
$handlerTwo = $handlers['handler_two']:
787+
}
788+
}
789+
790+
.. tip::
791+
792+
You can omit the F438 ``index_attribute_name`` attribute, by implementing a static
793+
method ``getDefaultIndexAttributeName`` to the handler.
794+
795+
Based on the previous example ``App\Handler\One`` should look like this::
796+
797+
// src/Handler/One.php
798+
namespace App\Handler;
799+
800+
class One
801+
{
802+
public static function getDefaultIndexName(): string
803+
{
804+
return 'handler_one';
805+
}
806+
}
807+
808+
And the configuration:
809+
810+
.. configuration-block::
811+
812+
.. code-block:: yaml
813+
814+
# config/services.yaml
815+
services:
816+
App\Handler\One:
817+
tags:
818+
- { name: 'app.handler', priority: 20 }
819+
820+
# ...
821+
822+
.. code-block:: xml
823+
824+
<!-- config/services.xml -->
825+
<?xml version="1.0" encoding="UTF-8" ?>
826+
<container xmlns="http://symfony.com/schema/dic/services"
827+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
828+
xsi:schemaLocation="http://symfony.com/schema/dic/services
829+
http://symfony.com/schema/dic/services/services-1.0.xsd">
830+
831+
<services>
832+
<service id="App\Handler\One">
833+
<tag name="app.handler" priority="20" />
834+
</service>
835+
836+
<!-- ... -->
837+
</services>
838+
</container>
839+
840+
.. code-block:: php
841+
842+
// config/services.php
843+
$container->register(App\Handler\One::class)
844+
->addTag('app.handler', ['priority' => 20]);
845+
846+
// ...
847+
848+
You also can define the name of the static method to implement on each service
849+
with the ``default_index_method`` attribute on the argument.
850+
851+
Based on the previous example ``App\Handler\One`` should look like::
852+
853+
// src/Handler/One.php
854+
namespace App\Handler;
855+
856+
class One
857+
{
858+
public static function someFunctionName(): string
859+
{
860+
return 'handler_one';
861+
}
862+
}
863+
864+
And the configuration:
865+
866+
.. configuration-block::
867+
868+
.. code-block:: yaml
869+
870+
# config/services.yaml
871+
services:
872+
# ...
873+
874+
App\HandlerCollection:
875+
# inject all services tagged with app.handler as first argument
876+
arguments: [!tagged { tag: 'app.handler', index_by: 'key', default_index_method: 'someFunctionName' }]
877+
878+
.. code-block:: xml
879+
880+
<!-- config/services.xml -->
881+
<?xml version="1.0" encoding="UTF-8" ?>
882+
<container xmlns="http://symfony.com/schema/dic/services"
883+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
884+
xsi:schemaLocation="http://symfony.com/schema/dic/services
885+
http://symfony.com/schema/dic/services/services-1.0.xsd">
886+
887+
<services>
888+
889+
<!-- ... --!>
890+
891+
<service id="App\HandlerCollection">
892+
<!-- inject all services tagged with app.handler as first argument -->
893+
<argument type="tagged" tag="app.handler" index-by="key" default-index-method="someFunctionName" />
894+
</service>
895+
</services>
896+
</container>
897+
898+
.. code-block:: php
899+
900+
// config/services.php
901+
// ...
902+
903+
$container->register(App\HandlerCollection::class)
904+
// inject all services tagged with app.handler as first argument
905+
->addArgument(new TaggedIteratorArgument('app.handler', 'key', 'someFunctionName'));
906+
907+
See also :doc:`tagged locator services </service_container/service_subscribers_locators>`

0 commit comments

Comments
 (0)
0