Skip to content

Commit 988994d

Browse files
committed
feature #12442 Documented "Handling decorations on non existent service" (mtarld)
This PR was merged into the 4.4 branch. Discussion ---------- Documented "Handling decorations on non existent service" Documentation part for the PR: symfony/symfony#33854 Commits ------- cb07e30 Add "Handling decorations on non existent service"
2 parents 2fcdf7c + cb07e30 commit 988994d

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed

service_container/service_decoration.rst

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,4 +313,115 @@ The generated code will be the following::
313313

314314
$this->services[Foo::class] = new Baz(new Bar(new Foo()));
315315

316+
Control the Behavior When the Decorated Service Does Not Exist
317+
--------------------------------------------------------------
318+
319+
.. versionadded:: 4.4
320+
321+
The ``decoration_on_invalid`` option has been introduced in Symfony 4.4.
322+
In previous versions, a ``ServiceNotFoundException`` was always thrown.
323+
324+
When you decorate a service that doesn't exist, the ``decoration_on_invalid``
325+
option allows you to choose the behavior to adopt.
326+
327+
Three different behaviors are available:
328+
329+
* ``exception``: A ``ServiceNotFoundException`` will be thrown telling that decorator's dependency is missing. (default)
330+
* ``ignore``: The container will remove the decorator.
331+
* ``null``: The container will keep the decorator service and will set the decorated one to ``null``.
332+
333+
.. configuration-block::
334+
335+
.. code-block:: yaml
336+
337+
# config/services.yaml
338+
Foo: ~
339+
340+
Bar:
341+
decorates: Foo
342+
decoration_on_invalid: ignore
343+
arguments: ['@Bar.inner']
344+
345+
.. code-block:: xml
346+
347+
<!-- config/services.xml -->
348+
<?xml version="1.0" encoding="UTF-8" ?>
349+
350+
<container xmlns="http://symfony.com/schema/dic/services"
351+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
352+
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">
353+
354+
<services>
355+
<service id="Foo"/>
356+
357+
<service id="Bar" decorates="Foo" decoration-on-invalid="ignore">
358+
<argument type="service" id="Bar.inner"/>
359+
</service>
360+
</services>
361+
</container>
362+
363+
.. code-block:: php
364+
365+
// config/services.php
366+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
367+
368+
use Symfony\Component\DependencyInjection\ContainerInterface;
369+
370+
return function(ContainerConfigurator $configurator) {
371+
$services = $configurator->services();
372+
373+
$services->set(Foo::class);
374+
375+
$services->set(Bar::class)
376+
->decorate(Foo::class, null, 0, ContainerInterface::IGNORE_ON_INVALID_REFERENCE)
377+
->args([ref(Bar::class.'.inner')])
378+
;
379+
};
380+
381+
.. caution::
382+
383+
When using ``null``, you may have to update the decorator constructor in
384+
order to make decorated dependency nullable.
385+
386+
.. configuration-block::
387+
388+
.. code-block:: yaml
389+
390+
App\Service\DecoratorService:
391+
decorates: Acme\OptionalBundle\Service\OptionalService
392+
decoration_on_invalid: null
393+
arguments: ['@App\Service\DecoratorService.inner']
394+
395+
.. code-block:: php
396+
397+
namespace App\Service;
398+
399+
use Acme\OptionalBundle\Service\OptionalService;
400+
401+
class DecoratorService
402+
{
403+
private $decorated;
404+
405+
public function __construct(?OptionalService $decorated)
406+
{
407+
$this->decorated = $decorated;
408+
}
409+
410+
public function tellInterestingStuff(): string
411+
{
412+
if (!$this->decorated) {
413+
return 'Just one interesting thing';
414+
}
415+
416+
return $this->decorated->tellInterestingStuff().' + one more interesting thing';
417+
}
418+
}
419+
420+
.. note::
421+
422+
Sometimes, you may want to add a compiler pass that creates service
423+
definitions on the fly. If you want to decorate such a service,
424+
be sure that your compiler pass is registered with ``PassConfig::TYPE_BEFORE_OPTIMIZATION``
425+
type so that the decoration pass will be able to find the created services.
426+
316427
.. _`Decorator pattern`: https://en.wikipedia.org/wiki/Decorator_pattern

0 commit comments

Comments
 (0)