How to Work with Compiler Passes

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 "Compiling the Container".

コンパイラ パスを使用すると、サービス コンテナに登録されている他のサービス定義を操作できます。それらの作成方法については、コンポーネント セクションの「コンテナのコンパイル」を参照してください。

Compiler passes are registered in the build() method of the application kernel:

コンパイラ パスは、アプリケーション カーネルの build() メソッドに登録されます。
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());
    }
}

One of the most common use-cases of compiler passes is to work with tagged services. In those cases, instead of creating a compiler pass, you can make the kernel implement CompilerPassInterface and process the services inside the process() method:

コンパイラ パスの最も一般的な使用例の 1 つは、タグ付きサービスを操作することです。このような場合、コンパイラ パスを作成する代わりに、カーネルに CompilerPassInterface を実装させ、process() メソッド内でサービスを処理させることができます。
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) {
            // ...
        }
    }
}

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):

バンドルは、メイン バンドル クラスの build() メソッドでコンパイラ パスを定義できます (これは、拡張機能で process() メソッドを実装する場合は必要ありません)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// src/MyBundle/MyBundle.php
namespace App\MyBundle;

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

class MyBundle extends Bundle
{
    public function build(ContainerBuilder $container): void
    {
        parent::build($container);

        $container->addCompilerPass(new CustomPass());
    }
}

If you are using custom service 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. For example, if you want to introduce some sort of "transport" tag in your AcmeMailerBundle, you should call it acme_mailer.transport.

バンドルでカスタム サービス タグを使用している場合、慣例により、タグ名はバンドルの名前 (小文字、区切り文字としてアンダースコア) で構成され、その後にドットが続き、最後に「実際の」名前が続きます。たとえば、AcmeMailerBundle にある種の「トランスポート」タグを導入したい場合は、acme_mailer.transport と呼ぶ必要があります。