Template Syntax

The official Twig documentation has a great guide on getting started with the language.

You can also play around with twig templates live here on the Twig Playground. More details on this here.

But here's a quick overview:

Variables

{{ something }}
{{ product.name }}

If Statements 

{% if product.is_in_stock %} ... {% endif %}

 Loops 

Loop some items
{% for item in items %}
    <li>{{ item.title }}</li>
{% endfor %}

 Filters 

Put the product name in "Title Case"
{{ product.name | title }}

Or change the formating of a date
{{ blog.date_added | date("m/d/Y") }}

 

Custom to REC


Filters


Repeat - repeats string a given times:

{{ "." | repeat(5) }} -> .....
{{ "hey" | repeat(2) }} -> heyhey

  

Safe email - converts an email address into ASCII html characters in order to make it more difficult for bots to crawl it. 

{{ "bob@email.com" | safe_email }} 

Displays to the user as: bob@email.com
but in source as: &#98;&#111;&#98;&#64;&#101;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;


You could even use thie with a system email such as:

{{ company.email | safe_email }}

     

Darken colour - take a hex colour and darken it

border-color: {{ theme.colour.borders | darkenColour(10) }};

 

Lighten colour - take a hex colour and lighten it

border-color: {{ theme.colour.borders | lightenColour(10) }};

 

Short link - generate a short link from given url, depending on site setting this will either be for tinyurl or bit.ly or none.

{{ "http://www.bbc.co.uk/" | short_link }}
{{ setup.twitter_url | short_link }}

 

HTML to Text - Strip any html from a html string

{{ product.desc | html2txt }}

 

Unescape - Decode html encoded string

{{ some_tag | unescape }}

ucfirst - uppercase the first letter (First letter only)

{{ some_tag | ucfirst }}

ucwords - uppercase the first letter of each word (Title Case Style)

{{ some_tag | ucwords }}


Truncate - Cut text or html to a specific length

# truncate, cut to an approx length, makes sure it doesn't cut words and ends html tags properly for you.
{{ company.name | truncate }}  # default to cutting to 100 characters
{{ company.name | truncate(50) }} # cut at about 50 characters
{{ company.name | truncate(50, ' , read more...') }}  # change default ending text from '...'

# truncate_exact, cut to an exact length, regardless of words or html!
{{ company.name | truncate_exact }}

# truncate_text, cut to an approx length, regardless of html but makes sure it doesn't cut words.
{{ company.name | truncate_text }}

# truncate_html, same as "truncate" above
{{ company.name | truncate_html }}

   

date_ago - Pipe a date to this to print how long ago it was, e.g. "1 day ago", "3 weeks ago" etc.

<p>Created: {{ object.created_at | date_ago }}</p>


google_map - Embed a Google Maps map for a given place:

<div class="iframe-container iframe-container-4-1 push-out">
{{ "address here" | google_map }}
</div>


money - Format an number as a monetary value (obeys the site setting for decimals and thousands commas)

{{ '12345' | money }}    ->    '12,345.00'
{{ '12345.6' | money }} -> '12,345.60'


youtube - Turn a link to a youtube video into an iframe (custom height and width optional)

{{ 'https://www.youtube.com/embed/z9Uz1icjwrM' | youtube }}    ->    "<iframe width="560" height="315" src="//www.youtube-nocookie.com/embed/z9Uz1icjwrM" frameborder="0" allowfullscreen></iframe>"

{{ 'https://www.youtube.com/embed/z9Uz1icjwrM' }} | youtube(1280, 1024) -> "<iframe width="1280" height="1024" src="//www.youtube-nocookie.com/embed/z9Uz1icjwrM" frameborder="0" allowfullscreen></iframe>"


