In Symfony 3.4, the application kernel can subscribe to events just by
implementing EventSubscriberInterface
and adding the methods to handle the
events. Given that Symfony 4 will push bundle-less applications, in Symfony 3.4
we improved the application kernel to also allow defining compiler passes in it.
To do so, the kernel must implement CompilerPassInterface
and include a method
called process()
where the compiler pass logic is defined:
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 27
// 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)
{
// define here the code to manipulate the service container...
// For example, change some container service:
$container->getDefinition('app.some_private_service')->setPublic(true);
// or process tagged services:
foreach ($container->findTaggedServiceIds('some_tag') as $id => $tags) {
// ...
}
}
}
The compiler pass defined in the kernel is of type PassConfig::TYPE_BEFORE_OPTIMIZATION
and has a priority of -10000
.
Why should we use this instead of https://github.com/symfony/symfony/blob/v3.3.9/src/Symfony/Component/HttpKernel/Kernel.php#L503 ?
This process() method is typically called after all bundles loaded their config and ran their own compiler passes. This means this give the opportunity to alter any service definition. A practical example would be in the "test" environment, to turn some private services to public, so that they can be mocked in test cases.
Of course, this should be used only when access to the fully configured container is required (like all compiler passes). For more common needs, the configuration should be done as usual.
Oh I see it now, thank you !