Як працювати з передачами компілятора

Дата оновлення перекладу 2025-01-17

Як працювати з передачами компілятора

Передачі компілятора надають вам можливість проводити маніпуляції з іншими визначеннями сервісу, які були зареєстровані у сервіс-контейнері.

Якщо ваша передача компілятора відносно невелика, ви можете визначити її всередині класу
класу додатку Kernel замість того, щоб створювати окремий клас передачі компілятора .

Для цього змусьте ваше ядро реалізовувати 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():

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
// 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 process(ContainerBuilder $container): void
    {
        // у цьому методі ви можете маніпулювати сервіс-контейнером:
        // наприклад, зміна якогось сервіс-контейнера:
        $container->getDefinition('app.some_private_service')->setPublic(true);

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

Альтернативно, при використанні :ref:1e4f440fd4cc46b7f0953c86b02c40a391999a3ebuild()`` свого головного класу пакета:

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\AbstractBundle;

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

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

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