preg_replace - Replace parts of a string using a regular expression (due to how twig passes the variables, you'll need to use double slashes for escaped characters)

{{ "something.pdf" | preg_replace('/\\.\\w+$/', '') }}    ->    'something'


preg_replace - Replace parts of a string using a regular expression (due to how twig passes the variables, you'll need to use double slashes for escaped characters)

{{ "something.pdf" | preg_replace('/\\.\\w+$/', '') }}    ->    'something'


encryptID - Encrypt an ID for a link such as to an order page from email tasks.

{{ order.id | encryptID }}


Array filters


Map formatting - take an array of strings or objects and format into another array of formatted strings

When used with join this can be used to avoid a for loop when dealing with simple repeated data

 

# e.g. product options
{{ item.options | map_format("%group: %desc") | join(", ") }}

# simple array
{{ [1,2,3] | map_format("[%s]") | join(",") }}

# objects inside an array, using key
{{ [{ name: "Bob" }, { name: "Jim" }] | map_format("%name") | join(", ") }}

 

Group by - Group multi arrays into key = value arrays where value is an array matching the key

{% set max = entries | group_by('value') | sub_count | max %}


Count - number of items in an array

{% set total = entries | count %}


Sub count - count, but within a multi/grouped array and returns an array of those counts

{% set max = entries | group_by('value') | sub_count | max %}


Sum - total value of values in an array (or sub array if key given to find in sub array)

{{ [1,4,3] | sum }}    ->    8


Avg - acts on arrays or sub arrays like sum, but returns the average value rather than the total

{{ object.userData.entries.rating | avg('value') | round }}


Min - find minimum value in array

{{ [4,3,6] | min }}    ->    3


Max - find maximum value in array

{{ [4,3,6] | max }}    ->    6


Where - filter array to only matching a given value

{{ [1, 2, 3, 3, 4] | where(3) }}    ->    [3, 3]
{{ [{a: 1, b: 2}, {a: 3, b: 4}] | where('a', 3) }} -> [{a: 3, b: 4}]


Where not - filter array to only where not matching a given value

{{ [1, 2, 3, 3, 4] | whereNot(3) }}    ->    [1, 2, 4]
{{ [{a: 1, b: 2}, {a: 3, b: 4}] | whereNot('a', 3) }} -> [{a: 1, b: 2}]


Where in - filter array to where it's value is in another array

{{ [1, 2, 3, 4, 5, 6] | whereIn([5, 6]) }}    ->    [5, 6]
// Need to document key usage


Where not in - filter array to where it's value is not in another array

{{ [1, 2, 3, 4, 5, 6] | whereNotIn([5, 6]) }}    ->    [1, 2, 3, 4]
// Need to document key usage


Where contains - Return items where a key contains a specific value (works if the key value is an array or a string)

{{ [{a: [1, 2, 3], b: 4}, { a: [5, 6], b: 7}] | whereContains('a', 2) }}    ->    [{a: [1, 2, 3], b: 4}]

{{ [{a: ['Featured', 'Special'], b: 'Keyboard'}, {a: 'Special', b: 'Mouse'}] | whereContains('a', 'Special') }} -> [{a: ['Featured', 'Special'], b: 'Keyboard'}, {a: 'Special', b: 'Mouse'}]


Get - quickly retried a value from an array

{{ [6, 3, 8, 2, 6] | get(3) }}    ->    2 (Array keys start at 0)

JSON - Turn an array into a JSON string

{{ [{a: 1, b: 2}, {c: 3, d: 4}] | json }}    ->    "[{"a":1,"b":2},{"c":3,"d":4}]"


Chunk - Split an array into smaller chunks

{{ [1, 2, 3, 4, 5, 6] | chunk(3) }}    ->    [[1, 2, 3], [4, 5, 6]]


Random - Select a random item from an array (can pass a number to specify the amount of random items

{{ [1, 2, 3, 4, 5, 6] | random }}    ->    5
{{ [1, 2, 3, 4, 5, 6] | random(2) }} -> [3, 1]


Key by - Restructure an array as a multidimensional array by setting the key as a field value

{{ [{a: 'Boop'}, {a: 'Beep'}] | key_by('a') }}    ->   {'Boop': {a: 'Boop'}, 'Beep': {a: 'Beep'}}


Sort by - Sort an array based on a key value

{{ [{a: 1, b: 3}, {a: 4, b: 2}] | sort_by('b') }}    ->    [{a: 4, b: 2}, {a: 1, b: 3}]

// Pass in a function to split full name on space characters and sort by the surname
{{ [{full_name: 'Andrew Stilliard'}, {full_name: 'James McKinnon'}] | sort_by(x => x.full_name | split(' ')[1]) }} -> [{full_name: 'James McKinnon'}, {full_name: 'Andrew Stilliard'}]


Pluck - Create a new array with just the requested key values

{{ [{a: 1, b: 2}, {a: 3, b: 4}] | pluck('a') }}    ->    [1, 3]


Functions 

API

We have a custom function used to access the API: api() E.g. Loop the latest 10 featured products

a HTTP request to the api would normally look like:

/api/v1/products.json?status=featured&limit=10&api_key=xxxxxxxx

But in our twig function, you simply pass the resource your looking for, in this case "products", and each additional param for filtering as a json object. Also the api_key key is not needed as this request happeneds internally.  

{% set products = api('products', { fields: '*', limit: 50 }) %}
<ul>
    {% for product in products %}
    <li>
        <strong>{{ product.name }}</strong>
    </li>
    {% else %}
    <li>
        <em>No featured products found</em>
    </li>
    {% endfor %}
</ul>

  The apifunction can only access public data from the api, so no orders or customer data, but why would you want to show that anyway? ;)

We have full docs on using the api here.

You can also us our API explorer to find whats available, via the admin side of your site.


Example to get 8 gallery images from the Summer album:

{% set images = api('gallery', { limit: 8, album: 'Summer' }) %}
<ul>
{% for image in images %}
<li><img src="{{ image.src }}" alt="{{ image.name }}"></li>
{% endfor %}
</ul>



rec_app - bring in a specific app quickly inside a template.

{{ rec_app('Contact us') }}


module - like the api(), but returns values from a custom module.

{% set logos = module('homepage-logos') %}
<div class="owl-carousel owl-theme">
{% for logo in logos.items %}
<a class="item" href="{{ logo.link }}">
<img src="{{ logo.logo_image }}" alt="{{ logo.name }}">
</a>
{% endfor %}
</div>


module_parents - Used for getting the parent items in a module relationship

{{ module_parents(item.id, 'app-store', 'author') }}    ->    Get all app-store items that have this item set as the author field

{{ module_parents(item.id, 'app-store') }} -> Get all app-store items that have this item set in any of its relation fields

{{ module_parents(item.id) }} -> Get all items across all modules that have this item set in any of its relation fields


rec_icon - Used to add a font/forkawesome icon (previously was useful in CKEditor as it used to remove empty html tags)

{{ rec_icon('cart') }}    ->    '<i class="fa fa-cart"></i>'


rec_page - Used to insert a pages HTML

{{ rec_page(1) }}    ->    Add the content of the page with an ID of 1
{{ rec_page('home') }} -> Add the content of the page with a slug of "home"
{{ rec_page('home', { template: true }) }} -> Same as above, but also bringing in the pages layout file
{{ rec_page('home', { template: true, keys: { custom: 123} }) }} -> Same as above, but allows you to pass custom keys to the template/page


rec_block - Used to render content blocks

{{ rec_block('Home Text') }}
{{ rec_block('Display Picture', type="image") }}


rec_form - Used to render forms

{{ rec_form('Contact Us') }}    ->    Render the form
{{ rec_form('Contact Us', { 'input_field_3': 5 }) }} -> Render the form and set the value of the input with a name of "input_field_3" to 5


add_to_cart_form - Generates an add to cart form for a specified product id

{{ add_to_cart_form(5) }}    ->    Generates a form to add the product with an id of 5 to the cart


tags_hierarchy - Converts an array of strings into a hierarchical array based on a divider

// Example code from a clients product_tags.html.twig
{% for group in groups %}
{% set tags = tags_hierarchy(group.title, group.tags, '>') %}

<details>
<summary>{{ group.title }}</summary>
<ul>
{% for tag, subtags in tags %}
<li>
{% if subtags is iterable %}
<details>
<summary>{{ tag }}</summary>
<ul>
{% for subtag, subsubtags in subtags %}
<li>
{% if subsubtags is iterable %}
<details>
<summary>{{ subtag }}</summary>
<ul>
{% for subsubtag, link in subsubtags %}
<li><a href="{{ link }}">{{ subsubtag }}</a></li>
{% endfor %}
</ul>
</details>
{% else %}
<a href="{{ subsubtags }}">{{ subtag }}</a>
{% endif %}
</li>
{% endfor %}
</ul>
</details>
{% else %}
<a href="{{ subtags }}">{{ tag }}</a>
{% endif %}
</li>
{% endfor %}
</ul>
</details>
{% endfor %}


scss - Include a SCSS/SASS file (Rivendell uses this function by default)

// This function takes in an uncompiled SCSS/SASS file, compiles it and presents it as CSS.
{{ scss('path/to/main.scss') }}