Services tagged with the twig.extension tag are collected during the
initialization of TwigBundle and added to Twig as extensions.

Other tags are used to integrate your services into other systems. For a list of
all the tags available in the core Symfony Framework, check out
Built-in Symfony Service Tags. Each of these has a different effect on your service
and many tags require additional arguments (beyond just the name parameter).

For most users, this is all you need to know. If you want to go further and
learn how to create your own custom tags, keep reading.

If you enable autoconfigure, then some tags are
automatically applied for you. That's true for the twig.extension tag: the
container sees that your class extends Twig_Extension (or more accurately,
that it implements Twig_ExtensionInterface) and adds the tag for you.

Tags on their own don't actually alter the functionality of your services in
any way. But if you choose to, you can ask a container builder for a list of
all services that were tagged with some specific tag. This is useful in
compiler passes where you can find these services and use or modify them in
some specific way.

For example, if you are using Swift Mailer you might imagine that you want
to implement a "transport chain", which is a collection of classes implementing
\Swift_Transport. Using the chain, you'll want Swift Mailer to try several
ways of transporting the message until one succeeds.

Now you might want several of the \Swift_Transport classes to be instantiated
and added to the chain automatically using the addTransport() method.
For example, you may add the following transports as services:

// src/DependencyInjection/Compiler/MailTransportPass.phpnamespaceApp\DependencyInjection\Compiler;useSymfony\Component\DependencyInjection\ContainerBuilder;useSymfony\Component\DependencyInjection\Compiler\CompilerPassInterface;useSymfony\Component\DependencyInjection\Reference;useApp\Mail\TransportChain;classMailTransportPassimplementsCompilerPassInterface{publicfunctionprocess(ContainerBuilder$container){// always first check if the primary service is definedif(!$container->has(TransportChain::class)){return;}$definition=$container->findDefinition(TransportChain::class);// find all service IDs with the app.mail_transport tag$taggedServices=$container->findTaggedServiceIds('app.mail_transport');foreach($taggedServicesas$id=>$tags){// add the transport service to the ChainTransport service$definition->addMethodCall('addTransport',array(newReference($id)));}}}

As you can see, when addTransport() is called, it takes not only a Swift_Transport
object, but also a string alias for that transport. So, how can you allow
each tagged transport service to also supply an alias?

Notice that you've added a generic alias key to the tag. To actually
use this, update the compiler:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

useSymfony\Component\DependencyInjection\ContainerBuilder;useSymfony\Component\DependencyInjection\Compiler\CompilerPassInterface;useSymfony\Component\DependencyInjection\Reference;classTransportCompilerPassimplementsCompilerPassInterface{publicfunctionprocess(ContainerBuilder$container){// ...foreach($taggedServicesas$id=>$tags){// a service could have the same tag twiceforeach($tagsas$attributes){$definition->addMethodCall('addTransport',array(newReference($id),$attributes["alias"]));}}}}

The double loop may be confusing. This is because a service can have more
than one tag. You tag a service twice or more with the app.mail_transport
tag. The second foreach loop iterates over the app.mail_transport
tags set for the current service and gives you the attributes.

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 the following example, all services tagged with app.handler are passed as
first constructor argument to the App\HandlerCollection service:

YAML

1
2
3
4
5
6
7
8
9
10
11

# config/services.yamlservices:App\Handler\One:tags:[app.handler]App\Handler\Two:tags:[app.handler]App\HandlerCollection:# inject all services tagged with app.handler as first argumentarguments:[!taggedapp.handler]

// config/services.phpuseSymfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;$container->register(App\Handler\One::class)->addTag('app.handler');$container->register(App\Handler\Two::class)->addTag('app.handler');$container->register(App\HandlerCollection::class)// inject all services tagged with app.handler as first argument->addArgument(newTaggedIteratorArgument('app.handler'));

After compilation the HandlerCollection service is able to iterate over your
application handlers.