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
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy