Как работать с передачами компилятора в пакетах

Дата обновления перевода 2023-06-30

Как работать с передачами компилятора в пакетах

Передачи компилятора предоставляют вам возможность производить манипуляции с другими определениями сервиса, которые были зарегистрированы в сервис-контейнере. Вы можете прочитать о том, как создать их в разделе компоненты "".

Compiler passes are registered 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());
    }
}

Одним из наиболее распространенных случаев использования передач компилятора является работа с тегированными сервисами. В таких случаях, вместо создания передачи компилятора, вы можете сделать так, чтобы ядро реализовывало 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
    {
        // в этом методе вы можете изменять сервис-контейнер:
        // например, изменить какой-то сервис-контейнер:
        $container->getDefinition('app.some_private_service')->setPublic(true);

        // или обработать тегированные сервисы:
        foreach ($container->findTaggedServiceIds('some_tag') as $id => $tags) {
            // ...
        }
    }
}

Работа с передачами компилятора в пакетах

Пакеты могут определять передачи компилятора в методе 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());
    }
}

Если вы используете пользовательские сервис-теги в пакете, тогда, по соглашению, имена тегов состоят из имени пакета (нижний регистр, нижние подчеркивания в качестве разделителей), за которым следует точка, а затем "настоящее" имя. Например, если вы хотите представить некоторый тег "транспорта" в вашем AcmeMailerBundle, вы должны назвать его acme_mailer.transport.