Templates with Twig
Easier Than You Think

with Margaret Staples
Hello, Nice to Meet You
I'm Margaret






Hello, Nice to Meet You
I'm Margaret
I have been working with Twig
mostly as part of the Symfony2 framework
for about 3 years

Hello, Nice to Meet You
I'm Margaret
I'm developing a Social Strategy City-Builder RPG game of awesomeness.

brunegame.com
Twig Templates

Overview
- Create a New Project
- Install Twig
- Create a Twig Layout
- Initial Twig Template
- Using Variables
- Conditionals and Loops
- Including Templates
- Additional Information
Create a New Project
Local Webserver
Linux + Apache + MySQL + PHP


Create a New Project
New Project Structure
*/NewProject
*/NewProject/src
*/NewProject/views
*/NewProject/index.php
*/path/to/web/directory


Install Twig
Composer
Dependency Manager for PHP

getcomposer.org
Install Twig
Install Twig
*/NewProject/composer.json
{
"autoload": {
"psr-4": {
"NewProject\\Classes\\": "src/"
}
},
"require": {
"twig/twig": "~1.0"
}
}
> php composer.phar install

Install Twig
Install Twig (Alternative)
> php composer.phar init
Search for a package: Twig
Enter package # to add ...: 0
...
"autoload": {
"psr-4": {
"NewProject\\Classes\\": "src/"
}
}
...

Install Twig
*/NewProject/index.php
<?php
require_once 'vendor/autoload.php';
require_once 'vendor/twig/twig/lib/Twig/Autoloader.php';
Twig_Autoloader::register();
$loader = new Twig_Loader_Filesystem('views');
$twig = new Twig_Environment($loader, [
'cache' => 'cache',
]);
Add to index.php

Create a Twig Layout
*/NewProject/views/layout.html
<!DOCTYPE html>
<html>
<head>
<style>
h1 {
color: blue;
}
</style>
</head>
<body>
</body>
</html>
Create layout.html

Create a Twig Layout
Add Blocks to the Layout
Create layout.html
...
<body>
{% block content %}
{% endblock %}
{% block footer %}
© Copyright 2015 by MyCompany.
{% endblock %}
</body>
...
Blocks designate areas that may be replaced by child templates.
Block content in the layout will be the default.



Initial Twig Template
*/NewProject/views/index.html
{% extends 'layout.html' %}
{% block content %}
<h1>Hello World!</h1>
{% endblock %}
Create index.html

