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: bob@email.com
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>
google_reviews - Bring in a slider (or other designed) app of Google Reviews
{{ google_reviews(template='slider', max=10, minScore=0, featured=false) }} - Template Name - Defaults to slider, if entered template doesn't exist a blank string is returned - Maximum amount of Reviews to show - Defaults to 10 - Minimum review score to show (inclusive) - Defaults to 0 - Show Featured Reviews only? - Defaults to false
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>
youtube - embed a youtube video
{{ youtube('url') }}
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") }}
Find out more about these content blocks & their related functions here.
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
CSRF token security
{{ csrf_token() }} <-- for just the token {{ csrf_field() }} <-- for the token in a hidden form input field
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') }}