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.
composer require setono/composite-compiler-passLet'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.
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 and PHPStan know that $service is an instance of TaggedServiceInterface
}
}
}
interface TaggedServiceInterface
{
}