@@ -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, but you can use
29+ `Interface Proxifying `_ to work around this limitation.
2930
3031 In PHP versions prior to 8.0 lazy services do not support parameters with
3132 default values for built-in PHP classes (e.g. ``PDO ``).
@@ -100,6 +101,77 @@ To check if your proxy works you can check the interface of the received object:
100101 over the ``lazy `` flag and directly instantiate the service as it would
101102 normally do.
102103
104+ Interface Proxifying
105+ --------------------
106+
107+ Under the hood, proxies generated to lazily load services inherit from the class
108+ used by the service. However, sometimes this is not possible at all (e.g. because
109+ the class is `final `_ and can not be extended) or not convenient.
110+
111+ To workaround this limitation, you can configure a proxy to only implement
112+ specific interfaces.
113+
114+ ..configuration-block ::
115+
116+ ..code-block ::yaml
117+
118+ # config/services.yaml
119+ services :
120+ App\Twig\AppExtension :
121+ lazy :' Twig\Extension\ExtensionInterface'
122+ # or a complete definition:
123+ lazy :true
124+ tags :
125+ -{ name: 'proxy', interface: 'Twig\Extension\ExtensionInterface' }
126+
127+ ..code-block ::xml
128+
129+ <!-- config/services.xml-->
130+ <?xml version =" 1.0" encoding =" UTF-8" ?>
131+ <container xmlns =" http://symfony.com/schema/dic/services"
132+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
133+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
134+ https://symfony.com/schema/dic/services/services-1.0.xsd" >
135+
136+ <services >
137+ <service id =" App\Twig\AppExtension" lazy =" Twig\Extension\ExtensionInterface" />
138+ <!-- or a complete definition:-->
139+ <service id =" App\Twig\AppExtension" lazy =" true" >
140+ <tag name =" proxy" interface =" Twig\Extension\ExtensionInterface" />
141+ </service >
142+ </services >
143+ </container >
144+
145+ ..code-block ::php
146+
147+ // config/services.php
148+ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
149+
150+ use App\Twig\AppExtension;
151+ use Twig\Extension\ExtensionInterface;
152+
153+ return function(ContainerConfigurator $configurator) {
154+ $services = $configurator->services();
155+
156+ $services->set(AppExtension::class)
157+ ->lazy()
158+ ->tag('proxy', ['interface' => ExtensionInterface::class])
159+ ;
160+ };
161+
162+ The virtual `proxy `_ injected into other services will only implement the
163+ specified interfaces and will not extend the original service class, allowing to
164+ lazy load services using `final `_ classes. You can configure the proxy to
165+ implement multiple interfaces by adding new "proxy" tags.
166+
167+ ..tip ::
168+
169+ This feature can also act as a safe guard: given that the proxy does not
170+ extend the original class, only the methods defined by the interface can
171+ be called, preventing to call implementation specific methods. It also
172+ prevents injecting the dependency at all if you type-hinted a concrete
173+ implementation instead of the interface.
174+
103175Additional Resources
104176--------------------
105177