@@ -306,46 +306,94 @@ For more details, see :doc:`/cookbook/bundles/prepend_extension`, which
306
306
is specific to the Symfony Framework, but contains more details about this
307
307
feature.
308
308
309
- Creating a Compiler Pass
310
- ------------------------
309
+ .. _ creating-a-compiler-pass :
310
+ .. _ components-di-compiler-pass :
311
311
312
- You can also create and register your own compiler passes with the container.
313
- To create a compiler pass it needs to implement the
314
- :class: `Symfony\\ Component\\ DependencyInjection\\ Compiler\\ CompilerPassInterface `
315
- interface. The compiler pass gives you an opportunity to manipulate the
316
- service definitions that have been compiled. This can be very powerful,
317
- but is not something needed in everyday use.
312
+ Execute Code During Compilation
313
+ -------------------------------
318
314
319
- The compiler pass must have the ``process `` method which is passed the container
320
- being compiled::
315
+ You can also execute custom code during compilation by writing your own
316
+ compiler pass. By implementing
317
+ :class: `Symfony\\ Component\\ DependencyInjection\\ Compiler\\ CompilerPassInterface `
318
+ in your extension, the added ``process() `` method will be called during
319
+ compilation::
321
320
321
+ // ...
322
322
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
323
- use Symfony\Component\DependencyInjection\ContainerBuilder;
324
323
325
- class CustomCompilerPass implements CompilerPassInterface
324
+ class AcmeDemoExtension implements ExtensionInterface, CompilerPassInterface
326
325
{
327
326
public function process(ContainerBuilder $container)
328
327
{
329
- // ...
328
+ // ... do something during the compilation
330
329
}
330
+
331
+ // ...
331
332
}
332
333
334
+ .. versionadded :: 2.8
335
+ Prior to Symfony 2.8, extensions implementing ``CompilerPassInterface ``
336
+ were not automatically registered. You needed to register them as explained
337
+ in :ref: `the next section <components-di-separate-compiler-passes >`.
338
+
339
+ As ``process() `` is called *after * all extensions are loaded, it allows you to
340
+ edit service definitions of other extensions as well as retrieving information
341
+ about service definitions.
342
+
333
343
The container's parameters and definitions can be manipulated using the
334
- methods described in the :doc: `/components/dependency_injection/definitions `.
335
- One common thing to do in a compiler pass is to search for all services
336
- that have a certain tag in order to process them in some way or dynamically
337
- plug each into some other service.
344
+ methods described in :doc: `/components/dependency_injection/definitions `.
345
+
346
+ .. note ::
347
+
348
+ Please note that the ``process() `` method in the extension class is
349
+ called during the optimization step. You can read
350
+ :ref: `the next section <components-di-separate-compiler-passes >` if you
351
+ need to edit the container during another step.
352
+
353
+ .. note ::
354
+
355
+ As a rule, only work with services definition in a compiler pass and do not
356
+ create service instances. In practice, this means using the methods
357
+ ``has() ``, ``findDefinition() ``, ``getDefinition() ``, ``setDefinition() ``,
358
+ etc. instead of ``get() ``, ``set() ``, etc.
359
+
360
+ .. tip ::
361
+
362
+ Make sure your compiler pass does not require services to exist. Abort the
363
+ method call if some required service is not available.
338
364
339
- Registering a Compiler Pass
340
- ---------------------------
365
+ A common use-case of compiler passes is to search for all service definitions
366
+ that have a certain tag in order to process dynamically plug each into some
367
+ other service. See the section on :ref: `service tags <components-di-compiler-pass-tags >`
368
+ for an example.
341
369
342
- You need to register your custom pass with the container. Its process method
343
- will then be called when the container is compiled::
370
+ .. _components-di-separate-compiler-passes :
371
+
372
+ Creating Separate Compiler Passes
373
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
374
+
375
+ Sometimes, you need to do more than one thing during compliation, want to use
376
+ compiler passes without an extension or you need to execute some code at
377
+ another step in the compilation process. In these cases, you can create a new
378
+ class implementing the ``CompilerPassInterface ``::
379
+
380
+ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
381
+ use Symfony\Component\DependencyInjection\ContainerBuilder;
382
+
383
+ class CustomPass implements CompilerPassInterface
384
+ {
385
+ public function process(ContainerBuilder $container)
386
+ {
387
+ // ... do something during the compilation
388
+ }
389
+ }
390
+
391
+ You then need to register your custom pass with the container::
344
392
345
393
use Symfony\Component\DependencyInjection\ContainerBuilder;
346
394
347
395
$container = new ContainerBuilder();
348
- $container->addCompilerPass(new CustomCompilerPass );
396
+ $container->addCompilerPass(new CustomPass() );
349
397
350
398
.. note ::
351
399
@@ -354,17 +402,16 @@ will then be called when the container is compiled::
354
402
more details.
355
403
356
404
Controlling the Pass Ordering
357
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
405
+ .............................
358
406
359
407
The default compiler passes are grouped into optimization passes and removal
360
408
passes. The optimization passes run first and include tasks such as resolving
361
409
references within the definitions. The removal passes perform tasks such
362
- as removing private aliases and unused services. You can choose where in
363
- the order any custom passes you add are run. By default they will be run
364
- before the optimization passes.
410
+ as removing private aliases and unused services. When registering compiler
411
+ passes using `` addCompilerPass() ``, you can configure when your compiler pass
412
+ is run. By default, they are run before the optimization passes.
365
413
366
- You can use the following constants as the second argument when registering
367
- a pass with the container to control where it goes in the order:
414
+ You can use the following constants to determine when your pass is executed:
368
415
369
416
* ``PassConfig::TYPE_BEFORE_OPTIMIZATION ``
370
417
* ``PassConfig::TYPE_OPTIMIZE ``
@@ -373,14 +420,11 @@ a pass with the container to control where it goes in the order:
373
420
* ``PassConfig::TYPE_AFTER_REMOVING ``
374
421
375
422
For example, to run your custom pass after the default removal passes have
376
- been run::
423
+ been run, use ::
377
424
378
- use Symfony\Component\DependencyInjection\ContainerBuilder;
379
- use Symfony\Component\DependencyInjection\Compiler\PassConfig;
380
-
381
- $container = new ContainerBuilder();
425
+ // ...
382
426
$container->addCompilerPass(
383
- new CustomCompilerPass ,
427
+ new CustomPass() ,
384
428
PassConfig::TYPE_AFTER_REMOVING
385
429
);
386
430
0 commit comments