These are the slides for a workshop I’ve given at a couple conferences, explaining how Twig works to people who don’t necessarily come from a programming background.
3. It’s a templating language.
!
All templating features are
available globally to all
templates in any context,
as part of the language.
!
It’s not up to each and every
application feature to
provide its own tags.
4. It’s super powerful.
!
- Many ways to stay DRY
- Custom variables
- Functions
- Filters
- It knows math
- Whitespace control
- Extensible
16. Comment tags are like HTML
comments, except they won’t
show up in the page source.
!
{# This won’t make it to
the page source #}
!
<!-- This will -->
24. Some have a closing tag.
!
{% block content %}
<p>Hey</p>
{% endblock %}
25. Some even have nested tags.
!
{% if foo %}
<p>Something</p>
{% else %}
<p>Something else</p>
{% endif %}
26. It really all depends on
the tag.
!
The only thing they have in
common is that they all start
with “{%”, followed by the
tag name.
!
{% tagname ...
27. Twig comes with several
built-in tags.
!
{% autoescape %}
{% block %}
{% filter %}
{% do %}
{% embed %}
{% extends %}
{% autoescape %}
{% flush %}
{% for %}
{% from %}
{% if %}
{% import %}
{% include %}
{% macro %}
{% sandbox %}
{% set %}
{% spaceless %}
{% use %}
{% verbatim %}
28. {% autoescape %}
!
Escapes text for HTML.
!
{% autoescape %}
<p>Hey</p>
{% endautoescape %}
=> <p>Hey</p>
34. Twig supports five different
types of values.
!
Strings: "Hey" / 'Hey'
Numbers: 42 / 3.14
Booleans: true / false
Arrays: ['a', 'b', 'c']
Objects: { foo: 'bar' }
35. An expression is either a solo
value, or multiple values
combined to form another value.
!
"Hey" => "Hey"
"Hey "~"there" => "Hey there"
10 => 10
true => true
['a','b','c'] => ['a','b','c']
"Day "~1 => "Day 1"
10*(5+5) => 100
36. Variables are values that get
set to a name, to be
referenced later.
!
Use the {% set %} tag to
create them.
!
{% set foo = "foo" %}
{% set a = 42 %}
{% set foobar = foo~"bar" %}
37. The {% set %} tag can also be
used as a tag pair.
!
{% set foo %}
<p>foo</p>
{% endset %}
!
That’s the same as:
!
{% set foo = "n
<p>foo</p>n
" %}
38. Variables are one tool for
keeping our templates DRY.
!
{% set title = "About Us" %}
...
<title>{{ title }}</title>
...
<h1>{{ title }}</h1>
41. To pass a value through a
filter, type a pipe (“|”)
after the value, followed by
the filter name.
!
"foo"|upper => "FOO"
21.3|round => 21
['a','b','c']|length => 3
55. Some of them are global:
!
{{ dump(foo) }}
!
And they can also be nested
within objects:
!
{{ craft.isLocalized() }}
56. Twig comes with a few global
functions built-in:
attribute()
block()
constant()
cycle()
date()
dump()
include()
max()
min()
parent()
random()
range()
source()
template_from_string()
57. min() & max()
!
Returns the smallest/largest
value in a given array.
!
{{ min([1, 2, 3]) }}
=> 1
!
{{ max([1, 2, 3]) }}
=> 3
62. You can prevent certain parts
of your template from
executing unless a certain
condition is met by wrapping
it in conditional tags.
63. Conditionals always open with
an {% if %} tag, and close
with an {% endif %} tag.
!
{% if user %}
<p>Hey there handsome!</p>
{% endif %}
64. You can also specify template
code to be executed if the
condition doesn’t pass, using
the {% else %} tag.
!
{% if user %}
<p>Hey there handsome!</p>
{% else %}
<p>Have we met?</p>
{% endif %}
65. There’s also an {% elseif %} tag
if you need fallback conditions.
!
{% if user %}
<p>Hey there handsome!</p>
{% elseif username %}
<p>Is this {{ username }}?</p>
{% else %}
<p>Have we met?</p>
{% endif %}
66. Conditionals can be nested.
!
{% if user %}
{% if user.male %}
<p>Hey there handsome!</p>
{% else %}
<p>Hey pretty lady!</p>
{% endif %}
{% elseif username %}
<p>Is this {{ username }}?</p>
{% else %}
<p>Have we met?</p>
{% endif %}
67. A single condition can be
made up of multiple
expressions joined together
with “and” or “or”.
!
{% if foo and bar %}
!
{% if foo or bar %}
68. You can negate a condition by
typing “not” before it.
!
{% if not foo %}
69. You can also group
expressions together using
parentheses.
!
{% if foo and (
foo == "foo" or
foo == "bar"
) %}
71. Tests are little conditional
helpers. They don’t have to
be used within conditionals,
but usually are.
72. To write a test, add either
“is” or “is not” after a
variable, followed by the
test name.
!
{% if foo is defined %}
!
{% if foo is not empty %}
73. Twig comes with a few tests
built-in.
!
is constant
is defined
is divisible by
is empty
is even
is iterable
is null
is odd
is same as
74. is defined
!
Tests whether a variable
exists at all, without Twig
getting mad at you if
it’s not.
!
{% if foo is defined %}
75. is divisible by
!
Tests whether a number is
divisible by another.
!
{% if 5 is divisible by(2) %}
!
That’s similar to writing:
!
{% if 5 % 2 == 0 %}
76. is even & is odd
!
Tests whether a number is
even/odd.
!
{% if 5 is even %}
!
{% if 5 is odd %}
77. is empty
!
Tests whether a variable is
“empty”.
!
{% if foo is not empty %}
!
That’s the same as writing:
!
{% if foo %}
78. is same as
!
Tests whether two variables
have the same *type*.
!
{% if 5 == "5" %}
=> true
!
{% if 5 is same as "5" %}
=> false
81. Arrays contain values in a
specific order, and have an
inherent numerical index.
!
{% set arr = ['a','b','c'] %}
!
{{ arr[0] }} => 'a'
{{ arr[1] }} => 'b'
{{ arr[2] }} => 'c'
82. Objects contain key-value
pairs, and the order is
generally less important.
!
{% set obj = {
foo: "Foo",
bar: "Bar"
} %}
!
{{ obj.foo }} => "Foo"
{{ obj.bar }} => "Bar"
83. You can merge arrays together
with the ‘merge’ filter.
!
{% set a1 = ['a','b'] %}
{% set a2 = ['c','d'] %}
{% set a3 = a1|merge(a2) %}
!
=> ['a','b','c','d']
84. You can merge objects
together too.
!
{% set o1 = {foo: "Foo"} %}
{% set o2 = {bar: "Bar"} %}
{% set o3 = o1|merge(o2) %}
!
=> {foo: "Foo", bar: "Bar"}
85. You can grab part of an array
with the “slice” filter.
!
{% set a1 = ['a','b','c'] %}
{% set a2 = a1|slice(0, 2) %}
!
=> ['a','b']
!
A shortcut is also available:
!
{% set a2 = a1[0:2] %}
87. You can loop through arrays with
the {% for %} tag.
!
The syntax is:
!
{% for itemname in myarray %}
...
{% endfor %}
!
The 2nd param (“itemname”) is
whatever you want to call each
item within the array.
88. Example 1: Age field
!
<select name="age">
{% for age in [0..150] %}
<option>
{{ age }}</option>
{% endfor %}
</select>
89. Example 2: Exp. Year field
!
{% set y1 = now.year %}
{% set y2 = y1 + 10 %}
!
<select name="exp_year">
{% for year in [y1..y2] %}
<option>
{{ year }}</option>
{% endfor %}
</select>
90. Example 3: Navigation
!
{% set nav = [
{ title: "Home", uri: "" },
{ title: "About", uri: "about" }
] %}
!
<nav>
{% for item in nav %}
<a href="{{ url(item.uri) }}">
{{ item.title }}</a>
{% endfor %}
</nav>
94. Use the {% include %} tag to
include another template
wherever the tag is placed.
!
{% include "some/template" %}
95. By default, any variables
available to the “parent”
template will also be available
in the included template.
!
{% set foo = "foo" %}
{% include "myinclude" %}
!
myinclude.html:
{{ foo }}
=> foo
96. You can define additional
variables just for the included
template using the “with” param.
!
{% include "myinclude"
with { foo: "foo" }
%}
!
some/template.html:
{{ foo }}
=> foo
97. To *only* pass certain variables
to the included template, use the
“only” param.
!
{% set foo = "foo" %}
{% include "myinclude"
with { bar: "bar" } only
%}
!
some/template.html:
{% if foo is defined %}
=> false
99. A template can extend
another, overriding parts of
it (called “blocks”).
Parent Template
Block
Child Template Child Template
100. Define overridable areas in
the parent template using the
{% block %} tag.
!
<body>
{% block body %}
<p>Default content</p>
{% endblock %}
</body>
101. Use the {% extends %} tag
within your child template to
tell it which template it
extends.
!
{% extends "layout" %}
102. Override the parent’s blocks
by creating new blocks in the
child template with the same
name.
!
{% extends "layout" %}
!
{% block body %}
<p>Override content</p>
{% endblock %}
103. You can output the parent
block’s content using the
parent() function.
!
{% extends "layout" %}
!
{% block body %}
{{ parent() }}
<p>Additional content</p>
{% endblock %}
106. Twig also lets you “embed”
other templates, which is
similar to including them,
except you get to override
the child template’s blocks
in the process.
108. Use the {% embed %} tag to
embed another template.
!
{% embed "promo" %}
{% block body %}
{{ parent() }}
<span class="ribbon">
50% off!
</span>
{% endblock %}
{% endembed %}
110. Macros are like includes that
are defined right within
another template.
111. Use the {% macro %} tag to
define them.
!
{% macro errors(list) %}
{% if list|length %}
<ul class="errors">
{% for error in list %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
{% endmacro %}
112. You must import macros before
you can use them, with either
{% from %} or {% import %}.
!
{% from _self import errors %}
{{ errors(entry.allErrors) }}
!
!
{% import _self as m %}
{{ m.errors(entry.allErrors) }}
113. You can import macros from other
templates, too.
!
{% from "macros" import errors %}
{{ errors(entry.allErrors) }}
!
!
{% import "macros" as m %}
{{ m.errors(entry.allErrors) }}
!