@@ -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
3031Installation
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+
100176Additional Resources
101177--------------------
102178
0 commit comments