@@ -25,7 +25,8 @@ until you interact with the proxy in some way.
25
25
26
26
.. caution ::
27
27
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.
29
30
30
31
Installation
31
32
------------
@@ -97,6 +98,81 @@ To check if your proxy works you can check the interface of the received object:
97
98
`ocramius/proxy-manager `_, the container will skip over the ``lazy ``
98
99
flag and directly instantiate the service as it would normally do.
99
100
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
+
100
176
Additional Resources
101
177
--------------------
102
178
0 commit comments