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

Дата оновлення перекладу 2023-06-22

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

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

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

        // або обробити теговані сервіси:
        foreach ($containerBuilder->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 $containerBuilder): void
    {
        parent::build($containerBuilder);

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

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