+ All Categories
Home > Software > Making Sense of Twig

Making Sense of Twig

Date post: 28-Aug-2014
Category:
Upload: brandonkelly212
View: 665 times
Download: 5 times
Share this document with a friend
Description:
These are the slides for a workshop I’ve given at a couple conferences, explaining how Twig works to people who don’t necessarily come from a programming background.
114
Making Sense of Twig Brandon Kelly
Transcript
Page 1: Making Sense of Twig

Making Sense of Twig

Brandon Kelly

Page 2: Making Sense of Twig

What is Twig?

Page 3: Making Sense of Twig

It’s a templating language. !

All templating features are available globally to all templates in any context, as part of the language. !

It’s not up to each and every application feature to provide its own tags.

Page 4: Making Sense of Twig

It’s super powerful. !

- Many ways to stay DRY - Custom variables - Functions - Filters - It knows math - Whitespace control - Extensible

Page 5: Making Sense of Twig

Templates get compiled into PHP, so it’s super fast.

Page 6: Making Sense of Twig

Twig even makes debugging a piece of cake.

Page 7: Making Sense of Twig

Used by some popular apps: !

- LemonStand - Symfony - Craft - others

Page 8: Making Sense of Twig

twig.sensiolabs.org

Page 9: Making Sense of Twig

The Language

Page 10: Making Sense of Twig

Types of Tags

Page 11: Making Sense of Twig

<html> <head> <title>{{ title }}</title> </head> <body> <h1>{{ title }}</h1> {% block main %} <p>Hey!</p> {% endblock %} </body> </html>

Page 12: Making Sense of Twig

<html> <head> <title>{{ title }}</title> </head> <body> <h1>{{ title }}</h1> {% block main %} <p>Hey!</p> {% endblock %} </body> </html>

Page 13: Making Sense of Twig

<html> <head> <title>{{ title }}</title> </head> <body> <h1>{{ title }}</h1> {% block main %} <p>Hey!</p> {% endblock %} </body> </html>

Page 14: Making Sense of Twig

Twig code always lives within one of these three tag pairs: !

