diff --git a/components/dependency_injection/index.rst b/components/dependency_injection/index.rst
index ac0e9d2a7da..20e26e0263e 100644
--- a/components/dependency_injection/index.rst
+++ b/components/dependency_injection/index.rst
@@ -7,6 +7,7 @@
introduction
definitions
compilation
+ tags
factories
parentservices
diff --git a/cookbook/service_container/tags.rst b/components/dependency_injection/tags.rst
similarity index 54%
rename from cookbook/service_container/tags.rst
rename to components/dependency_injection/tags.rst
index 510728bc6a0..708757f0797 100644
--- a/cookbook/service_container/tags.rst
+++ b/components/dependency_injection/tags.rst
@@ -1,33 +1,33 @@
-.. index::
+.. index::
single: Service Container; Tags
How to make your Services use Tags
==================================
-Several of Symfony2's core services depend on tags to recognize which services
-should be loaded, notified of events, or handled in some other special way.
-For example, Twig uses the tag ``twig.extension`` to load extra extensions.
+You can ask a container builder for any services that were tagged when registered
+with it. This is useful in compiler passes where you can find services which
+were registered in config files you do not have control over and make use
+of them. This is useful if your service handles a collection of some kind,
+or implements a "chain", in which several alternative strategies are tried
+until one of them is successful. You can then allow services to be registered
+with a tag and add these services to your collection or chain.
-But you can also use tags in your own bundles. For example in case your service
-handles a collection of some kind, or implements a "chain", in which several alternative
-strategies are tried until one of them is successful. In this article I will use the example
+For example, if you are using Swift Mailer and want to implement a
of a "transport chain", which is a collection of classes implementing ``\Swift_Transport``.
-Using the chain, the Swift mailer may try several ways of transport, until one succeeds.
-This post focuses mainly on the dependency injection part of the story.
+Using the chain, Swift Mailer can try several ways of transport, until one
+succeeds.
To begin with, define the ``TransportChain`` class::
- namespace Acme\MailerBundle;
-
class TransportChain
{
private $transports;
-
+
public function __construct()
{
$this->transports = array();
}
-
+
public function addTransport(\Swift_Transport $transport)
{
$this->transports[] = $transport;
@@ -40,33 +40,29 @@ Then, define the chain as a service:
.. code-block:: yaml
- # src/Acme/MailerBundle/Resources/config/services.yml
parameters:
- acme_mailer.transport_chain.class: Acme\MailerBundle\TransportChain
-
+ acme_mailer.transport_chain.class: TransportChain
+
services:
acme_mailer.transport_chain:
class: %acme_mailer.transport_chain.class%
.. code-block:: xml
-
-
- Acme\MailerBundle\TransportChain
+ TransportChain
-
+
-
+
.. code-block:: php
-
- // src/Acme/MailerBundle/Resources/config/services.php
+
use Symfony\Component\DependencyInjection\Definition;
-
- $container->setParameter('acme_mailer.transport_chain.class', 'Acme\MailerBundle\TransportChain');
-
+
+ $container->setParameter('acme_mailer.transport_chain.class', 'TransportChain');
+
$container->setDefinition('acme_mailer.transport_chain', new Definition('%acme_mailer.transport_chain.class%'));
Define Services with a Custom Tag
@@ -80,7 +76,6 @@ As an example we add the following transports as services:
.. code-block:: yaml
- # src/Acme/MailerBundle/Resources/config/services.yml
services:
acme_mailer.transport.smtp:
class: \Swift_SmtpTransport
@@ -92,67 +87,42 @@ As an example we add the following transports as services:
class: \Swift_SendmailTransport
tags:
- { name: acme_mailer.transport }
-
+
.. code-block:: xml
-
%mailer_host%
-
+
-
+
.. code-block:: php
-
- // src/Acme/MailerBundle/Resources/config/services.php
+
use Symfony\Component\DependencyInjection\Definition;
-
+
$definitionSmtp = new Definition('\Swift_SmtpTransport', array('%mailer_host%'));
$definitionSmtp->addTag('acme_mailer.transport');
$container->setDefinition('acme_mailer.transport.smtp', $definitionSmtp);
-
+
$definitionSendmail = new Definition('\Swift_SendmailTransport');
$definitionSendmail->addTag('acme_mailer.transport');
$container->setDefinition('acme_mailer.transport.sendmail', $definitionSendmail);
-Notice the tags named "acme_mailer.transport". We want the bundle to recognize
-these transports and add them to the chain all by itself. In order to achieve
-this, we need to add a ``build()`` method to the ``AcmeMailerBundle`` class::
-
- namespace Acme\MailerBundle;
-
- use Symfony\Component\HttpKernel\Bundle\Bundle;
- use Symfony\Component\DependencyInjection\ContainerBuilder;
-
- use Acme\MailerBundle\DependencyInjection\Compiler\TransportCompilerPass;
-
- class AcmeMailerBundle extends Bundle
- {
- public function build(ContainerBuilder $container)
- {
- parent::build($container);
-
- $container->addCompilerPass(new TransportCompilerPass());
- }
- }
+Notice the tags named "acme_mailer.transport". This is the custom tag to use ion your compiler pass::
Create a ``CompilerPass``
-------------------------
-You will have spotted a reference to the not yet existing ``TransportCompilerPass`` class.
-This class will make sure that all services with a tag ``acme_mailer.transport``
-will be added to the ``TransportChain`` class by calling the ``addTransport()``
-method. The ``TransportCompilerPass`` should look like this::
+Your compiler pass can then ask the container for any services with the
+custom tag::
- namespace Acme\MailerBundle\DependencyInjection\Compiler;
-
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;
-
+
class TransportCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
@@ -160,9 +130,9 @@ method. The ``TransportCompilerPass`` should look like this::
if (false === $container->hasDefinition('acme_mailer.transport_chain')) {
return;
}
-
+
$definition = $container->getDefinition('acme_mailer.transport_chain');
-
+
foreach ($container->findTaggedServiceIds('acme_mailer.transport') as $id => $attributes) {
$definition->addMethodCall('addTransport', array(new Reference($id)));
}
@@ -176,26 +146,13 @@ to the definition of the ``acme_mailer.transport_chain`` service a call to
The first argument of each of these calls will be the mailer transport service
itself.
-.. note::
-
- By convention, tag names consist of the name of the bundle (lowercase,
- underscores as separators), followed by a dot, and finally the "real"
- name, so the tag "transport" in the AcmeMailerBundle should be: ``acme_mailer.transport``.
+Register the pass with the container
+------------------------------------
-The Compiled Service Definition
--------------------------------
+You also need to register the pass with the container, it will then be
+run when the container is compiled.
-Adding the compiler pass will result in the automatic generation of the following
-lines of code in the compiled service container. In case you are working
-in the "dev" environment, open the file ``/cache/dev/appDevDebugProjectContainer.php``
-and look for the method ``getTransportChainService()``. It should look like this::
-
- protected function getAcmeMailer_TransportChainService()
- {
- $this->services['acme_mailer.transport_chain'] = $instance = new \Acme\MailerBundle\TransportChain();
-
- $instance->addTransport($this->get('acme_mailer.transport.smtp'));
- $instance->addTransport($this->get('acme_mailer.transport.sendmail'));
+ use Symfony\Component\DependencyInjection\ContainerBuilder;
- return $instance;
- }
+ $container = new ContainerBuilder();
+ $container->addCompilerPass(new TransportCompilerPass);
diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc
index 64c9d03358b..0bc2001bb88 100644
--- a/cookbook/map.rst.inc
+++ b/cookbook/map.rst.inc
@@ -92,7 +92,7 @@
* :doc:`/cookbook/service_container/event_listener`
* :doc:`/cookbook/service_container/scopes`
- * :doc:`/cookbook/service_container/tags`
+ * :doc:`/cookbook/service_container/compiler_passes`
* :doc:`/cookbook/security/index`
diff --git a/cookbook/service_container/compiler_passes.rst b/cookbook/service_container/compiler_passes.rst
new file mode 100644
index 00000000000..7182d1953d9
--- /dev/null
+++ b/cookbook/service_container/compiler_passes.rst
@@ -0,0 +1,32 @@
+How to work with Compiler Passes in Bundles
+===========================================
+
+Compiler passes give you an opportunity to manipulate other service
+definitions that have been registered with the service container. You
+can read about how to create them in the components section ":doc:`/components/dependency_injection/compilation`".
+To register a compiler pass from a bundle you need to add it to the build
+method of the bundle definition class::
+
+ namespace Acme\MailerBundle;
+
+ use Symfony\Component\HttpKernel\Bundle\Bundle;
+ use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+ use Acme\MailerBundle\DependencyInjection\Compiler\CustomCompilerPass;
+
+ class AcmeMailerBundle extends Bundle
+ {
+ public function build(ContainerBuilder $container)
+ {
+ parent::build($container);
+
+ $container->addCompilerPass(new CustomCompilerPass());
+ }
+ }
+
+One of the common tasks for compiler passes is to work with tagged services,
+read more about this in the components section ":doc:`/components/dependency_injection/tags`".
+If you are using custom tags in a bundle then by convention, tag names consist
+of the name of the bundle (lowercase, underscores as separators), followed
+by a dot, and finally the "real" name, so the tag "transport" in the AcmeMailerBundle
+should be: ``acme_mailer.transport``.
diff --git a/cookbook/service_container/index.rst b/cookbook/service_container/index.rst
index 3b0a82ad06e..be8ad17868b 100644
--- a/cookbook/service_container/index.rst
+++ b/cookbook/service_container/index.rst
@@ -6,4 +6,4 @@ Service Container
event_listener
scopes
- tags
+ compiler_passes
diff --git a/redirection_map b/redirection_map
index 814b30c3eca..3e979ddb236 100644
--- a/redirection_map
+++ b/redirection_map
@@ -9,6 +9,7 @@
/cookbook/tools/finder /components/finder
/cookbook/service_container/parentservices /components/dependency_injection/parentservices
/cookbook/service_container/factories /components/dependency_injection/factories
+/cookbook/service_container/tags /components/dependency_injection/tags
/reference/configuration/mongodb /bundles/DoctrineMongoDBBundle/config
/reference/YAML /components/yaml
/components/dependency_injection /components/dependency_injection/introduction