The ABC Manager 6 core itself uses a variety of compiler passes, with different [pass
orders](http://symfony.com/doc/current/components/dependency_injection/compilation.html#controlling-the-pass-ordering).
They can also come in handy for your bundles when a more advanced logic is required to manipulate the service container
during compilation.
By far the most common way that compiler passes are used is to handle [tagged
services](http://symfony.com/doc/current/components/dependency_injection/tags.html), where a collection of service
definitions are fetched from the container by a common tag and then handled. Example: inserting them into another service
definition as one collection.
In ABC Manager 6, a bundle's `Bundle` class is the component that should configure the *container builder* for that bundle.
Taking a look at the abstract base bundle class `Abc\AbcBundle\Bundle\Bundle`, you will see there is an overloadable
method called `configureContainerBuilder()` that you will need to implement in your Bundle's `Bundle.php` file to
be able to register a compiler pass.
### Creating a Compiler Pass
---
We will now demonstrate a Compiler Pass that creates a new container parameter based
on some environmental settings.
#### Registering a Compiler Pass
First, we will register a new pass in the `ServiceContainerBundle`'s bundle
class by implementing the overloadable public method `configureContainerBuilder()`,
which receives the "Container Builder" instance.
```php
// file: src/Demo/ServiceContainerBundle/Bundle.php
/**
* Configure the container builder
*
* @param Symfony\Component\DependencyInjection\ContainerBuilder $containerBuilder
*/
public function configureContainerBuilder(
\Symfony\Component\DependencyInjection\ContainerBuilder $containerBuilder
)
{
// Register the compiler pass
$containerBuilder->addCompilerPass(
new \Demo\ServiceContainerBundle\CompilerPass\Environment
);
}
```
Via the method `addCompilerPass()` we will add the compiler pass instance.
#### Writing the Compiler Pass
We should now create the actual compiler pass. Matching the namespace used, the filename
for this pass becomes `src/ServiceContainerBundle/CompilerPass/Environment.php`.
Inside the class, we are requried to implement a method called `process()`,
that will be automatically called by the container builder.
A reference to the container builder is passed to this method, allowing us to
modify/add service and parameter definitions in the service container.
In this demonstration we will add a new service container parameter called
`environment`, an array with some environmental values:
```php
// File: src/ServiceContainerBundle/CompilerPass/Environment.php
/**
* Process the builder
*
* @param ContainerBuilder $container
*/
public function process(ContainerBuilder $container)
{
$container->setParameter(
'environment',
[
'phpversion' => phpversion(),
'timezone' => date_default_timezone_get()
]
);
}
```
The environment array parameter is now present in the container and can be used by
other services by referencing: `%environment%`:
The environment values are:
* PHP version: `8.3.15`
* Timezone: `Europe/Amsterdam `
```php
// file: src/Demo/PublicationBundle/Controller/Demo.php:#54
/**
* Demo the compiler passes
*
* @return Response
*/
public function compilerPassesAction()
{
// Retrieve the environment parameter via the container service
// Uses "Abc\HttpBundle\Controller\ContainerAware::get()" to retrieve a service from the container
$environment = $this->get('demo.compiler_pass')->getValue();
...
}
```
```yaml
# File: src/ServiceContainerBundle/Resources/config/services-application.yml
# Compiler Pass example
$application.compiler_pass:
class: Demo\ServiceContainerBundle\Container
calls:
- [setValue, [%environment%]]
```
```twig
# file: compiler-passes.html.twig
The environment values are:
* PHP version: `{{ environment.phpversion }}`
* Timezone: `{{ environment.timezone }}`
```
You should now be able to create your own compiler passes.