zenstruck / twig-service-bundle
Make functions, static methods, Symfony service methods available in your twig templates.
Fund package maintenance!
kbond
Installs: 2 682
Dependents: 0
Suggesters: 0
Security: 0
Stars: 9
Watchers: 2
Forks: 2
Open Issues: 2
Type:symfony-bundle
Requires
- php: >=8.0
- symfony/framework-bundle: ^5.4|^6.0|^7.0
- symfony/twig-bundle: ^5.4|^6.0|^7.0
Requires (Dev)
- phpstan/phpstan: ^1.4
- phpunit/phpunit: ^9.5
- symfony/console: ^5.4|^6.0|^7.0
- symfony/phpunit-bridge: ^6.1|^7.0
- symfony/var-dumper: ^5.4|^6.0|^7.0
- zenstruck/console-test: ^1.4
README
Making data from your app's services available in twig templates can be done by either:
- Injecting the service/data into the template when rendering.
- Creating a twig extension that has access to the service/data.
For #1, this isn't always a viable option (ie you need this data in your layout). With #2, there is a bit of boilerplate and if done incorrectly (ie not using a runtime or service proxy for heavy services), it could lead to performance issues.
This bundle provides an easy way to make functions, static methods, service methods, and even full service objects available in your twig templates.
Installation
composer require zenstruck/twig-service-bundle
Note
If not added automatically by symfony/flex
, enable ZenstruckTwigServiceBundle
.
Usage
Note
The output for the following functions/filters will be escaped. If your
function\filter returns html that you don't want escaped, use the |raw
filter.
Service Methods as Functions/Filters
You can mark any public method in your configured services with the #[AsTwigFunction]
attribute to make them available within your twig templates with the fn()
twig
function/filter:
// ... use Zenstruck\Twig\AsTwigFunction; class SomeService { // ... #[AsTwigFunction] // will be available as "fn_someMethod()" in twig public function someMethod($arg1, $arg2): string { // ... } #[AsTwigFunction('alias')] // will be available as "fn_alias()" in twig public function anotherMethod($arg1, $arg2): string { // ... } }
In your twig template, use the fn()
function/filter to call:
{# as a function: #} {{ fn('someMethod', 'foo', 'bar') }} {{ fn('alias', 'foo', 'bar') }} {# as a filter: #} {{ 'foo'|fn('someMethod', 'bar') }} {{ 'foo'|fn('alias', 'bar') }}
Dynamic functions/filters are made available. The following is equivalent to above:
{# as a function: #} {{ fn_someMethod('foo', 'bar') }} {{ fn_alias('foo', 'bar') }} {# as a filter: #} {{ 'foo'|fn_someMethod('bar') }} {{ 'foo'|fn_alias('bar') }}
User Defined as Functions/Filters
You can mark any of your custom functions with the #[AsTwigFunction]
attribute
to make them available within your twig templates with the fn()
twig function\filter:
use Zenstruck\Twig\AsTwigFunction; #[AsTwigFunction] // will be available as "some_function" in twig function some_function($arg1, $arg2): string { // ... } #[AsTwigFunction('alias')] // will be available as "alias" in twig function another_function($arg1, $arg2): string { // ... }
In your twig template, use the fn()
function/filter to call:
{# as a function: #} {{ fn('some_function', 'foo', 'bar') }} {{ fn('alias', 'foo', 'bar') }} {# as a filter: #} {{ 'foo'|fn('some_function', 'bar') }} {{ 'foo'|fn('alias', 'bar') }}
Dynamic functions/filters are made available. The following is equivalent to above:
{# as a function: #} {{ fn_some_function('foo', 'bar') }} {{ fn_alias('foo', 'bar') }} {# as a filter: #} {{ 'foo'|fn_some_function('bar') }} {{ 'foo'|fn_alias('bar') }}
3rd-Party Functions/Filters
If you need to make functions, static/service methods available in your twig templates for code you do not control (ie internal PHP functions/3rd party package), you can configure these in the bundle config:
zenstruck_twig_service: functions: - strlen # available as "fn_strlen()" in twig - [service.id, serviceMethod] # available as "fn_serviceMethod()" in twig - [Some\Class, somePublicStaticMethod] # available as "fn_somePublicStaticMethod()" in twig # use the array key to customize the name functions: len: strlen # available as "fn_len()" in twig custom: [service.id, serviceMethod] # available as "fn_custom()" in twig alias: [Some\Class, somePublicStaticMethod] # available as "fn_alias()" in twig
Service Function
Mark any service you'd like to make available in twig templates with the #[AsTwigService]
.
Note
While you can mark any service as a twig service, it is not recommended to mark services that have nothing to do with templating (ie repositories) as such. You can think of twig services as lightweight-lazy-twig-extension-functions whose purpose is to break up/simplify large custom twig extensions.
namespace App\Twig\Service; // ... use Zenstruck\Twig\AsTwigService; #[AsTwigService(alias: 'posts')] class PostService { public function __construct(private PostRepository $repo) { } /** * @return Post[] */ public function latestPosts(int $number = 10): array { return $this->repo->findLatestPosts($number); } }
You're now ready to access the service in any twig template:
{% for post in service('posts').latestPosts(5) %} {# ... #} {% endfor %}
Each service alias is made available as a dynamic function. The following is equivalent to above:
{% for post in service_posts().latestPosts(5) %} {# ... #} {% endfor %}
Invokable Service Filters
You can turn any twig service into a twig filter by having it implement __invoke()
:
namespace App\Twig\Service; // ... use Zenstruck\Twig\AsTwigService; #[AsTwigService(alias: 'image_transformer')] class ImageTransformer { public function __invoke(string $imageUrl, string ...$transformations): string { // adds transformation to url and returns new url } }
In your template, use the service
twig filter:
{{ url|service('image_transformer', 'square-200', 'watermark') }}
Each service alias is made available as a dynamic filter. The following is equivalent to above:
{{ url|service_image_transformer('square-200', 'watermark') }}
Parameter Function
You can access any service container parameter with the provided parameter()
twig function:
{% for locale in parameter('kernel.enabled_locales') %} {# ... #} {% endfor %}
zenstruck:twig-service:list
Command
Use this command to list all functions/filters/services configured by this bundle and available in your twig templates.
Note
This command is only available when debug: true
.
bin/console zenstruck:twig-service:list
Available Functions/Filters
---------------------------
// As function: call with fn('{alias}', {...args}) or fn_{alias}({...args})
// As filter: use as {value}|fn('{alias}', {...args}) or {value}|fn_{alias}({...args})
---------- ---------------------------------------------
Alias Callable
---------- ---------------------------------------------
strlen strlen
generate @router->generate()
---------- ---------------------------------------------
Available Services
------------------
// Access via service('{alias}') or service_{alias}()
// If invokable, use as {value}|service('{alias}', {...args}) or {value}|service_{alias}({...args})
------- -------------------- ------------
Alias Service Invokable?
------- -------------------- ------------
foo App\SomeService yes
bar App\AnotherService no
------- -------------------- ------------
Full Default Bundle Configuration
zenstruck_twig_service: # Callables to make available with fn() twig function/filter functions: # Examples: 0: strlen # available as "strlen" alias: [Some\Class, somePublicStaticMethod] # available as "alias"