From d63c2985e24c7a4b519682ee1a36c69169a17707 Mon Sep 17 00:00:00 2001 From: Anthony MARTIN Date: Thu, 21 Feb 2019 16:06:17 +0100 Subject: [PATCH] [DependencyInjection] Doc for Allow to choose an index for service locator collection --- .../service_subscribers_locators.rst | 206 ++++++++++++++++++ 1 file changed, 206 insertions(+) diff --git a/service_container/service_subscribers_locators.rst b/service_container/service_subscribers_locators.rst index cd043880282..8e1d9b16018 100644 --- a/service_container/service_subscribers_locators.rst +++ b/service_container/service_subscribers_locators.rst @@ -394,6 +394,212 @@ will share identical locators amongst all the services referencing them:: .. _`Command pattern`: https://en.wikipedia.org/wiki/Command_pattern +Tagged Services Locator Collection with Index +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you want to retrieve a specific service within the injected service collector +you can use the ``index_by`` and ``default_index_method`` options of the argument +in combination with ``!tagged_locator`` to define an index. + +In the following example, all services tagged with ``app.handler`` are passed as +first constructor argument to ``App\Handler\HandlerCollection``, +but we can now access a specific injected service: + +.. configuration-block:: + + .. code-block:: yaml + + # config/services.yaml + services: + App\Handler\One: + tags: + - { name: 'app.handler', key: 'handler_one' } + + App\Handler\Two: + tags: + - { name: 'app.handler', key: 'handler_two' } + + App\HandlerCollection: + # inject all services tagged with app.handler as first argument + arguments: [!tagged_locator { tag: 'app.handler', index_by: 'key' }] + + .. code-block:: xml + + + + + + + + + + + + + + + + + + + + + + .. code-block:: php + + // config/services.php + use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; + use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; + + $container->register(App\Handler\One::class) + ->addTag('app.handler', ['key' => 'handler_one']); + + $container->register(App\Handler\Two::class) + ->addTag('app.handler', ['key' => 'handler_two']); + + $container->register(App\Handler\HandlerCollection::class) + // inject all services tagged with app.handler as first argument + ->addArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('app.handler', 'key'))); + +After compilation the ``HandlerCollection`` to retrieve a specific service by it's ``key`` attribute +from the service locator injected, we just have to do ``$serviceLocator->get('handler_two');`` to +retrieve the ``handler_two`` handler:: + + // src/Handler/HandlerCollection.php + namespace App\Handler; + + use Symfony\Component\DependencyInjection\ServiceLocator; + + class HandlerCollection + { + public function __construct(ServiceLocator $locator) + { + $handlerTwo = $locator->get('handler_two'): + } + } + +.. tip:: + + You can omit the ``index_attribute_name`` attribute, by implementing a static + method ``getDefaultIndexAttributeName`` to the handler. + + Based on the previous example ``App\Handler\One`` should look like this:: + + // src/Handler/One.php + namespace App\Handler; + + class One + { + public static function getDefaultIndexName(): string + { + return 'handler_one'; + } + } + + And the configuration: + + .. configuration-block:: + + .. code-block:: yaml + + # config/services.yaml + services: + App\Handler\One: + tags: + - { name: 'app.handler', priority: 20 } + + # ... + + .. code-block:: xml + + + + + + + + + + + + + + + .. code-block:: php + + // config/services.php + $container->register(App\Handler\One::class) + ->addTag('app.handler', ['priority' => 20]); + + // ... + + You also can define the name of the static method to implement on each service + with the ``default_index_method`` attribute on the argument. + + Based on the previous example ``App\Handler\One`` should look like:: + + // src/Handler/One.php + namespace App\Handler; + + class One + { + public static function someFunctionName(): string + { + return 'handler_one'; + } + } + + And the configuration: + + .. configuration-block:: + + .. code-block:: yaml + + # config/services.yaml + services: + # ... + + App\HandlerCollection: + # inject all services tagged with app.handler as first argument + arguments: [!tagged_locator { tag: 'app.handler', index_by: 'key', default_index_method: 'someFunctionName' }] + + .. code-block:: xml + + + + + + + + + + + + + + + + + .. code-block:: php + + // config/services.php + // ... + + $container->register(App\HandlerCollection::class) + // inject all services tagged with app.handler as first argument + ->addArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('app.handler', 'key', 'someFunctionName'))); + +See also :doc:`tagged services ` + Service Subscriber Trait ------------------------