New in Symfony 4.3: Indexed and Tagged Service Collections

Warning: This post is about an unsupported Symfony version. Some of this information may be out of date. Read the most recent Symfony Docs.
Contributed by
François-Xavier de Guillebon
and Anthony Martin
in #30257.
Symfony provides a shortcut to inject all services tagged with a specific tag, which is a common need in some applications, so you don't have to write a compiler pass just for that. In Symfony 4.3 we improved this to allow accessing the tagged services by your own defined index.
In the following example, services tagged with app.handler
define an
additional attribute called key
. When injecting them into the
App\HandlerCollection
service, you can now define an attribute called
index_by
to tell Symfony which is the index that should be used in the
associative array that contains the tagged services:
1 2 3 4 5 6 7 8 9 10 11 12 13
# 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
# and use the value of the 'key' tag attribute to index the services
arguments: [!tagged { tag: 'app.handler', index_by: 'key' }]
After compiling the service container, the HandlerCollection
service can
iterate over the handlers using the values defined in their key
attributes:
1 2 3 4 5 6 7 8 9 10 11 12
// src/Handler/HandlerCollection.php
namespace App\Handler;
class HandlerCollection
{
public function __construct(iterable $handlers)
{
$handlers = iterator_to_array($handlers);
$handlerTwo = $handlers['handler_two'];
// ...
}
}
Instead of defining the index value in each service tag, you can define this
value in a static method called getDefaultIndexName()
in your service. For
example, this is how the previous App\Handler\One
service would look now:
1 2 3 4 5 6 7 8 9 10 11 12
// src/Handler/One.php
namespace App\Handler;
class One
{
// ...
public static function getDefaultIndexName(): string
{
return 'handler_one';
}
}
The name of this static method is also configurable via the
default_index_method
tag attribute:
1 2 3 4 5 6
# config/services.yaml
services:
# ...
App\HandlerCollection:
arguments: [!tagged { tag: 'app.handler', default_index_method: 'someCustomMethodName' }]
Help the Symfony project!
As with any Open-Source project, contributing code or documentation is the most common way to help, but we also have a wide range of sponsoring opportunities.
Comments




Comments are closed.
To ensure that comments stay relevant, they are closed for old posts.