Skip to content

Commit 2b1e48a

Browse files
committed
Merge branch '6.0' into 6.1
* 6.0: [DependencyInjection] Document `stack` definitions
2 parents c89c883 + bd50806 commit 2b1e48a

File tree

1 file changed

+235
-14
lines changed

1 file changed

+235
-14
lines changed

service_container/service_decoration.rst

Lines changed: 235 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
384605
Control the Behavior When the Decorated Service Does Not Exist
385606
--------------------------------------------------------------
386607

0 commit comments

Comments
 (0)