Skip to content

How to Work with Compiler Passes

Edit this page

Compiler passes give you an opportunity to manipulate other service definitions that have been registered with the service container.

If your compiler pass is relatively small, you can define it inside the application's Kernel class instead of creating a separate compiler pass class.

To do so, make your kernel implement CompilerPassInterface and add the compiler pass code inside the process() method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// src/Kernel.php
namespace App;

use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;

class Kernel extends BaseKernel implements CompilerPassInterface
{
    use MicroKernelTrait;

    // ...

    public function process(ContainerBuilder $container): void
    {
        // in this method you can manipulate the service container:
        // for example, changing some container service:
        $container->getDefinition('app.some_private_service')->setPublic(true);

        // or processing tagged services:
        foreach ($container->findTaggedServiceIds('some_tag') as $id => $tags) {
            // ...
        }
    }
}

If you create separate compiler pass classes, enable them in the build() method of the application kernel:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// src/Kernel.php
namespace App;

use App\DependencyInjection\Compiler\CustomPass;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;

class Kernel extends BaseKernel
{
    use MicroKernelTrait;

    // ...

    protected function build(ContainerBuilder $container): void
    {
        $container->addCompilerPass(new CustomPass());
    }
}

Working with Compiler Passes in Bundles

Bundles can define compiler passes in the build() method of the main bundle class (this is not needed when implementing the process() method in the extension):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// src/MyBundle/MyBundle.php
namespace App\MyBundle;

use App\DependencyInjection\Compiler\CustomPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;

class MyBundle extends AbstractBundle
{
    public function build(ContainerBuilder $container): void
    {
        $container->addCompilerPass(new CustomPass());
    }
}

If your compiler pass is relatively small, you can make the main bundle class implements CompilerPassInterface so that it can add itself:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// src/MyBundle/MyBundle.php
namespace App\MyBundle;

use App\DependencyInjection\Compiler\CustomPass;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;

class MyBundle extends AbstractBundle implements CompilerPassInterface
{

    public function build(ContainerBuilder $container): void
    {
        $container->addCompilerPass($this);
    }

    public function process(ContainerBuilder $container): void
    {
        // in this method you can manipulate the service container:
        // for example, changing some container service:
        $container->getDefinition('app.some_private_service')->setPublic(true);

        // or processing tagged services:
        foreach ($container->findTaggedServiceIds('some_tag') as $id => $tags) {
            // ...
        }
    }
}

If you are using custom service tags in a bundle, the convention is to format tag names by starting with the bundle's name in lowercase (using underscores as separators), followed by a dot, and finally the specific tag name. For example, to introduce a "transport" tag in your AcmeMailerBundle, you would name it acme_mailer.transport.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
TOC
    Version