A Symfony bundle that can provide lazy access to simpler, more common kinds of registered Twig extensions.
In a typical application using Twig, all extension services need to be instantiated to be added to a Twig environment even if a small minority of extensions will actually be used in any given execution. In a large application, the number of Twig extensions instantiated in this way can become excessive, causing mushrooming memory usage and slowdowns.
For Twig extensions that only declare functions, filters and tests into the Twig environment, this bundle provides a mechanism by which these extensions can be used lazily within a Symfony-based application.
Typically, a Twig extension will be declared into an application using a service definition such as the following:
my_extension:
class: MyBundle\MyExtension
arguments:
- '@my_heavy_dependency'
tags:
- { name: twig.extension }
By default, Symfony's TwigBundle will then ensure that my_extension
will be added to the twig
environment service.
As long as the my_extension
extension adheres to the following rules:
- the extension must only declare functions, filters and tests, and must instantiate them independently of any injected dependencies
- the options for the functions, filters and tests must themselves not be dependent on injected dependencies
then it can be declared as a proxied extension instead.
The same functional effect as above can be achieved by the following declaration:
my_extension:
class: MyBundle\MyExtension
arguments:
- '@my_heavy_dependency'
tags:
- { name: twig.proxied_extension }
With this example, any functions, filters or tests will still be declared into the twig
environment, but the extension object itself will only be instantiated (and therefore, my_heavy_dependency
will itself only be instantiated) once one of these Twig functors are actually used.
In cases where it is useful for Twig extensions to be arranged into groups of proxies (in order to sandbox certain extensions to particular areas of an application), extension services can be tagged with the optional "groups" option. The default group is "default", so to declare additional groups on top of this there should be a comma-separated list in the tag declaration.
The following is the above extension service declaration but declaring in addition a group named "custom":
my_extension:
class: MyBundle\MyExtension
arguments:
- '@my_heavy_dependency'
tags:
- { name: twig.proxied_extension, groups: "default, custom" }
This custom proxy extension can then be accessed with the service ID markup_twig_extension_proxy.proxy.custom
. Typically this would then be added to a manually-declared Twig environment.
With the bundle configuration:
markup_twig_extension_proxy:
proxify_tagged_extensions: true
an application will opt into converting any service tagged twig.extension
into a proxied extension instead (if the extension is compatible, otherwise it will be included in the normal manner).
If you are using a version of Symfony prior to Symfony 3.2, you may need to list this bundle right near the top of your Symfony app kernel in order to convert other extensions. (The compiler pass that achieves this has a priority of 100.)
Named arguments are not supported at the current time - unfortunately these are only caught at template compilation time not application compilation time, so please watch out for that!