Twig Reference
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.”
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
.
{% (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 #}
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>
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 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.
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)))
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 %}
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.
You may want to split your theme into multiple files. To “drop in” a Twig file, use {% include "path/to/file.twig" %}
.
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 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 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. |
To make a comment in your template file, simply surround it with {# these #}
and it will be ignored by the lexer.
Variables are passed as a “context” array upon the loading of the template file. [todo: list common/global context variables]
The paths used in {% include %}
, {% extends %}
, etc., relative to the directory that the Twig lexer was initiated to read from (for themes, /themes/yourtheme
).