Twig Lambda
Lambda expressions for Twig and filters that make use of them, (*1)
, (*2)
Quick examples
Listing names of all authors ordered by age:, (*3)
{% for author in articles|map(=> _.author)|unique_by('===')|sort_by(=> _.age) %}
* {{ author.name }}, {{ author.age }}
{% endfor %}
Counting elements starting from specified letter:, (*4)
{% for key, count in ['foo', 'bar', 'foobar']|countBy(=> _|first|capitalize) %}
* {{ count }} elements start from {{ key }}.
{% endfor %}
, (*5)
Installation
Install via Composer:, (*6)
composer require dpolac/twig-lambda
Add the extension to Twig:, (*7)
$twig->addExtension(new \DPolac\TwigLambda\LambdaExtension());
... or if you use Symfony, add the following to your services.yml config file:, (*8)
services:
# ...
dpolac.twig_lambda.extension:
class: DPolac\TwigLambda\LambdaExtension
tags: [ { name: twig.extension } ]
Usage
, (*9)
Lambda expression
To create lambda expression prepend any valid Twig expression
with => operator. Inside of the lambda expression you can use
any variable from the outside. There are also two special
variables available:
* _ (single underscore) - first argument,
* __ (double underscore) - array of arguments counted
from zero., (*10)
=> _.name
=> _ * 2
=> _|first
=> 'foobar'
=> _ is even
=> __[0] + __[1]
To create lambda expression with list of arguments, add it
before => operator. Separate multiple arguments with
semicolons. You can use brackets for readability., (*11)
x => x + 1
(book) => book.author
arg1; arg2 => arg1 ~ arg2
(a; b; c) => a + b - c
Note that if you use list of arguments, _ variable is not
longer available., (*12)
Below is a list of available filters and tests. All works
with arrays and any Traversable object and preserve it keys.
All lambdas are called with two arguments: element and key., (*13)
, (*14)
|map
Alias: |select
Signature: array|map(lambda), (*15)
Applies a given function to each element and returns
array of results in the same order., (*16)
{% for i in [1, 2, 3, 4]|map(=> _ * 2) %}
{{ i }} {# prints '2 4 6 8' #}
{% endfor %}
, (*17)
|filter
Alias: |where
Signature: array|filter(lambda), (*18)
Returns array of elements that passes a test specified by lambda., (*19)
{% for i in [1, 2, 3, 4, 5, 6]|filter(=> _ is even) %}
{{ i }} {# prints '2 4 6' #}
{% endfor %}
, (*20)
|unique_by
Signature: array|unique_by(lambda|'==='|'=='), (*21)
Returns array of unique elements. Uniqueness is checked with
passed lambda. PHP operators == or === will be used if
string '==' or '===' is passed instead of lambda., (*22)
Lambda should have two arguments - items to check. Keys of
elements are also passed as third and fourth argument., (*23)
{% for i in [1, 2, 2, 3, 1]|unique_by((i1;i2) => i1 == i2) %}
{{ i }} {# prints '1 2 3' #}
{% endfor %}
equivalent, (*24)
{% for i in [1, 2, 2, 3, 1]|unique_by('==') %}
{{ i }} {# prints '1 2 3' #}
{% endfor %}
, (*25)
|group_by
Signature: array|group_by(lambda), (*26)
Sorts an array into groups by the result of lambda., (*27)
{% for key, group in ['foo', 'bar', 'foobar', 'barbar']|group_by(=> _|first|capitalize) %}
= {{ key }}
{% for i in group %}
* {{ i }}
{% endfor %}
{% endfor %}
will produce, (*28)
= F
* foo
* foobar
= B
* bar
* barbar
, (*29)
|sort_by
Signature: array|sort_by(lambda[, direction = 'ASC']), (*30)
Sorts array by values returned by lambda.
Direction can be 'ASC' or 'DESC'., (*31)
{% for i in ['bar', 'fo', 'foobar', 'foob']|sort_by(=> _|length, 'DESC') %}
{{ i }} {# prints 'foobar foob bar fo' #}
{% endfor %}
, (*32)
|count_by
Signature: array|count_by(lambda), (*33)
Sorts an array into groups and returns a count for the number of
objects in each group., (*34)
If lambda returns true, false or null, it will be converted to
string 'true', 'false' or 'null'. Float will be converted to
integer., (*35)
{% for key, count in ['foo', 'bar', 'foobar']|count_by(=> _|first|capitalize) %}
* {{ count }} elements start from {{ key }}.
{% endfor %}
will produce, (*36)
* 2 elements start from F
* 1 elements start from B
, (*37)
is any
Signature: array is any(lambda), (*38)
Returns true if lambda returns true for any element from
an array., (*39)
Returns false if array is empty., (*40)
{{ [1, 2, 3] is any(=> _ is even) ? "There is even element in the array." }}
{# prints 'There is even element in the array.' #}
, (*41)
is every
Signature: array is every(lambda), (*42)
Returns true if lambda returns true for every element from
an array., (*43)
Returns true if array is empty., (*44)
{{ [1, 2, 3] is every(=> _ > 0) ? "All elements in the array are positive." }}
{# prints 'All elements in the array are positive.' #}
, (*45)
call()
Signature: call(lambda [, arguments:array]), (*46)
Calls lambda and returns its result. You can provide array
of arguments., (*47)
This function is provided to allow creating twig macros taking
lambda as an argument., (*48)
{{ call(=> _ * 2, [10]) }}
{# prints '20' #}
{{ call(=> _.foo, [{foo: 12}]) }}
{# prints '12' #}