10000 [DI] Document proxifying interfaces for lazy services · symfony/symfony-docs@f86b976 · GitHub
[go: up one dir, main page]

Skip to content

Commit f86b976

Browse files
committed
[DI] Document proxifying interfaces for lazy services
Symfony 4.2 introduced the possibility to lazy load services using final classes by proxyfying specific interfaces, but this has not been documented yet.
1 parent cc774af commit f86b976

File tree

1 file changed

+77
-1
lines changed

1 file changed

+77
-1
lines changed

service_container/lazy_services.rst

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ until you interact with the proxy in some way.
2525

2626
.. caution::
2727

28-
Lazy services do not support `final`_ classes.
28+
Lazy services do not support `final`_ classes. You can use `Interface
29+
Proxifying`_ to work around this limitation.
2930

3031
Installation
3132
------------
@@ -97,6 +98,81 @@ To check if your proxy works you can check the interface of the received object:
9798
`ocramius/proxy-manager`_, the container will skip over the ``lazy``
9899
flag and directly instantiate the service as it would normally do.
99100

101+
Interface Proxifying
102+
--------------------
103+
104+
Under the hood, proxies generated to lazily load services inherit from the class
105+
used by the service. But sometimes this is not possible at all (`final`_ classes
106+
can not be extended for example) or not convenient.
107+
108+
To workaround this limitation, you can configure a proxy to only implements
109+
specific interfaces.
110+
111+
.. versionadded:: 4.2
112+
113+
Proxyfying interfaces was introduced in Symfony 4.2.
114+
115+
.. configuration-block::
116+
117+
.. code-block:: yaml
118+
119+
# config/services.yaml
120+
services:
121+
App\Twig\AppExtension:
122+
lazy: 'Twig\Extension\ExtensionInterface'
123+
# or a complete definition:
124+
lazy: true
125+
tags:
126+
- { name: 'proxy', interface: 'Twig\Extension\ExtensionInterface' }
127+
128+
.. code-block:: xml
129+
130+
<!-- config/services.xml -->
131+
<?xml version="1.0" encoding="UTF-8" ?>
132+
<container xmlns="http://symfony.com/schema/dic/services"
133+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
134+
xsi:schemaLocation="http://symfony.com/schema/dic/services
135+
https://symfony.com/schema/dic/services/services-1.0.xsd">
136+
137+
<services>
138+
<service id="App\Twig\AppExtension" lazy="Twig\Extension\ExtensionInterface"/>
139+
<!-- or a complete definition: -->
140+
<service id="App\Twig\AppExtension" lazy="true">
141+
<tag name="proxy" interface="Twig\Extension\ExtensionInterface"/>
142+
</service>
143+
</services>
144+
</container>
145+
146+
.. code-block:: php
147+
148+
// config/services.php
149+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
150+
151+
use App\Twig\AppExtension;
152+
use Twig\Extension\ExtensionInterface;
153+
154+
return function(ContainerConfigurator $configurator) {
155+
$services = $configurator->services();
156+
157+
$services->set(AppExtension::class)
158+
->lazy()
159+
->tag('proxy', ['interface' => ExtensionInterface::class])
160+
;
161+
};
162+
163+
The virtual `proxy`_ injected into other services will only implement the
164+
specified interfaces and will not extend the original service class allowing to
165+
lazy load service using `final`_ classes. You can configure the proxy to
166+
implement multiple interfaces by repeating the "proxy" tag.
167+
168+
.. tip::
169+
170+
This features can also act as a "safe guard". Because the proxy does not
171+
extends the original class, only the methods defined by the interfaces can
172+
be called, preventing to call implementation specific one. It also prevents
173+
injecting the dependency at all if you type hinted a concrete implementation
174+
instead of the interface.
175+
100176
Additional Resources
101177
--------------------
102178

0 commit comments

Comments
 (0)
0