Twig Functions

Objectives
  • Describe the difference between filters and functions.
  • Use functions in Twig templates.
  • List three often-used Twig functions.
  • Look up official documentation on functions.
  • Describe how a content management system offers frontend flexibility through modular templates.
Prerequisites
  • Working with {{ }} and {% %} tags.
  • Working with loops.
  • Basic programming concepts (variables, operators, control structures)
Last revision:

Overview

Twig functions behave like PHP functions: they have a name and can take one or more optional or required arguments. They typically return a value but don't have to.

You can extend Twig by creating functions in PHP and exposing those as Twig functions.

Example

The random() function returns a random number, random array element, or random character from a string.

{% set colours = [ 'red', 'green', 'blue' ] %}
{% set number = random() %}
Random colour: {{ random(colours) }}
Random number: {{ number }}


Possible output:

Random colour: green
Random number: 298553500


Built-in functions

Often-used built-in functions include:

Filters vs Functions

You may wonder about the difference between filters and functions, since both behave in a similar way.

Filters

  • can take one or more optional or required arguments
  • are always separated by a pipe sign from the variable they act upon
  • modify the variable they act upon and return the modified value
  • are typically, but not always, used when generating output with {{ }}

Functions

  • can take one or more optional or required arguments
  • typically return a value, but don't have to
  • are typically, but not always, used in {%%} code blocks

Examples

Using min() and max()

Given a sequence of numbers, print the smallest number, the greatest number, and the total number of items.

Twig template:

{% set items = [ 0, 1, 2, 4, 8, 3 ] %}

{# Populate some variables and then print them. #}

{% set smallest = min(items) %}
{% set greatest = max(items) %}
{% set total = items | length %}

Smallest item: {{ smallest }}
Greatest item: {{ greatest }}
Total items: {{ total }}


Output

Smallest item: 0
Greatest item: 8
Total items: 6

 

Alternative solution without creating intermediary variables:


Twig template:

{% set items = [ 0, 1, 2, 4, 8, 3 ] %}

{# Of course you can also print the return values directly. #}

Smallest item: {{ min(items) }}
Greatest item: {{ max(items) }}
Total items: {{ items | length }}


Output:

Smallest item: 0
Greatest item: 8
Total items: 6

Using range()

Loop through a list returned by a function.

Twig template:

{% for number in range(0, 5) %}
 {{ number }}
{% endfor %}


Output:

 0
 1
 2
 3
 4
 5

The range() function returns a sequential list of numbers. In this example it takes two arguments: the starting number and the ending number, resulting in the sequence [ 0, 1, 2, 3, 4, 5 ].

Looping through the returned sequence we print each number.

Using return values in functions / filters

Given a

Twig template:

{% set items = [ 0, 1, 2, 4, 5, 3 ] %}

List 1:
{% for number in range(min(items), max(items)) %}
 {{ number }}
{% endfor %}

List 2:
{% for number in range(items | first, items | last %}
 {{ number }}
{% endfor %}


Output:

List 1:
 0
 1
 2
 3
 4
 5
List 2:
 0
 1
 2
 3

List 1: 
Given a sequence of numbers, take the smallest and greatest number. Use those to create a range. Loop through that range and print each number in the range.

List 2:
Given a sequence of numbers, take the first and last number. Use those to create a range. Loop through that range and print each number in the range.

Using cycle()

The cycle() function keeps looping through a given sequence, and returns the element at the given position. If the given position is greater than the number of items in the sequence, the function repeats the cycle and keeps going.

Example

We want to print a list of vehicles. Each vehicle should be surrounded by <div> tags, and each div should get the CSS class dark or light to get a nice zebra-striped effect.

In other words the first item should get the dark class, the second item the light class, the third item the dark class again, and so on.

{% set classes = [ 'dark', 'light' ] %}

{% set vehicles = [ 'car', 'boat', 'bicycle', 'tractor' ] %}

{% for vehicle in vehicles %}
 {% set class = cycle(classes, loop.index0) %}
 <div class="{{ class }}">{{ vehicle }}</div>
{% endfor %}


Output:

   <div class="dark">car</div>
   <div class="light">boat</div>
   <div class="dark">bicycle</div>
   <div class="light">tractor</div>


During 1st loop, cycle(classes, loop.index0) returns element at position 0: dark.
During 2nd loop, cycle(classes, loop.index0) returns element at position 1: light.
During 3rd loop, cycle(classes, loop.index0) returns element at position 2: dark again (end of classes sequence reached; restarted at 0.
And so on.

Related reading: Alternating class names in Drupal views (TrainingCloud Blog).

Using include()

The include() function lets you embed rendered output of one template into another template. All variables from the main template are available in the included template as well.

Example

Main template:

{% 
 set cars =  [
   { 'id': 123, 'make': 'BMW', 'model': 'X3', 'year': 2015 }, 
   { 'id': 764, 'make': 'Nissan', 'model': 'Terrano', 'year': 2011 },
   { 'id': 9624, 'make': 'Volkswagen', 'model': 'Touareg', 'year': 2009 },
   { 'id': 188, 'make': 'Tata', 'model': 'Safari', 'year': 2022 }
 ]
%}

{%- for car in cars %}
  {%- include 'car.html.twig' %}
{% endfor %}

 

car.html.twig:

<div class="car">
 <div>Inventory ID: {{ car.id}}</div>
 <div>Make: {{ car.make }}</div>
 <div>Model: {{ car.model }}</div>
 <div>Year: {{ car.year}} </div>
</div>


Output:

<div class="car">
 <div>Inventory ID: 123</div>
 <div>Make: BMW</div>
 <div>Model: X3</div>
 <div>Year: 2015 </div>
</div>

<div class="car">
 <div>Inventory ID: 764</div>
 <div>Make: Nissan</div>
 <div>Model: Terrano</div>
 <div>Year: 2011 </div>
</div>

<div class="car">
 <div>Inventory ID: 9624</div>
 <div>Make: Volkswagen</div>
 <div>Model: Touareg</div>
 <div>Year: 2009 </div>
</div>

<div class="car">
 <div>Inventory ID: 188</div>
 <div>Make: Tata</div>
 <div>Model: Safari</div>
 <div>Year: 2022 </div>
</div>

Content management systems like Drupal rely on this mechanism to let frontend developers write templates for components like blocks, pages, forms, menus, quotes, cards, listings, and much more. Each component is styled according to a Twig template, whether it's a generic template per type or component, or a specific template for one specific component.

If you want to learn more, have a look at the Twig documentation on includes.

Activity 1

Look up and describe the difference between the date filter and the date function.

Activity 2

In the cycle light/dark example, how would you modify the code so the first class to use is light instead of dark? Provide 2 different solutions.

Answer / solution
  • Change the order of the items in the classes array: start with light instead of dark.
  • Use the index.loop variable (starts at 1) instead of the index.loop0 variable (starts at 0)

Summary

  • Twig functions behave like PHP functions.
  • Twig functions can take arguments, but don't have to.
  • Twig functions can return a value, but don't have to.
  • Twig functions and filters behave in a similar way.
  • You can extend Twig with your own custom functions written in PHP.
  • You can embed Twig templates inside other Twig templates.