setono/composite-compiler-pass

A composite compiler pass for Symfony to make it even easier to create composite services

v1.1.0 2023-05-19 07:49 UTC

This package is auto-updated.

Last update: 2024-04-15 18:12:07 UTC


README

Latest Version Software License Build Status Code Coverage Mutation testing

When you use composite services you find yourself writing the same compiler pass over and over again. This library will give you the compiler pass you need so you don't have to think about it again.

Installation

composer require setono/composite-compiler-pass

Usage

Let's presume you have a composite service like this:

<?php
final class YourCompositeService
{
    /**
     * @var list<object>
     */
    private array $taggedServices = [];

    public function add(object $taggedService): void
    {
        $this->taggedServices[] = $taggedService;
    }
}

that has the service id your_bundle.your_service, and you want to add services that are tagged with tag automatically to this composite service.

In your bundle class you do this:

<?php

use Setono\CompositeCompilerPass\CompositeCompilerPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;

final class YourBundle extends Bundle
{
    public function build(ContainerBuilder $container): void
    {
        $container->addCompilerPass(new CompositeCompilerPass('your_bundle.your_service', 'tag'));
    }
}

NOTICE You can even define your tagged services with a priority and they will be automatically sorted before being added to the composite service. This is thanks to the Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait used under the hood.

Composite service included

The library also comes with a small abstract class you can base your composite service on if you wish. The class is named CompositeService and you can find it here.

Here is an example of how you can use it:

<?php

use Setono\CompositeCompilerPass\CompositeService;

/**
 * @property list<TaggedServiceInterface> $services
 *
 * @extends CompositeService<TaggedServiceInterface>
 */
final class ConcreteCompositeService extends CompositeService implements TaggedServiceInterface
{
    public function process(): void
    {
        foreach ($this->services as $service) {
            // Both your IDE, Psalm, and PHPStan knows that $service is an instance of TaggedServiceInterface
        }
    }
}

interface TaggedServiceInterface
{

}