8000 [DependencyInjection] Doc for Allow to choose an index for service lo… · symfony/symfony-docs@10cfeb0 · GitHub
[go: up one dir, main page]

Skip to content

Commit 10cfeb0

Browse files
author
Anthony MARTIN
committed
[DependencyInjection] Doc for Allow to choose an index for service locator collection
1 parent f034d99 commit 10cfeb0

File tree

1 file changed

+206
-0
lines changed

1 file changed

+206
-0
lines changed

service_container/service_subscribers_locators.rst

Lines changed: 206 additions & 0 deletions
< F42D tr class="diff-line-row">
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,212 @@ will share identical locators amongst all the services referencing them::
372372

373373
.. _`Command pattern`: https://en.wikipedia.org/wiki/Command_pattern
374374

375+
Tagged Services Locator Collection with Index
376+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
377+
378+
If you want to retrieve a specific service within the injected service collector
379+
you can use the ``index_by`` and ``default_index_method`` options of the argument
380+
in combination with ``!tagged_locator`` to define an index.
381+
382+
In the following example, all services tagged with ``app.handler`` are passed as
383+
first constructor argument to ``App\Handler\HandlerCollection``,
384+
but we can now access a specific injected service:
385+
386+
.. configuration-block::
387+
388+
.. code-block:: yaml
389+
390+
# config/services.yaml
391+
services:
392+
App\Handler\One:
393+
tags:
394+
- { name: 'app.handler', key: 'handler_one' }
395+
396+
App\Handler\Two:
397+
tags:
398+
- { name: 'app.handler', key: 'handler_two' }
399+
400+
App\HandlerCollection:
401+
# inject all services tagged with app.handler as first argument
402+
arguments: [!tagged_locator { tag: 'app.handler', index_by: 'key' }]
403+
404+
.. code-block:: xml
405+
406+
<!-- config/services.xml -->
407+
<?xml version="1.0" encoding="UTF-8" ?>
408+
<container xmlns="http://symfony.com/schema/dic/services"
409+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
410+
xsi:schemaLocation="http://symfony.com/schema/dic/services
411+
http://symfony.com/schema/dic/services/services-1.0.xsd">
412+
413+
<services>
414+
<service id="App\Handler\One">
415+
<tag name="app.handler" key="handler_one" />
416+
</service>
417+
418+
<service id="App\Handler\Two">
419+
<tag name="app.handler" key="handler_two" />
420+
</service>
421+
422+
<service id="App\HandlerCollection">
423+
<!-- inject all services tagged with app.handler as first argument -->
424+
<argument type="tagged_locator" tag="app.handler" index-by="key" />
425+
</service>
426+
</services>
427+
</container>
428+
429+
.. code-block:: php
430+
431+
// config/services.php
432+
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
433+
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
434+
435+
$container->register(App\Handler\One::class)
436+
->addTag('app.handler', ['key' => 'handler_one']);
437+
438+
$container->register(App\Handler\Two::class)
439+
->addTag('app.handler', ['key' => 'handler_two']);
440+
441+
$container->register(App\Handler\HandlerCollection::class)
442+
// inject all services tagged with app.handler as first argument
443+
->addArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('app.handler', 'key')));
444+
445+
After compilation the ``HandlerCollection`` to retrieve a specific service by it's ``key`` attribute
446+
from the service locator injected, we just have to do ``$serviceLocator->get('handler_two');`` to
447+
retrieve the ``handler_two`` handler::
448+
449+
// src/Handler/HandlerCollection.php
450+
namespace App\Handler;
451+
452+
use Symfony\Component\DependencyInjection\ServiceLocator;
453+
454+
class HandlerCollection
455+
{
456+
public function __construct(ServiceLocator $locator)
457+
{
458+
$handlerTwo = $locator->get('handler_two'):
459+
}
460+
}
461+
462+
.. tip::
463+
464+
You can omit the ``index_attribute_name`` attribute, by implementing a static
465+
method ``getDefaultIndexAttributeName`` to the handler.
466+
467+
Based on the previous example ``App\Handler\One`` should look like this::
468+
469+
// src/Handler/One.php
470+
namespace App\Handler;
471+
472+
class One
473+
{
474+
public static function getDefaultIndexName(): string
475+
{
476+
return 'handler_one';
477+
}
478+
}
479+
480+
And the configuration:
481+
482+
.. configuration-block::
483+
484+
.. code-block:: yaml
485+
486+
# config/services.yaml
487+
services:
488+
App\Handler\One:
489+
tags:
490+
- { name: 'app.handler', priority: 20 }
491+
492+
# ...
493+
494+
.. code-block:: xml
495+
496+
<!-- config/services.xml -->
497+
<?xml version="1.0" encoding="UTF-8" ?>
498+
<container xmlns="http://symfony.com/schema/dic/services"
499+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
500+
xsi:schemaLocation="http://symfony.com/schema/dic/services
501+
http://symfony.com/schema/dic/services/services-1.0.xsd">
502+
503+
<services>
504+
<service id="App\Handler\One">
505+
<tag name="app.handler" priority="20" />
506+
</service>
507+
508+
<!-- ... -->
509+
</services>
510+
</container>
511+
512+
.. code-block:: php
513+
514+
// config/services.php
515+
$container->register(App\Handler\One::class)
516+
->addTag('app.handler', ['priority' => 20]);
517+
518+
// ...
519+
520+
You also can define the name of the static method to implement on each service
521+
with the ``default_index_method`` attribute on the argument.
522+
523+
Based on the previous example ``App\Handler\One`` should look like::
524+
525+
// src/Handler/One.php
526+
namespace App\Handler;
527+
528+
class One
529+
{
530+
public static function someFunctionName(): string
531+
{
532+
return 'handler_one';
533+
}
534+
}
535+
536+
And the configuration:
537+
538+
.. configuration-block::
539+
540+
.. code-block:: yaml
541+
542+
# config/services.yaml
543+
services:
544+
# ...
545+
546+
App\HandlerCollection:
547+
# inject all services tagged with app.handler as first argument
548+
arguments: [!tagged_locator { tag: 'app.handler', index_by: 'key', default_index_method: 'someFunctionName' }]
549+
550+
.. code-block:: xml
551+
552+
<!-- config/services.xml -->
553+
<?xml version="1.0" encoding="UTF-8" ?>
554+
<container xmlns="http://symfony.com/schema/dic/services"
555+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
556+
xsi:schemaLocation="http://symfony.com/schema/dic/services
557+
http://symfony.com/schema/dic/services/services-1.0.xsd">
558+
559+
<services>
560+
561+
<!-- ... --!>
562+
563+
<service id="App\HandlerCollection">
564+
<!-- inject all services tagged with app.handler as first argument -->
565+
<argument type="tagged_locator" tag="app.handler" index-by="key" default-index-method="someFunctionName" />
566+
</service>
567+
</services>
568+
</container>
569+
570+
.. code-block:: php
571+
572+
// config/services.php
573+
// ...
574+
575+
$container->register(App\HandlerCollection::class)
576+
// inject all services tagged with app.handler as first argument
577+
->addArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('app.handler', 'key', 'someFunctionName')));
578+
579+
See also :doc:`tagged services </service_container/tags>`
580+
375581
Service Subscriber Trait
376582
------------------------
377583

0 commit comments

Comments
 (0)
0