@@ -323,17 +323,18 @@ the ``decoration_priority`` option. Its value is an integer that defaults to
323323 ..code-block ::yaml
324324
325325# config/services.yaml
326- Foo :~
326+ services :
327+ Foo :~
327328
328- Bar :
329- decorates :Foo
330- decoration_priority :5
331- arguments :['@.inner']
329+ Bar :
330+ decorates :Foo
331+ decoration_priority :5
332+ arguments :['@.inner']
332333
333- Baz :
334- decorates :Foo
335- decoration_priority :1
336- arguments :['@.inner']
334+ Baz :
335+ decorates :Foo
336+ decoration_priority :1
337+ arguments :['@.inner']
337338
338339 ..code-block ::xml
339340
@@ -365,14 +366,14 @@ the ``decoration_priority`` option. Its value is an integer that defaults to
365366 return function(ContainerConfigurator $configurator) {
366367 $services = $configurator->services();
367368
368- $services->set(Foo::class);
369+ $services->set(\ Foo::class);
369370
370- $services->set(Bar::class)
371- ->decorate(Foo::class, null, 5)
371+ $services->set(\ Bar::class)
372+ ->decorate(\ Foo::class, null, 5)
372373 ->args([service('.inner')]);
373374
374- $services->set(Baz::class)
375- ->decorate(Foo::class, null, 1)
375+ $services->set(\ Baz::class)
376+ ->decorate(\ Foo::class, null, 1)
376377 ->args([service('.inner')]);
377378 };
378379
@@ -381,6 +382,226 @@ The generated code will be the following::
381382
382383 $this->services[Foo::class] = new Baz(new Bar(new Foo()));
383384
385+ Stacking Decorators
386+ -------------------
387+
388+ An alternative to using decoration priorities is to create a ``stack `` of
389+ ordered services, each one decorating the next:
390+
391+ ..configuration-block ::
392+
393+ ..code-block ::yaml
394+
395+ # config/services.yaml
396+ services :
397+ decorated_foo_stack :
398+ stack :
399+ -class :Baz
400+ arguments :['@.inner']
401+ -class :Bar
402+ arguments :['@.inner']
403+ -class :Foo
404+
405+ # using the short syntax:
406+ decorated_foo_stack :
407+ stack :
408+ -Baz :['@.inner']
409+ -Bar :['@.inner']
410+ -Foo :~
411+
412+ # can be simplified when autowiring is enabled:
413+ decorated_foo_stack :
414+ stack :
415+ -Baz :~
416+ -Bar :~
417+ -Foo :~
418+
419+ ..code-block ::xml
420+
421+ <!-- config/services.xml-->
422+ <?xml version =" 1.0" encoding =" UTF-8" ?>
423+ <container xmlns =" http://symfony.com/schema/dic/services"
424+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
425+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
426+ https://symfony.com/schema/dic/services/services-1.0.xsd"
427+ >
428+ <services >
429+ <stack id =" decorated_foo_stack" >
430+ <service class =" Baz" >
431+ <argument type =" service" id =" .inner" />
432+ </service >
433+ <service class =" Bar" >
434+ <argument type =" service" id =" .inner" />
435+ </service >
436+ <service class =" Foo" />
437+ </stack >
438+
439+ <!-- can be simplified when autowiring is enabled:-->
440+ <stack id =" decorated_foo_stack" >
441+ <service class =" Baz" />
442+ <service class =" Bar" />
443+ <service class =" Foo" />
444+ </stack >
445+ </services >
446+ </container >
447+
448+ ..code-block ::php
449+
450+ // config/services.php
451+ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
452+
453+ return function(ContainerConfigurator $container) {
454+ $container->services()
455+ ->stack('decorated_foo_stack', [
456+ inline_service(\Baz::class)->args([service('.inner')]),
457+ inline_service(\Bar::class)->args([service('.inner')]),
458+ inline_service(\Foo::class),
459+ ])
460+
461+ // can be simplified when autowiring is enabled:
462+ ->stack('decorated_foo_stack', [
463+ inline_service(\Baz::class),
464+ inline_service(\Bar::class),
465+ inline_service(\Foo::class),
466+ ])
467+ ;
468+ };
469+
470+ The result will be the same as in the previous section::
471+
472+ $this->services['decorated_foo_stack'] = new Baz(new Bar(new Foo()));
473+
474+ Like aliases, a ``stack `` can only use ``public `` and ``deprecated `` attributes.
475+
476+ Each frame of the ``stack `` can be either an inlined service, a reference or a
477+ child definition.
478+ The latter allows embedding ``stack `` definitions into each others, here's an
479+ advanced example of composition:
480+
481+ ..configuration-block ::
482+
483+ ..code-block ::yaml
484+
485+ # config/services.yaml
486+ services :
487+ some_decorator :
488+ class :App\Decorator
489+
490+ embedded_stack :
491+ stack :
492+ -alias :some_decorator
493+ -App\Decorated :~
494+
495+ decorated_foo_stack :
496+ stack :
497+ -parent :embedded_stack
498+ -Baz :~
499+ -Bar :~
500+ -Foo :~
501+
502+ ..code-block ::xml
503+
504+ <!-- config/services.xml-->
505+ <?xml version =" 1.0" encoding =" UTF-8" ?>
506+ <container xmlns =" http://symfony.com/schema/dic/services"
507+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
508+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
509+ https://symfony.com/schema/dic/services/services-1.0.xsd"
510+ >
511+ <services >
512+ <service id =" some_decorator" class =" App\Decorator" />
513+
514+ <stack id =" embedded_stack" >
515+ <service alias =" some_decorator" />
516+ <service class =" App\Decorated" />
517+ </stack >
518+
519+ <stack id =" decorated_foo_stack" >
520+ <service parent =" embedded_stack" />
521+ <service class =" Baz" />
522+ <service class =" Bar" />
523+ <service class =" Foo" />
524+ </stack >
525+ </services >
526+ </container >
527+
528+ ..code-block ::php
529+
530+ // config/services.php
531+ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
532+
533+ use App\Decorated;
534+ use App\Decorator;
535+
536+ return function(ContainerConfigurator $container) {
537+ $container->services()
538+ ->set('some_decorator', Decorator::class)
539+
540+ ->stack('embedded_stack', [
541+ service('some_decorator'),
542+ inline_service(Decorated::class),
543+ ])
544+
545+ ->stack('decorated_foo_stack', [
546+ inline_service()->parent('embedded_stack'),
547+ inline_service(\Baz::class),
548+ inline_service(\Bar::class),
549+ inline_service(\Foo::class),
550+ ])
551+ ;
552+ };
553+
554+ The result will be::
555+
556+ $this->services['decorated_foo_stack'] = new App\Decorator(new App\Decorated(new Baz(new Bar(new Foo()))));
557+
558+ ..note ::
559+
560+ To change existing stacks (i.e. from a compiler pass), you can access each
561+ frame by its generated id with the following structure:
562+ ``.stack_id.frame_key ``.
563+ From the example above, ``.decorated_foo_stack.1 `` would be a reference to
564+ the inlined ``Baz `` service and ``.decorated_foo_stack.0 `` to the embedded
565+ stack.
566+ To get more explicit ids, you can give a name to each frame:
567+
568+ ..configuration-block ::
569+
570+ ..code-block ::yaml
571+
572+ # ...
573+ decorated_foo_stack :
574+ stack :
575+ first :
576+ parent :embedded_stack
577+ second :
578+ Baz :~
579+ # ...
580+
581+ ..code-block ::xml
582+
583+ <!-- ...-->
584+ <stack id =" decorated_foo_stack" >
585+ <service id =" first" parent =" embedded_stack" />
586+ <service id =" second" class =" Baz" />
587+ <!-- ...-->
588+ </stack >
589+
590+ ..code-block ::php
591+
592+ // ...
593+ ->stack('decorated_foo_stack', [
594+ 'first' => inline_service()->parent('embedded_stack'),
595+ 'second' => inline_service(\Baz::class),
596+ // ...
597+ ])
598+
599+ The ``Baz `` frame id will now be ``.decorated_foo_stack.second ``.
600+
601+ ..versionadded ::5.1
602+
603+ The ability to define ``stack `` was introduced in Symfony 5.1.
604+
384605Control the Behavior When the Decorated Service Does Not Exist
385606--------------------------------------------------------------
386607