Skip to content

Commit e6bc038

Browse files
romainneutronweaverryan
authored andcommitted
Add documentation about service decoration
1 parent 6c87f99 commit e6bc038

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

components/dependency_injection/advanced.rst

+92
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,95 @@ the service itself gets loaded. To do so, you can use the ``file`` directive.
185185
186186
Notice that Symfony will internally call the PHP statement ``require_once``,
187187
which means that your file will be included only once per request.
188+
189+
Decorating Services
190+
-------------------
191+
192+
.. versionadded:: 2.5
193+
Decorated services were introduced in Symfony 2.5.
194+
195+
When overriding an existing definition, the old service is lost:
196+
197+
.. code-block:: php
198+
199+
$container->register('foo', 'FooService');
200+
201+
// this is going to replace the old definition with the new one
202+
// old definition is lost
203+
$container->register('foo', 'CustomFooService');
204+
205+
Most of the time, that's exactly what you want to do. But sometimes,
206+
you might want to decorate the old one instead. In this case, the
207+
old service should be kept around to be able to reference it in the
208+
new one. This configuration replaces ``foo`` with a new one, but keeps
209+
a reference of the old one as ``bar.inner``:
210+
211+
.. configuration-block::
212+
213+
.. code-block:: yaml
214+
215+
bar:
216+
public: false
217+
class: stdClass
218+
decorates: foo
219+
arguments: ["@bar.inner"]
220+
221+
.. code-block:: xml
222+
223+
<service id="bar" class="stdClass" decorates="foo" public="false">
224+
<argument type="service" id="bar.inner" />
225+
</service>
226+
227+
.. code-block:: php
228+
229+
use Symfony\Component\DependencyInjection\Reference;
230+
231+
$container->register('bar', 'stdClass')
232+
->addArgument(new Reference('bar.inner'))
233+
->setPublic(false)
234+
->setDecoratedService('foo');
235+
236+
Here is what's going on here: the ``setDecoratedService()` method tells
237+
the container that the ``bar`` service should replace the ``foo`` service,
238+
renaming ``foo`` to ``bar.inner``.
239+
By convention, the old ``foo`` service is going to be renamed ``bar.inner``,
240+
so you can inject it into your new service.
241+
242+
.. note::
243+
The generated inner id is based on the id of the decorator service
244+
(``bar`` here), not of the decorated service (``foo`` here). This is
245+
mandatory to allow several decorators on the same service (they need to have
246+
different generated inner ids).
247+
248+
Most of the time, the decorator should be declared private, as you will not
249+
need to retrieve it as ``bar`` from the container. The visibility of the
250+
decorated ``foo`` service (which is an alias for ``bar``) will still be the
251+
same as the original ``foo`` visibility.
252+
253+
You can change the inner service name if you want to:
254+
255+
.. configuration-block::
256+
257+
.. code-block:: yaml
258+
259+
bar:
260+
class: stdClass
261+
public: false
262+
decorates: foo
263+
decoration_inner_name: bar.wooz
264+
arguments: ["@bar.wooz"]
265+
266+
.. code-block:: xml
267+
268+
<service id="bar" class="stdClass" decorates="foo" decoration-inner-name="bar.wooz" public="false">
269+
<argument type="service" id="bar.wooz" />
270+
</service>
271+
272+
.. code-block:: php
273+
274+
use Symfony\Component\DependencyInjection\Reference;
275+
276+
$container->register('bar', 'stdClass')
277+
->addArgument(new Reference('bar.wooz'))
278+
->setPublic(false)
279+
->setDecoratedService('foo', 'bar.wooz');

0 commit comments

Comments
 (0)