Skip to content

Commit a18cae1

Browse files
committed
[DependencyInjection] Update the article about compiler passes
1 parent 4964d30 commit a18cae1

File tree

1 file changed

+54
-26
lines changed

1 file changed

+54
-26
lines changed

service_container/compiler_passes.rst

+54-26
Original file line numberDiff line numberDiff line change
@@ -3,53 +3,85 @@ How to Work with Compiler Passes
33

44
Compiler passes give you an opportunity to manipulate other
55
:doc:`service definitions </service_container/definitions>` that have been
6-
registered with the service container. You can read about how to create them in
7-
the components section ":ref:`components-di-separate-compiler-passes`".
6+
registered with the service container.
87

9-
Compiler passes are registered in the ``build()`` method of the application kernel::
8+
.. _kernel-as-compiler-pass:
9+
10+
If your compiler pass is relatively small, you can define it inside the
11+
application's ``Kernel`` class instead of creating a
12+
:ref:`separate compiler pass class <components-di-separate-compiler-passes>`.
13+
14+
To do so, make your kernel implement :class:`Symfony\\Component\\DependencyInjection\\Compiler\\CompilerPassInterface`
15+
and add the compiler pass code inside the ``process()`` method::
1016

1117
// src/Kernel.php
1218
namespace App;
1319

14-
use App\DependencyInjection\Compiler\CustomPass;
1520
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
21+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1622
use Symfony\Component\DependencyInjection\ContainerBuilder;
1723
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
1824

19-
class Kernel extends BaseKernel
25+
class Kernel extends BaseKernel implements CompilerPassInterface
2026
{
2127
use MicroKernelTrait;
2228

2329
// ...
2430

25-
protected function build(ContainerBuilder $container): void
31+
public function process(ContainerBuilder $container): void
2632
{
27-
$container->addCompilerPass(new CustomPass());
33+
// in this method you can manipulate the service container:
34+
// for example, changing some container service:
35+
$container->getDefinition('app.some_private_service')->setPublic(true);
36+
37+
// or processing tagged services:
38+
foreach ($container->findTaggedServiceIds('some_tag') as $id => $tags) {
39+
// ...
40+
}
2841
}
2942
}
3043

31-
.. _kernel-as-compiler-pass:
32-
33-
One of the most common use-cases of compiler passes is to work with :doc:`tagged
34-
services </service_container/tags>`. In those cases, instead of creating a
35-
compiler pass, you can make the kernel implement
36-
:class:`Symfony\\Component\\DependencyInjection\\Compiler\\CompilerPassInterface`
37-
and process the services inside the ``process()`` method::
44+
If you create separate compiler pass classes, enable them in the ``build()``
45+
method of the application kernel::
3846

3947
// src/Kernel.php
4048
namespace App;
4149

50+
use App\DependencyInjection\Compiler\CustomPass;
4251
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
43-
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
4452
use Symfony\Component\DependencyInjection\ContainerBuilder;
4553
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
4654

47-
class Kernel extends BaseKernel implements CompilerPassInterface
55+
class Kernel extends BaseKernel
4856
{
4957
use MicroKernelTrait;
5058

5159
// ...
5260

61+
protected function build(ContainerBuilder $container): void
62+
{
63+
$container->addCompilerPass(new CustomPass());
64+
}
65+
}
66+
67+
Working with Compiler Passes in Bundles
68+
---------------------------------------
69+
70+
If your compiler pass is relatively small, you can add it directly in the main
71+
bundle class. To do so, make your bundle implement the
72+
:class:`Symfony\\Component\\DependencyInjection\\Compiler\\CompilerPassInterface`
73+
and place the compiler pass code inside the ``process()`` method of the main
74+
bundle class::
75+
76+
// src/MyBundle/MyBundle.php
77+
namespace App\MyBundle;
78+
79+
use App\DependencyInjection\Compiler\CustomPass;
80+
use Symfony\Component\DependencyInjection\ContainerBuilder;
81+
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
82+
83+
class MyBundle extends AbstractBundle
84+
{
5385
public function process(ContainerBuilder $container): void
5486
{
5587
// in this method you can manipulate the service container:
@@ -63,12 +95,8 @@ and process the services inside the ``process()`` method::
6395
}
6496
}
6597

66-
Working with Compiler Passes in Bundles
67-
---------------------------------------
68-
69-
:doc:`Bundles </bundles>` can define compiler passes in the ``build()`` method of
70-
the main bundle class (this is not needed when implementing the ``process()``
71-
method in the extension)::
98+
Alternatively, when using :ref:`separate compiler pass classes <components-di-separate-compiler-passes>`,
99+
bundles can enable them in the ``build()`` method of their main bundle class::
72100

73101
// src/MyBundle/MyBundle.php
74102
namespace App\MyBundle;
@@ -88,7 +116,7 @@ method in the extension)::
88116
}
89117

90118
If you are using custom :doc:`service tags </service_container/tags>` in a
91-
bundle then by convention, tag names consist of the name of the bundle
92-
(lowercase, underscores as separators), followed by a dot, and finally the
93-
"real" name. For example, if you want to introduce some sort of "transport" tag
94-
in your AcmeMailerBundle, you should call it ``acme_mailer.transport``.
119+
bundle, the convention is to format tag names by starting with the bundle's name
120+
in lowercase (using underscores as separators), followed by a dot, and finally
121+
the specific tag name. For example, to introduce a "transport" tag in your
122+
AcmeMailerBundle, you would name it ``acme_mailer.transport``.

0 commit comments

Comments
 (0)