Permalink
Browse files

feature #3753 [DependencyInjection] Add documentation about service d…

…ecoration (romainneutron)

This PR was submitted for the master branch but it was merged into the 2.5 branch instead (closes #3753).

Discussion
----------

[DependencyInjection] Add documentation about service decoration

| Q             | A
| ------------- | ---
| Doc fix?      | yes
| New docs?     | yes (symfony/symfony#10600)
| Applies to    | 2.5+
| Fixed tickets | #3745

Commits
-------

578d2e2 [DependencyInjection] Add documentation about service decoration
  • Loading branch information...
weaverryan committed May 29, 2014
2 parents 6c87f99 + e6bc038 commit 4fd1b49bb54db0dc19aa231bf1949d78537eb851
Showing with 92 additions and 0 deletions.
  1. +92 −0 components/dependency_injection/advanced.rst
@@ -185,3 +185,95 @@ the service itself gets loaded. To do so, you can use the ``file`` directive.
Notice that Symfony will internally call the PHP statement ``require_once``,
which means that your file will be included only once per request.
Decorating Services
-------------------
.. versionadded:: 2.5
Decorated services were introduced in Symfony 2.5.
When overriding an existing definition, the old service is lost:
.. code-block:: php
$container->register('foo', 'FooService');
// this is going to replace the old definition with the new one
// old definition is lost
$container->register('foo', 'CustomFooService');
Most of the time, that's exactly what you want to do. But sometimes,
you might want to decorate the old one instead. In this case, the
old service should be kept around to be able to reference it in the
new one. This configuration replaces ``foo`` with a new one, but keeps
a reference of the old one as ``bar.inner``:
.. configuration-block::
.. code-block:: yaml
bar:
public: false
class: stdClass
decorates: foo
arguments: ["@bar.inner"]
.. code-block:: xml
<service id="bar" class="stdClass" decorates="foo" public="false">
<argument type="service" id="bar.inner" />
</service>
.. code-block:: php
use Symfony\Component\DependencyInjection\Reference;
$container->register('bar', 'stdClass')
->addArgument(new Reference('bar.inner'))
->setPublic(false)
->setDecoratedService('foo');
Here is what's going on here: the ``setDecoratedService()` method tells
the container that the ``bar`` service should replace the ``foo`` service,
renaming ``foo`` to ``bar.inner``.
By convention, the old ``foo`` service is going to be renamed ``bar.inner``,
so you can inject it into your new service.
.. note::
The generated inner id is based on the id of the decorator service
(``bar`` here), not of the decorated service (``foo`` here). This is
mandatory to allow several decorators on the same service (they need to have
different generated inner ids).
Most of the time, the decorator should be declared private, as you will not
need to retrieve it as ``bar`` from the container. The visibility of the
decorated ``foo`` service (which is an alias for ``bar``) will still be the
same as the original ``foo`` visibility.
You can change the inner service name if you want to:
.. configuration-block::
.. code-block:: yaml
bar:
class: stdClass
public: false
decorates: foo
decoration_inner_name: bar.wooz
arguments: ["@bar.wooz"]
.. code-block:: xml
<service id="bar" class="stdClass" decorates="foo" decoration-inner-name="bar.wooz" public="false">
<argument type="service" id="bar.wooz" />
</service>
.. code-block:: php
use Symfony\Component\DependencyInjection\Reference;
$container->register('bar', 'stdClass')
->addArgument(new Reference('bar.wooz'))
->setPublic(false)
->setDecoratedService('foo', 'bar.wooz');

0 comments on commit 4fd1b49

Please sign in to comment.