Initial Twig Template
*/NewProject/src/Page.php
<?php
namespace NewProject\Classes;
class Page
{
public function index()
{
return [
'salute' => 'goodnight',
'target' => 'moon'
];
Create Page.php

Initial Twig Template
*/NewProject/index.php
<?php
...
use NewProject\Classes\Page;
...
$page = new Page();
echo $twig->render('index.html', $page->index());
Use Page.php and index.html

Initial Twig Template
localhost/NewProject/index.php
View Initial Twig Template

Hello World!
Let's Review!
What is the purpose of views/layout.html?
Provide HTML, CSS, and Javascript that is the same for multiple templates

Let's Review!
What is the purpose of Page.php's index() function?
To prepare data for the index.html template.

Let's Review!
To identify where in layout.html to place the template content.

What is the purpose of the
{% content block %} {% endblock %} tags?
Using Variables
Use variables from Page.php index()
*/NewProject/src/Page.php
return [
'salute' => 'goodnight',
'target' => 'moon'
];
*/NewProject/index.php
echo $twig->render('index.html', $page->index());

Using Variables
*/NewProject/views/index.html
{% extends 'layout.html' %}
{% block content %}
<h1>{{ salute }} {{ target }}!</h1>
{% endblock %}
Use variables from Page.php index()

Using Variables
View Your Page
localhost/NewProject/index.php
goodnight moon!

Using Variables
Modify Your Variables
*/NewProject/views/index.html
{% extends 'layout.html' %}
{% block content %}
<h1>{{ salute|title }} {{ target|title }}!</h1>
{% endblock %}
Goodnight Moon!

Using Variables
{{ salute|capitalize }} = Goodnight
{{ salute|lower }} = goodnight
{{ salute|upper }} = GOODNIGHT
{{ salute }} moon = goodnight moon
{{ salute ~ ' ' ~ target }} = goodnight moon
{{ "goodnight ${target}" }} = goodnight moon
{{ "hi moon"|replace({ 'hi': 'goodnight' }) }} = goodnight moon

Strings






twig.sensiolabs.org

Using Variables
{{ -1234.567|round }} = -1235
{{ -1234.567|abs }} = 1234.567
{{ "1 + 2 = ${1 + 2}" }} = 1 + 2 = 3
{{ -1234.567|number_format(2) }} = -1,234.56
{{ 5 // 2 }} = 2
{{ 2 ** 3 }} = 8

Numbers






twig.sensiolabs.org
Using Variables

Setting Variables
twig.sensiolabs.org
{% set my_var = "I am a new value!" %}
{{ my_var }}
I am a new value!
Using Variables
More Filters
twig.sensiolabs.org/doc/filters/index.html
trim upper url_encodereplace reverse round nl2br number_format convert_encoding date |
abs batch capitalize date_modify default escape first formatjoin json_encode |
keys last length lower merge rawslice sort split striptags |
---|
Using Variables
Custom Filters, Functions, and Tags
twig.sensiolabs.org/doc/advanced.html#creating-an-extension
Implement the Twig_ExtensionInterface Interface
Register using the addExtension() method
Override the getFilters() method
Register functions using the getFunctions() method
Override the getTokenParsers() method





Let's Review!
How do we print the value of a variable in Twig?
Surround the variable name with double curly brackets:
{{ foo }}

Let's Review!
How do we apply a Twig filter to a value?
Follow the value with a pipe and the name of the filter:
{{ foo|title }}

Let's Review!
What signifies an action tag as opposed to a display tag?
Surround the action with curly-bracket percent-sign pairs:
{% set foo = bar %}

Conditionals and Loops
Logic
{{ "goodnight" starts with "g" }} = true
{{ "moon" ends with "p" }} = false
{{ "night" in "goodnight" }} = true
{{ 1 in [ 1, 2, 3 ] }} = true
{{ 1 is even }} = false
{{ 4 not in [ 1, 2, 3 ] }} = true
{{ "moon"|length < 3 }} = false







twig.sensiolabs.org

Conditionals and Loops
Conditionals
*/NewProject/views/index.html
{% if target|lower == 'sun' %}
{% set title_color = 'red' %}
{% else %}
{% set title_color = 'purple' %}
{% endif %}
<h1 style="color:{{ title_color }}">
{{ salute|title }} {{ target }}!
</h1>

Goodnight Moon!
Conditionals and Loops
Loops
*/NewProject/src/Page.php
public function index()
{
return [
'salute' => 'Goodnight',
'my_set' => [
'red' => 'Sun',
'blue' => 'Moon',
'purple' => 'Stars'
]
];
}

Conditionals and Loops
Loops
*/NewProject/views/index.html
{% for key,value in my_set %}
<h1 style="color: {{ key }}">
{{ loop.index }}. {{ salute }} {{ value }}!
</h1>
{% endfor %}
1. Goodnight Sun!
2. Goodnight Moon!
3. Goodnight Stars!

Conditionals and Loops
Loops with Objects
class MyRecord
{
protected title;
protected description;
protected link;
protected color;
...
}

Conditionals and Loops
Loops with Objects
*/NewProject/views/index.php
{% for record in my_records %}
<a href="{{ record.link }}">
<h1 style="color: {{ record.color }}">
{{ record.title }}
</h1>
</a>
<p>{{ record.description }}</p>
{% endfor %}

Conditionals and Loops
Loops with Nested Arrays
$my_array = [
1 => [
'title' => "My Title",
'description' => "This is a description",
'link' => "http://twig.sensiolabs.org",
'color' => "blue"
],
2 => [
'title' => "Other Title",
'description' => "Another description",
'link' => "http://getcomposer.org",
'color' => "green"
]
];

Conditionals and Loops
Loops with Nested Arrays
*/NewProject/views/index.php
{% for record in my_records %}
<a href="{{ record.link }}">
<h1 style="color: {{ record.color }}">
{{ record.title }}
</h1>
</a>
<p>{{ record.description }}</p>
{% endfor %}

Let's Review!
How do we access the keys when looping through an array?
By providing a key name followed by a comma and a value name in the loop declaration:
{% for key,value in array %}

Let's Review!
How do we access an object's properties?
By using a dot, followed by the property name:
myObject.objectProperty
*Bracket notation also works: myObject['objectProperty']

Let's Review!
How do we access an array value by key?
Just like an object:
myArray.arrayKey
*Bracket notation also works: myArray['arrayKey']

Let's Review!
How can we get the current iteration count in a loop?
loop.index

Including Templates
Create heading.html
*/NewProject/images/fancyheading.png
*/NewProject/views/heading.html
<div class="heading">
<img src="../images/fancyheading.png">
</div>

Including Templates
Create feature.html
*/NewProject/views/feature.html
<div class="feature">
<img src="../images/feature.png">
</div>
*/NewProject/images/feature.png

Including Templates
Create feature.html
*/NewProject/views/index.html
{% extends 'layout.html' %}
{% block content %}
{% include 'heading.html' %}
<h1>{{ salute|title }} {{ my_set.blue }}!</h1>
{% include 'feature.html' %}
{% endblock %}
Including Templates
localhost/NewProject/index.php

View Your Page
Goodnight Moon!

Twig Templates
Additional Information

http://twig.sensiolabs.org/
Questions?
Margaret Staples
@dead_lugosi on twitter
deadlugosi on freenode
brunegame.com
Twig
By Margaret Staples
Twig
- 3,743