8000 [DependencyInjection] Doc for Allow to choose an index for service locators by XuruDragon · Pull Request #11042 · symfony/symfony-docs · GitHub
[go: up one dir, main page]

Skip to content

[DependencyInjection] Doc for Allow to choose an index for service locators #11042

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 24, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
8000
Diff view
[DependencyInjection] Doc for Allow to choose an index for service lo…
…cator collection
  • Loading branch information
Anthony MARTIN authored and javiereguiluz committed Sep 24, 2019
commit d63c2985e24c7a4b519682ee1a36c69169a17707
206 changes: 206 additions & 0 deletions service_container/service_subscribers_locators.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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

<!-- config/services.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<service id="App\Handler\One">
<tag name="app.handler" key="handler_one" />
</service>

<service id="App\Handler\Two">
<tag name="app.handler" key="handler_two" />
</service>

<service id="App\HandlerCollection">
<!-- inject all services tagged with app.handler as first argument -->
<argument type="tagged_locator" tag="app.handler" index-by="key" />
</service>
</services>
</container>

.. 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

<!-- config/services.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<service id="App\Handler\One">
<tag name="app.handler" priority="20" />
</service>

<!-- ... -->
</services>
</container>

.. 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

<!-- config/services.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>

<!-- ... --!>

<service id="App\HandlerCollection">
<!-- inject all services tagged with app.handler as first argument -->
<argument type="tagged_locator" tag="app.handler" index-by="key" default-index-method="someFunctionName" />
</service>
</services>
</container>

.. 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_container/tags>`

Service Subscriber Trait
------------------------

Expand Down
0