From Twig in Drupal 8:
Twig is a template engine for PHP and it is part of the Symfony2 framework.
In Drupal 8 Twig replaces PHPTemplate as the default templating engine. One of the results of this change is that all of the theme_* functions and PHPTemplate based
*.tpl.php
files have been replaced by*.html.twig
template files.
Twig uses {{ }}
syntax to output data.
{{ 3 }}
will output the integer3
.{{ 'xyz' }}
will output the stringxyz
{{ myvar }}
will output the variablemyvar
{{ someFunction }}
will output the results ofsomeFunction()
{{ someFunction(foo, bar) }}
will out put the results ofsomeFunction(foo, bar)
Array items and object properties/methods can be accessed using a dot (.
):
{{ foo.0 }}
{{ foo.bar }}
{{ foo.method }}
{{ foo.method(baz) }}
This allows themers to not worry about variable types, and just output the data.
Array items can also be accessed using the subscript syntax ([]
):
{{ foo[0] }}
{{ foo['bar'] }}
From Twig for Template Designers:
For convenience's sake
foo.bar
does the following things on the PHP layer:
- check if
foo
is an array andbar
a valid element; if not, and iffoo
is an object, check thatbar
is a valid property;- if not, and if
foo
is an object, check thatbar
is a valid method (even ifbar
is the constructor - use__construct()
instead);- if not, and if
foo
is an object, check thatgetBar
is a valid method;- if not, and if
foo
is an object, check thatisBar
is a valid method;- if not, and if
foo
is an object, check thathasBar
is a valid method;- if not, return a
null
value.
foo['bar']
on the other hand only works with PHP arrays:
- check if
foo
is an array andbar
a valid element;- if not, return a
null
value.
If you need access a dynamic attribute:
{{ attribute(foo, 'data-foo') }}
Twig uses {% %}
syntax to execute statements.
{% set x = 123 %}
{% set name = 'Name: !name'|t('!name', list.name) %}
{% if message %}
<div class="message">{{ message }}</div>
{% endif %}
<ul>
{% for item in list %}
<li>{{ item.title }}: ${{item.price}}</li>
{% endfor %}
</ul>
Twig uses {# #}
syntax or comments.
{# Comments go inside these brackets. #}
You can also do multiline comments:
{#
This comment spans
multiple lines.
#}
A notable use for this is the twig file DocBlock. For example:
{#
/**
* @file
* Default theme implementation for a region.
*
* Available variables:
* - content: The content for this region, typically blocks.
* - attributes: Remaining HTML attributes for the element, including:
* - class: HTML classes that can be used to style contextually through CSS.
*
* @see template_preprocess_region()
*
* @ingroup themeable
*/
#}
Filters can be used to modify variables and expressions.
{{ "Some String"|t }}
Here are some common Drupal-specific filters:
trans
/t
: Runs variable through Drupalt()
function. (Note: Do not pass variables through the translation filter as this is a potential security vulnerability.)placeholder
: Escapes content to HTML and passes throughdrupal_placeholder()
, which emphasizes text (i.e.<em>foo</em>
).clean_class
: Prepares a string for use as a class name.clean_id
: Prepares a string for use as an id.format_date
: Prepares a timestamp for use as a formatted date.raw
: Marks value as being safe which means no escaping will take place. This should be avoided if possible.render
: Wrapper for therender()
function.safe_join
: Joins several strings together with a specified separator (e.g.{{ foo|safe_join(':') }}
)without
: Duplicates an array, excluding specified keys (e.g.{{ foo|without('bar', 'baz') }}
)
From Drupal.org - Added support for the Twig {% trans %} tag extension:
The Twig {% trans %} block will translate the text using tokens with t() or format_plural() if the {% plural ... %} switch has been declared in the tag:
<p class="submitted">
{% trans %}
Submitted by {{ author.name }} on {{ node.date }}
{% endtrans %}
</p>
With the {% plural ... %}
switch:
{% set count = comments|length %}
{% trans %}
{{ count }} comment was deleted successfully.
{% plural count %}
{{ count }} comments were deleted successfully.
{% endtrans %}
If filtering the tokens inside the {% trans %} block does not work, create a token outside of the block to minimize operations inside.
{% set date = node.created|format_date('medium') %}
{% trans %}
Node was created on {{ date }}.
{% endtrans %}
From Twig's official macro documentation:
Macros are comparable with functions in regular programming languages. They are useful to put often used HTML idioms into reusable elements to not repeat yourself.
Here is a small example of a macro that renders a form element:
{% macro input(name, value, type, size) %}
<input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
{% endmacro %}
Macros differ from native PHP functions in a few ways:
- Default argument values are defined by using the default filter in the macro body;
- Arguments of a macro are always optional.
- If extra positional arguments are passed to a macro, they end up in the special
varargs
variable as a list of values. But as with PHP functions, macros don't have access to the current template variables.
- drupal.org: Twig in Drupal 8
- drupal.org: Twig Coding Standards
- drupal.org: Filters - Modifying Variables In Twig Templates
- weebpal.com: Drupal 8 Theming Essential Guide
- sqndr.github.io: Twig Debug
- twig.sensiolabs.org: macro