Compiler Passes

All about Dependency Injection!

## Introduction ---
This demonstration assumes you have already got a good grasp of what a "Compiler Pass" is and can do. If not, please read about it first.
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.
Note - all demonstrations occur in realtime! Open this project in your IDE to view and/or modify the actual sourcecode used in the demonstrations.
### 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.
To change the order in which a compiler pass gets executed during compilation of the container, you should pass a `PassConfig` constant as 2nd parameter to the "addCompilerPass" method, see pass ordering for more info.
#### 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.