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 }}


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'


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') }}