Skip to content

Commit e607796

Browse files
author
Anthony MARTIN
committed
[DependencyInjection] Doc for Allow to choose an index for service locator collection
1 parent 6db79cd commit e607796

File tree

1 file changed

+203
-0
lines changed

1 file changed

+203
-0
lines changed

service_container/service_subscribers_locators.rst

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,209 @@ 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+
.. tip::
462+
463+
You can omit the ``index_attribute_name`` attribute, by implementing a static
464+
method ``getDefaultIndexAttributeName`` to the handler.
465+
466+
Based on the previous example ``App\Handler\One`` should look like this::
467+
468+
// src/Handler/One.php
469+
namespace App\Handler;
470+
471+
class One
472+
{
473+
public static function getDefaultIndexName(): string
474+
{
475+
return 'handler_one';
476+
}
477+
}
478+
And the configuration:
479+
480+
.. configuration-block::
481+
482+
.. code-block:: yaml
483+
484+
# config/services.yaml
485+
services:
486+
App\Handler\One:
487+
tags:
488+
- { name: 'app.handler', priority: 20 }
489+
490+
# ...
491+
492+
.. code-block:: xml
493+
494+
<!-- config/services.xml -->
495+
<?xml version="1.0" encoding="UTF-8" ?>
496+
<container xmlns="http://symfony.com/schema/dic/services"
497+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
498+
xsi:schemaLocation="http://symfony.com/schema/dic/services
499+
http://symfony.com/schema/dic/services/services-1.0.xsd">
500+
501+
<services>
502+
<service id="App\Handler\One">
503+
<tag name="app.handler" priority="20" />
504+
</service>
505+
506+
<!-- ... -->
507+
</services>
508+
</container>
509+
510+
.. code-block:: php
511+
512+
// config/services.php
513+
$container->register(App\Handler\One::class)
514+
->addTag('app.handler', ['priority' => 20]);
515+
516+
// ...
517+
518+
You also can define the name of the static method to implement on each service
519+
with the ``default_index_method`` attribute on the argument.
520+
521+
Based on the previous example ``App\Handler\One`` should look like::
522+
523+
// src/Handler/One.php
524+
namespace App\Handler;
525+
526+
class One
527+
{
528+
public static function someFunctionName(): string
529+
{
530+
return 'handler_one';
531+
}
532+
}
533+
And the configuration:
534+
535+
.. configuration-block::
536+
537+
.. code-block:: yaml
538+
539+
# config/services.yaml
540+
services:
541+
# ...
542+
543+
App\HandlerCollection:
544+
# inject all services tagged with app.handler as first argument
545+
arguments: [!tagged_locator { tag: 'app.handler', index_by: 'key', default_index_method: 'someFunctionName' }]
546+
547+
.. code-block:: xml
548+
549+
<!-- config/services.xml -->
550+
<?xml version="1.0" encoding="UTF-8" ?>
551+
<container xmlns="http://symfony.com/schema/dic/services"
552+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
553+
xsi:schemaLocation="http://symfony.com/schema/dic/services
554+
http://symfony.com/schema/dic/services/services-1.0.xsd">
555+
556+
<services>
557+
558+
<!-- ... --!>
559+
560+
<service id="App\HandlerCollection">
561+
<!-- inject all services tagged with app.handler as first argument -->
562+
<argument type="tagged_locator" tag="app.handler" index-by="key" default-index-method="someFunctionName" />
563+
</service>
564+
</services>
565+
</container>
566+
567+
.. code-block:: php
568+
569+
// config/services.php
570+
// ...
571+
572+
$container->register(App\HandlerCollection::class)
573+
// inject all services tagged with app.handler as first argument
574+
->addArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('app.handler', 'key', 'someFunctionName')));
575+
576+
See also :doc:`tagged services </service_container/tags>`
577+
375578
Service Subscriber Trait
376579
------------------------
377580

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