{# ... #} {{ ... }} {% ... %}

Page 15: Making Sense of Twig

{# ... #}

Comment Tags

Page 16: Making Sense of Twig

Comment tags are like HTML comments, except they won’t show up in the page source. !

{# This won’t make it to the page source #} !

<!-- This will -->

Page 17: Making Sense of Twig

{{ ... }}

Output Tags

Page 18: Making Sense of Twig

Output tags output stuff to the browser. !

{{ title }} !

{{ "Howdy" }} !

{{ 84 / 2 }}

Page 19: Making Sense of Twig

{% ... %}

Logic Tags

Page 20: Making Sense of Twig

Logic tags (or just “tags”) control the logic of the template: !

- Conditionals - Loops - Variable definitions - Macros - Template includes - etc.

Page 21: Making Sense of Twig

The syntax varies from tag to tag.

Page 22: Making Sense of Twig

Some are just a single word. !

{% requireLogin %}

Page 23: Making Sense of Twig

Some take parameters. !

{% exit 404 %}

Page 24: Making Sense of Twig

Some have a closing tag. !

{% block content %} <p>Hey</p> {% endblock %}

Page 25: Making Sense of Twig

Some even have nested tags. !

{% if foo %} <p>Something</p> {% else %} <p>Something else</p> {% endif %}

Page 26: Making Sense of Twig

It really all depends on the tag. !

The only thing they have in common is that they all start with “{%”, followed by the tag name. !

{% tagname ...

Page 27: Making Sense of Twig

Twig comes with several built-in tags. !{% autoescape %} {% block %} {% filter %} {% do %} {% embed %} {% extends %} {% autoescape %} {% flush %} {% for %} {% from %}

{% if %} {% import %} {% include %} {% macro %} {% sandbox %} {% set %} {% spaceless %} {% use %} {% verbatim %}

Page 28: Making Sense of Twig

{% autoescape %} !

Escapes text for HTML. !

{% autoescape %} <p>Hey</p> {% endautoescape %} => &lt;p&gt;Hey&lt;/p&gt;

Page 29: Making Sense of Twig

{% autoescape %} (Cont.) !

...or Javascript !

{% autoescape "js" %} http://foo.com {% endautoescape %} => http\x3A\x2F\x2Ffoo.com

Page 30: Making Sense of Twig

{% spaceless %} !

Removes any whitespace between Twig/HTML tags. !

{%- spaceless %} <p>Hey there</p> {% endspaceless -%} => <p>Hey there</p>

Page 31: Making Sense of Twig

{% verbatim %} !

Defines template code that Twig should output as-is, without parsing. !

{% verbatim %} <p>Type “{{ foo }}”.</p> {% endverbatim %} => <p>Type “{{ foo }}”.</p>

Page 32: Making Sense of Twig

You never put a Twig tag inside another Twig tag. !

Bad: !

{{ "Hey {{ firstName }}" }} !

Good: !

{{ "Hey " ~ firstName }}

Page 33: Making Sense of Twig

Values, Expressions, and Variables

Page 34: Making Sense of Twig

Twig supports five different types of values. !

Strings: "Hey" / 'Hey' Numbers: 42 / 3.14 Booleans: true / false Arrays: ['a', 'b', 'c'] Objects: { foo: 'bar' }

Page 35: Making Sense of Twig

An expression is either a solo value, or multiple values combined to form another value. !

"Hey" => "Hey" "Hey "~"there" => "Hey there" 10 => 10 true => true ['a','b','c'] => ['a','b','c'] "Day "~1 => "Day 1" 10*(5+5) => 100

Page 36: Making Sense of Twig

Variables are values that get set to a name, to be referenced later. !

Use the {% set %} tag to create them. !

{% set foo = "foo" %} {% set a = 42 %} {% set foobar = foo~"bar" %}

Page 37: Making Sense of Twig

The {% set %} tag can also be used as a tag pair. !

{% set foo %} <p>foo</p> {% endset %} !

That’s the same as: !

{% set foo = "\n <p>foo</p>\n " %}

Page 38: Making Sense of Twig

Variables are one tool for keeping our templates DRY. !

{% set title = "About Us" %} ... <title>{{ title }}</title> ... <h1>{{ title }}</h1>

Page 39: Making Sense of Twig

Filters

Page 40: Making Sense of Twig

Filters modify values. !

They can uppercase text, merge arrays, and lots of other things.

Page 41: Making Sense of Twig

To pass a value through a filter, type a pipe (“|”) after the value, followed by the filter name. !

"foo"|upper => "FOO" 21.3|round => 21 ['a','b','c']|length => 3

Page 42: Making Sense of Twig

Some accept arguments. !

"foobar"|slice(0,3) => foo

Page 43: Making Sense of Twig

You can even chain them. !

"foobar"|slice(0,3)|upper => FOO

Page 44: Making Sense of Twig

You can add filters to variables, too. !

{% set foo = "foo" %} {{ foo|length }} => 3

Page 45: Making Sense of Twig

You can use them in pretty much any context you can think of. !

{{ value|filter }} !

{% set foo = value|filter %} !

{% do func(value|filter) %}

Page 46: Making Sense of Twig

Filters only modify the value directly before the filter. !

"foo"~"bar"|upper => fooBAR !

("foo"~"bar")|upper => FOOBAR

Page 47: Making Sense of Twig

Twig comes with tons of built-in filters: |abs |batch |capitalize |covert_encoding |date |date_modify |default |escape |first |format |join |json_encode |keys |last |length |lower

|nl2br |number_format |merge |upper |raw |replace |reverse |round |slice |sort |split |striptags |title |trim |url_encode

Page 48: Making Sense of Twig

|length !

Finds the length of a string or array. !

{{ "foobar"|length }} => 6 !

{{ [1, 2, 3]|length }} => 3

Page 49: Making Sense of Twig

|upper & |lower !

Modify the casing of a string. !

{{ "foo"|upper }} => FOO !

{{ "BAR"|lower }} => bar

Page 50: Making Sense of Twig

|raw !

Protects a string from getting escaped. !

{{ "<p>Hey</p>" }} => &lt;p&gt;Hey&lt;/&gt; !

{{ "<p>Hey</p>"|raw }} => <p>Hey</p>

Page 51: Making Sense of Twig

|date !

Formats a date. !

{{ now|date("F j, Y") }} => April 23, 2014

Page 52: Making Sense of Twig

Functions

Page 53: Making Sense of Twig

Functions perform functions. !

To call one, type its name, followed by parentheses. !

{{ parent() }}

Page 54: Making Sense of Twig

Many functions accept arguments: !

random(1, 10)

Page 55: Making Sense of Twig

Some of them are global: !

{{ dump(foo) }} !

And they can also be nested within objects: !

{{ craft.isLocalized() }}

Page 56: Making Sense of Twig

Twig comes with a few global functions built-in:

attribute() block() constant() cycle() date() dump() include()

max() min() parent() random() range() source() template_from_string()

Page 57: Making Sense of Twig

min() & max() !

Returns the smallest/largest value in a given array. !

{{ min([1, 2, 3]) }} => 1 !

{{ max([1, 2, 3]) }} => 3

Page 58: Making Sense of Twig

random() !

{{ random("foobar") }} => f/o/b/a/r !

{{ random([1, 2, 3]) }} => 1/2/3 !

{{ random(10) }} => 1/2/3/4/5/6/7/8/9/10

Page 59: Making Sense of Twig

range() !

Creates a range of numbers as an array. !

{% set r = range(1, 5) %} => [1, 2, 3, 4, 5] !

{% set r = [1..5] %} => [1, 2, 3, 4, 5]

Page 60: Making Sense of Twig

dump() !

Outputs information about a given variable. Helpful when debugging. !

{{ dump(foo) }} !

(In Craft, dump() is only available in Dev Mode.)

Page 61: Making Sense of Twig

Conditionals

Page 62: Making Sense of Twig

You can prevent certain parts of your template from executing unless a certain condition is met by wrapping it in conditional tags.

Page 63: Making Sense of Twig

Conditionals always open with an {% if %} tag, and close with an {% endif %} tag. !

{% if user %} <p>Hey there handsome!</p> {% endif %}

Page 64: Making Sense of Twig

You can also specify template code to be executed if the condition doesn’t pass, using the {% else %} tag. !

{% if user %} <p>Hey there handsome!</p> {% else %} <p>Have we met?</p> {% endif %}

Page 65: Making Sense of Twig

There’s also an {% elseif %} tag if you need fallback conditions. !

{% if user %} <p>Hey there handsome!</p> {% elseif username %} <p>Is this {{ username }}?</p> {% else %} <p>Have we met?</p> {% endif %}

Page 66: Making Sense of Twig

Conditionals can be nested. !

{% if user %} {% if user.male %} <p>Hey there handsome!</p> {% else %} <p>Hey pretty lady!</p> {% endif %} {% elseif username %} <p>Is this {{ username }}?</p> {% else %} <p>Have we met?</p> {% endif %}

Page 67: Making Sense of Twig

A single condition can be made up of multiple expressions joined together with “and” or “or”. !

{% if foo and bar %} !

{% if foo or bar %}

Page 68: Making Sense of Twig

You can negate a condition by typing “not” before it. !

{% if not foo %}

Page 69: Making Sense of Twig

You can also group expressions together using parentheses. !

{% if foo and ( foo == "foo" or foo == "bar" ) %}

Page 70: Making Sense of Twig

Tests

Page 71: Making Sense of Twig

Tests are little conditional helpers. They don’t have to be used within conditionals, but usually are.

Page 72: Making Sense of Twig

To write a test, add either “is” or “is not” after a variable, followed by the test name. !

{% if foo is defined %} !

{% if foo is not empty %}

Page 73: Making Sense of Twig

Twig comes with a few tests built-in. !

is constant is defined is divisible by is empty is even

is iterable is null is odd is same as

Page 74: Making Sense of Twig

is defined !

Tests whether a variable exists at all, without Twig getting mad at you if it’s not. !

{% if foo is defined %}

Page 75: Making Sense of Twig

is divisible by !

Tests whether a number is divisible by another. !

{% if 5 is divisible by(2) %} !

That’s similar to writing: !

{% if 5 % 2 == 0 %}

Page 76: Making Sense of Twig

is even & is odd !

Tests whether a number is even/odd. !

{% if 5 is even %} !

{% if 5 is odd %}

Page 77: Making Sense of Twig

is empty !

Tests whether a variable is “empty”. !

{% if foo is not empty %} !

That’s the same as writing: !

{% if foo %}

Page 78: Making Sense of Twig

is same as !

Tests whether two variables have the same *type*. !

{% if 5 == "5" %} => true !

{% if 5 is same as "5" %} => false

Page 79: Making Sense of Twig

Working with Arrays and Objects

Page 80: Making Sense of Twig

Arrays and objects both contain multiple values.

Page 81: Making Sense of Twig

Arrays contain values in a specific order, and have an inherent numerical index. !

{% set arr = ['a','b','c'] %} !

{{ arr[0] }} => 'a' {{ arr[1] }} => 'b' {{ arr[2] }} => 'c'

Page 82: Making Sense of Twig

Objects contain key-value pairs, and the order is generally less important. !

{% set obj = { foo: "Foo", bar: "Bar" } %} !

{{ obj.foo }} => "Foo" {{ obj.bar }} => "Bar"

Page 83: Making Sense of Twig

You can merge arrays together with the ‘merge’ filter. !

{% set a1 = ['a','b'] %} {% set a2 = ['c','d'] %} {% set a3 = a1|merge(a2) %} !

=> ['a','b','c','d']

Page 84: Making Sense of Twig

You can merge objects together too. !

{% set o1 = {foo: "Foo"} %} {% set o2 = {bar: "Bar"} %} {% set o3 = o1|merge(o2) %} !

=> {foo: "Foo", bar: "Bar"}

Page 85: Making Sense of Twig

You can grab part of an array with the “slice” filter. !

{% set a1 = ['a','b','c'] %} {% set a2 = a1|slice(0, 2) %} !

=> ['a','b'] !

A shortcut is also available: !

{% set a2 = a1[0:2] %}

Page 86: Making Sense of Twig

Looping througharrays and objects

Page 87: Making Sense of Twig

You can loop through arrays with the {% for %} tag. !

The syntax is: !

{% for itemname in myarray %} ... {% endfor %} !

The 2nd param (“itemname”) is whatever you want to call each item within the array.

Page 88: Making Sense of Twig

Example 1: Age field !

<select name="age"> {% for age in [0..150] %} <option> {{ age }}</option> {% endfor %} </select>

Page 89: Making Sense of Twig

Example 2: Exp. Year field !

{% set y1 = now.year %} {% set y2 = y1 + 10 %} !

<select name="exp_year"> {% for year in [y1..y2] %} <option> {{ year }}</option> {% endfor %} </select>

Page 90: Making Sense of Twig

Example 3: Navigation !

{% set nav = [ { title: "Home", uri: "" }, { title: "About", uri: "about" } ] %} !

<nav> {% for item in nav %} <a href="{{ url(item.uri) }}"> {{ item.title }}</a> {% endfor %} </nav>

Page 91: Making Sense of Twig

DRY Templating

Page 92: Making Sense of Twig

Includes

Page 93: Making Sense of Twig

Templates can include others.

Include Template

Parent Template

Parent Template

Page 94: Making Sense of Twig

Use the {% include %} tag to include another template wherever the tag is placed. !

{% include "some/template" %}

Page 95: Making Sense of Twig

By default, any variables available to the “parent” template will also be available in the included template. !

{% set foo = "foo" %} {% include "myinclude" %} !

myinclude.html: {{ foo }} => foo

Page 96: Making Sense of Twig

You can define additional variables just for the included template using the “with” param. !

{% include "myinclude" with { foo: "foo" } %} !

some/template.html: {{ foo }} => foo

Page 97: Making Sense of Twig

To *only* pass certain variables to the included template, use the “only” param. !

{% set foo = "foo" %} {% include "myinclude" with { bar: "bar" } only %} !

some/template.html: {% if foo is defined %} => false

Page 98: Making Sense of Twig

Extending Templates

Page 99: Making Sense of Twig

A template can extend another, overriding parts of it (called “blocks”).

Parent Template

Block

Child Template Child Template

Page 100: Making Sense of Twig

Define overridable areas in the parent template using the {% block %} tag. !

<body> {% block body %} <p>Default content</p> {% endblock %} </body>

Page 101: Making Sense of Twig

Use the {% extends %} tag within your child template to tell it which template it extends. !

{% extends "layout" %}

Page 102: Making Sense of Twig

Override the parent’s blocks by creating new blocks in the child template with the same name. !

{% extends "layout" %} !

{% block body %} <p>Override content</p> {% endblock %}

Page 103: Making Sense of Twig

You can output the parent block’s content using the parent() function. !

{% extends "layout" %} !

{% block body %} {{ parent() }} <p>Additional content</p> {% endblock %}

Page 104: Making Sense of Twig

Multi-level inheritance is totally possible.

Page 105: Making Sense of Twig

Embedding Templates

Page 106: Making Sense of Twig

Twig also lets you “embed” other templates, which is similar to including them, except you get to override the child template’s blocks in the process.

Page 107: Making Sense of Twig
Page 108: Making Sense of Twig

Use the {% embed %} tag to embed another template. !

{% embed "promo" %} {% block body %} {{ parent() }} <span class="ribbon"> 50% off! </span> {% endblock %} {% endembed %}

Page 109: Making Sense of Twig

Macros

Page 110: Making Sense of Twig

Macros are like includes that are defined right within another template.

Page 111: Making Sense of Twig

Use the {% macro %} tag to define them. !

{% macro errors(list) %} {% if list|length %} <ul class="errors"> {% for error in list %} <li>{{ error }}</li> {% endfor %} </ul> {% endif %} {% endmacro %}

Page 112: Making Sense of Twig

You must import macros before you can use them, with either {% from %} or {% import %}. !

{% from _self import errors %} {{ errors(entry.allErrors) }} !

!

{% import _self as m %} {{ m.errors(entry.allErrors) }}

Page 113: Making Sense of Twig

You can import macros from other templates, too. !

{% from "macros" import errors %} {{ errors(entry.allErrors) }} !

!

{% import "macros" as m %} {{ m.errors(entry.allErrors) }} !

Page 114: Making Sense of Twig

The End.


Recommended