Skip to content

Commit 860cf3e

Browse files
committed
minor symfony#11042 [DependencyInjection] Doc for Allow to choose an index for service locators (Anthony MARTIN)
This PR was submitted for the master branch but it was merged into the 4.3 branch instead (closes symfony#11042). Discussion ---------- [DependencyInjection] Doc for Allow to choose an index for service locators Here is the doc for the new feature implemented in : [symfony/symfony#30348](symfony/symfony#30348) that follow the feature [symfony/symfony#30257](symfony/symfony#30257) Commits ------- d63c298 [DependencyInjection] Doc for Allow to choose an index for service locator collection
2 parents b64269e + d63c298 commit 860cf3e

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
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,212 @@ will share identical locators amongst all the services referencing them::
394394

395395
.. _`Command pattern`: https://en.wikipedia.org/wiki/Command_pattern
396396

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

0 commit comments

Comments
 (0)