In the first part of this blog post we introduced exciting new Twig features like inline comments, PHP enums support, improved operator precedence, the guard tag, and enhanced deprecation handling. This second part highlights other nice recent additions to Twig.

Dot Operator Improvements

Fabien Potencier
Contributed by Fabien Potencier in #4310

The attribute() function allows accessing attributes or properties of variables or objects where the name of the attribute/property is dynamic:

1
2
3
4
5
6
7
{# the dot notation can be used because the property name ('fullName') is known and static #}
{{ user.fullName }}

{# attribute() is needed because the name of the property is stored in a variable #}
{% for property in ['fullName', 'email', 'phoneNumber'] %}
    {{ attribute(user, property) }} <br>
{% endfor %}

In Twig 3.15, the attribute() function is deprecated, and the dot operator has been extended to handle dynamic properties:

1
2
3
4
{# wrap dynamic properties with parentheses #}
{% for property in ['fullName', 'email', 'phoneNumber'] %}
    {{ user.(property) }} <br>
{% endfor %}

Although the attribute() is deprecated, it will remain available in Twig 4.0 to ensure a smoother upgrade path.

Nicolas Grekas
Contributed by Nicolas Grekas in #4353

Another enhancement to the dot operator is the ability to access class constants directly from an object:

1
2
3
4
5
6
{# previously, you needed to pass the fully qualified class name #}
{{ constant('App\\Some\\Namespace\\Of\\Some\\Class::CONSTANT_NAME') }}

{# now, you can also use any object of the class containing the constants #}
{# SHIPPING_TYPE_EXPEDITED is the name of a constant in the Order class #}
{{ order.SHIPPING_TYPE_EXPEDITED }}

Named Arguments Improvements

Fabien Potencier
Contributed by Fabien Potencier in #4391

Twig macros are similar to functions in programming languages and they are useful to reuse template fragments. Starting from Twig 3.15, you can use named arguments when calling a macro, with the syntax argument: value, just like in PHP:

1
{{ forms.field(type: 'text', name: 'user[name]') }}

Named arguments are also supported when passing arguments with the dot operator:

1
2
3
4
5
{{ user.fullName(maxLength: 32) }}

{% for property in ['fullName', 'email', 'phoneNumber'] %}
    {{ user.(property)(escape: true, maxLength: 32) }} <br>
{% endfor %}

With these changes, named arguments are now supported everywhere: functions, filters, tests, macros, and dot operator arguments.

Free-Form PHP Callable Argument Names

Fabien Potencier
Contributed by Fabien Potencier in #4318

Previously, Twig required snake_case argument names when calling PHP callables, regardless of their original signature. In Twig 3.15, you can use either snake_case or camelCase, no matter which format is used by the PHP signature:

1
2
3
{# both syntaxes yield the same result #}
{{ order.summary(include_total: true) }}
{{ order.summary(includeTotal: true) }}

Argument Unpacking

Fabien Potencier
Contributed by Fabien Potencier in #4300

The ... spread operator can now expand arguments when calling a function:

1
2
{% set attr = [{type: 'submit'}, {class: 'btn btn-primary'}, {'data-tracking-id', '12345'}] %}
{{ html_attributes(...attr) }}

Arrow Functions in All Twig Callables

Fabien Potencier
Contributed by Fabien Potencier in #4378

Arrow functions, a favorite of many developers, are now supported everywhere in Twig. Previously supported in filters and functions, they can now also be used in tests, macro arguments, and method call arguments:

1
2
3
4
5
6
7
{% set people = [
    {first: "Bob", last: "Smith"},
    {first: "Alice", last: "Dupond"},
] %}

{# passing an arrow function to a macro #}
{{ _self.display_people_names(people, (person) => person.first) }}

Arrow functions can now also be stored in Twig variables:

1
2
3
4
{# defining the arrow function and storing it in a variable #}
{% set first_name_fn = (p) => p.first %}

{{ _self.display_people_names(people, first_name_fn) }}
Published in #Living on the edge