A func
-y little Craft CMS extension to enable anonymous function definition in Twig.
A (somewhat reluctant) Top Shelf Craft creation
Michael Rog, Proprietor
Twig famously prohibits defining functions in templates and only parses arrow syntax in the context of filter parameters. Funky provides a workaround for this limitation, allowing you to create ad-hoc functions in your templates, using a special syntax.
Install the package via Composer.
composer require topshelfcraft/funky
The extension is bootstrapped automatically.
Once installed, Funky enables a special syntax for defining functions in your Twig templates: funky|fn()
You can create a function inline, by passing an arrow function as a solo argument:
funky|fn(x => x*2)
You can also register a function to access later, by passing both a name and the arrow function as arguments:
{% do funky|fn('double', x => x*2) %}
{% do funky|fn('triple', x => x*3) %}
{{ fns.double(42) }}
{{ fns.triple(42) }}
Well, it's a hack. If you're using this, it might be a code smell. Twig has resisted this functionality for good reason: Templates should only be concerned about presentation; ideally they should not contain logic.
Of course, once you understand the rules, you can break the rules...
Used thoughtfully, there are some circumstances in which the ability to define ad-hoc functions might actually help DRY up your template code:
- Your custom functions are not reused across multiple templates, so it doesn't make sense to define them in a custom module.
- You need to pass a custom function into a Collection pipeline method.
- You're using Twig's
filter
,map
, orreduce
filters, and you want to reuse the same arrow function for multiple invocations in the same template.
So, proceed with temperance... or, reckless abandon; Who am I to tell you what to do?
Twig parses arrow function syntax in the context of filter parameters. So, Funky defines a fn
filter, which either:
- returns the Closure directly (if the first given argument is callable).
- registers the function as a virtual property of the Funky class instance, making it available via the
fns
global (if the first given argument is a function name).
Craft 4.0+ and PHP 8.0.2+
For heaven's sake, really?!
Yes, I double-checked... It's a bug.
Very well. Please open a GitHub Issue. If you're feeling ambitious, submit a PR to the 4.x.dev
branch.
- Extension development: Michael Rog / @michaelrog