Skip to content
bryanveloso edited this page Sep 12, 2010 · 25 revisions

Twig is the Chyrp templating engine. It is authored by Armin Ronacher, who was generous enough to jump on the chance to build us a templating engine. The syntax in general is “similar to the Genshi text templates which in turn were inspired by Django which also inspired Jinja (all three of them python template engines) which inspired the Twig runtime environment.”

Twig’s Purpose

A language independent and simple template engine is useful for applications that use code which is written in more than one programming language. Good Examples are portal systems which use a blog written in Ruby, a forum software written in PHP and a planet system written in Python.

While it was written for Chyrp exclusively, you should fairly easily be able to use it in any other system you want to use it in. Currently there is only one implementation, and that is in PHP. If you want to port it to another language, a spec sheet can be found in /includes/class/Twig/spec.html.

Terminology

  • {% (this is a block) %}
  • ${ (this is an expression) }
  • $this_is_a_variable
  • ${ this_is_also_a_variable }
  • ${ variable | this_is_a_filter("and", "these are", arguments) }
  • $variable.these.are.attributes
  • this == is + an ~ "expression"
  • {# this is a comment, and is removed when the template is built #}

Syntax

Here’s a basic overview of the syntax used by Twig for performing various functions.

<!DOCTYPE HTML>
{# This is a comment #}
<title>{% block title %}Page Title Goes Here{% endblock %}</title>
{% if show_navigation %}
<nav>
  <ul>
  {% for item in navigation %}
    <li><a href="${ item.href | escape }">$item.caption</a></li>
  {% endfor %}
  </ul>
</nav>
{% endif %}
<article>
{% block body %}
{% for article in articles %}
$article.title
{% else %}
There aren't any articles!
{% endfor %}
{% endblock %}
</article>

Variables and Attributes

To simply output the value of a variable using Twig, you use $foo. Use a . to access attributes of that variable or call a function of that name, e.g. $foo.bar.baz. Be careful when using a variable at the end of a sentence where a “.” would occur. In that case, you may want to wrap it in the filtering syntax, a-lá “this is an ${ example }.”.

A good example of the flexibility of the magical . is when checking group permissions: {% if visitor.group.can("do_something") %}.

Filters

Filters are used to manipulate a value and return the result. The most basic form of an expression in Twig is by “piping” the data to a “filter”. For example, ${ post.title | lower | truncate(40) } would return the title of the post, converted to lowercase, and truncated to 40 characters.

Default Filters

Name Description
date Format the timestamp using the PHP date formatting rules.
strftime Format the timestamp using standard strftime rules.
numberformat Apply number formatting on the string. This may or may not use local specific rules.
moneyformat Like numberformat but for money.
filesizeformat Takes a number of bytes and displays it as KB/MB/GB.
format Applies sprintf formatting on the string.
even Is the number even?
odd Is the number odd?
escape or e Escape HTML in the string.
urlencode URL encode the string. If the second parameter is true this function will encode for path sections, otherwise for query strings.
quotes Escape quotes (\’, \", etc.)
title Make the string lowercase, then upper case the first characters of all words.
capitalize Like title, but capitalizes only the first character of the whole string.
upper Convert the string to uppercase.
lower Convert the string to lowercase.
strip Trim leading and trailing whitespace.
lstrip Trim leading whitespace.
rstrip Trim trailing whitespace.
translate Translate the string using either the “theme” domain or the “chyrp” domain if in Admin.
translate_plural Translate the (singular) string, or the plural string if the number passed is not 1.
normalize Convert all excessive whitespace (including linebreaks) into a single space.
truncate Truncate a string, providing ellipsis, if it is longer than the passed length. Keeps words in tact by default, but with a second boolean parameter will be strict.
replace Replaces the occurrence of the first argument with the second argument in the string. If the third argument is true, it will use regular expressions.
linebreaks Convert linebreaks to <br />’s.
camelize Convert string to camelcase.
strip_tags Strip HTML from the string.
pluralize Return the pluralization of a string, or if a number is passed and it is 1, don’t pluralize.
sanitize Remove special characters from a string.
join Concatenate the array items and join them with the string provided (or commas by default).
split Split a string into an array at the given breakpoints.
first First entry of an Array.
offset Entry at Array[offset].
last Last entry of an Array.
reverse Reverse the Array items.
count Count the number of items in an array or string characters.
length Alias for count.
default If the value is none the first argument is returned
keys Keys of an Array.
items Items of an Array.
inspect Dumps the variable or value.
fallback If the value is empty or none, return this value.
selected If the first argument is the same as the value, output class="selected", or selected if the second argument is true.
option_selected Same as selected, but for selected="selected".
checked Same as selected, but for checked="checked".

If an unknown filter is used, it will fall back to using Trigger->filter() on the value. This makes it extremely easy for Modules to provide custom filters – they simply have to provide a filter function callback.

When filters are called, they pass the result of the preceding expression as the first argument, and any arguments passed to the filter itself (${ example | like("this") }) after it. A complex example:

${ 42 | foo(1, 2) | bar | baz }
    =>  baz(bar(foo(42, 1, 2)))

Formatting Blocks

Blocks define a block of content that can ultimately be extended by another twig file, or display its own content if it is not extended. Blocks are defined like so:

{% block myblock %} 
Here's some default content!
{% endblock %}

Extending Templates

In Twig, there is a basic hierarchy system in place that uses {% block foo %} to “define” separate parts of your layout. You can then “extend” the originating template using the {% extends "foo.twig" %} construct. Using it will load the foo.twig template, and overwrite its {% block %}s with anything you define afterwards. For example:

{% extends "layouts/whatever.twig" %}
{% block content %}
This is the content!
{% endblock %}

When overriding a block, you can use {% super %} to output the original @block@’s content.

Including Files

You may want to split your theme into multiple files. To “drop in” a Twig file, use {% include "path/to/file.twig" %}.

if Conditions

An if statement checks if something evaluates to true. If it is, the contents of the block up to the (mandatory) {% endif %} is processed. {% elseif foo %} is also available for further expressions. For example:

{% if condition %}
If @condition@ evaluates to @true@, you'll see me!
{% elseif condition2 %}
If @condition1@ is evaluates to @false@, but @condition2@ evaluates to @true@, you'll see me!
{% else %}
If neither are @true@, I'll show up and be all mopey about it.
{% endif %}

Expressions

Expressions can be used in {% blocks %} and ${ expressions }.

Operator Description
== Does the left expression equal the right expression?
+ Convert both arguments into a number and add them.
- Convert both arguments into a number and substract them.
* Convert both arguments into a number and multiply them.
/ Convert both arguments into a number and divide them.
% Convert both arguments into a number and calculate the rest of the integer division.
~ Convert both arguments into a string and concatenate them.
or True if the left or the right expression is true.
and True if the left and the right expression is true.
not Negate the expression.

For more complex operations, it may be best to wrap individual expressions in parentheses to avoid confusion:

{% if (foo and bar) or (fizz and (foo + bar == 3)) %}

for Loops

for loops are used to traverse arrays. {% else %} may be used if the array is empty. The syntax is very simple:

{% for page in pages %}
Page #$page.id
{% else %}
There aren't any pages!
{% endfor %}

For iterating over keys and values of an associative array, use the syntax {% for key, val in arr | items %} (note the items filter). This is the equivalent of foreach ($arr as $key => $val): in PHP.

Using loops provides a “loop” variable that is available to anything within the for. Its values are as follows:

Variable Description
loop.first Is this the first item in the loop?
loop.last Convert both arguments into a number and add them.
loop.index Offset of the current loop from the beginning, starting at 1.
loop.index0 Offset of the current loop from the beginning, starting at 0.
loop.revindex Offset of the current loop from the end, ending at 1.
loop.revindex0 Offset of the current iteration from the end, ending at 0.
loop.parent If the loop is nested within another loop, the loop “above” this one.

Comments

To make a comment in your template file, simply surround it with {# these #} and it will be ignored by the lexer.

Variable Origin

Variables are passed as a “context” array upon the loading of the template file. [todo: list common/global context variables]

Paths

The paths used in {% include %}, {% extends %}, etc., relative to the directory that the Twig lexer was initiated to read from (for themes, /themes/yourtheme).