PHP: Templates using Twig

This page forms the code summary of 08.templates.html, part of the Webscripting1 — Serverside Webscripting course, part of the Professional Bachelor ICT study programme, taught at Odisee, Ghent, Belgium. The materials and this summary were developed by Bram(us) Van Damme, lecturer ICT at Odisee, who blogs over at bram.us and Twitters as @bramus. The materials and this summary may be used freely, as long as credit to Bramus is present and a clear an upfront link to ikdoeict.be remains in place. Suggestions and additions may be mailed to Bramus, or sent via a pull request on GitHub.

Structure on disk

Loading and displaying templates

PHP file

<?php

	// includes & requires
	require_once __DIR__ . '/includes/Twig/Autoloader.php';
	Twig_Autoloader::register();

	// Twig Bootstrap
	$loader = new Twig_Loader_Filesystem(__DIR__ . '/templates');
	$twig = new Twig_Environment($loader, array(
		'cache' => __DIR__ . '/cache',
		'auto_reload' => true // set to false on production
	));

	// Data (fetched from DB for example)
	$user = array(
		'id' => 1,
		'username' => 'bramus',
		'firstname' => 'Bramus',
		'lastname' => 'Van Damme',
		'email' => 'bramus.vandamme@odisee.be',
		'password' => '$1$oGlMhJl6$EbgQIf8kQSr6MxA3YYYpm0'
	);

	// load template
	$tpl = $twig->loadTemplate('template.twig');

	// render template with our data
	echo $tpl->render(array(
		'user' => $user
	));

// EOF

Source template.twig

<p>Hi {{ user.firstname }} {{ user.lastname }}!</p>

Variable Filters

Variables can be filtered before display. Multiple filters can be added.

<p>The value of title is {{ title }}</p>
<p>{{ tagline|replace({'like':'love', 'Twig':'you'}) }}</p>
<p>Today: {{ curdate|date("d/m/Y") }}</p>
<p>{{ name|upper|reverse }}</p>

Full list of filters at http://twig.sensiolabs.org/doc/filters/index.html

Working with arrays

Looping Arrays

PHP array

$colleagues = array(
	array(
		'name' => 'Rogier van der Linde',
		'city' => 'Ghent',
		'courses' => array('Webtechnology', 'Webdesign & Usability', 'Webscripting 1', 'Webprogramming')
	), array(
		'name' => 'Kevin Picalausa',
		'city' => 'Ghent',
		'courses' => array('Webscripting 2', 'Webprogramming')
	), array(
		'name' => 'Davy De Winne',
		'city' => 'Schellebelle',
		'courses' => array('Webtechnology', 'Webdesign & Usability', 'Webscripting 2')
	), array(
		'name' => 'Joske Vermeulen'
	)
);

Template code

<h2>My web colleagues</h2>
<div>
	{% for colleague in colleagues %}
	<h3>
		{{ colleague.name }}
		{% if colleague.city %}<em>({{ colleague.city }})</em>{% endif %}
	</h3>
	<div>
		{% if colleague.courses %}
		<p>You might know him from:</p>
		<ul>
			{% for course in colleague.courses %}
			<li>{{ course }}</li>
			{% endfor %}
		</ul>
		{% else %}
		<p>(He's not teaching any web courses)</p>
		{% endif %}
	</div>
	{% endfor %}
</div>

Looping Arrays and getting the Keys / Keys & Values

Getting keys of an array

<ul>
{% for k in courses|keys %}
	<li>key: {{ k }}</li>
{% else %}
	<li>(no items in the array)</li>
{% endfor %}
</ul>

Getting keys & Values of an array

<ul>
{% for key, val in courses %}
	<li>{{ key }} = {{ val }}</li>
{% else %}
	<li>(no items in the array)</li>
{% endfor %}
</ul>

The loop variable

<ul>
{% for val in courses %}
	<li>
		{{ val }}
		<ul>
			<li><code>loop.index</code>: {{ loop.index }}</li>
			<li><code>loop.index0</code>: {{ loop.index0 }}</li>
			<li><code>loop.revindex</code>: {{ loop.revindex }}</li>
			<li><code>loop.revindex0</code>: {{ loop.revindex0 }}</li>
			<li><code>loop.first</code>: {{ loop.first }}</li>
			<li><code>loop.last</code>: {{ loop.last }}</li>
			<li><code>loop.length</code>: {{ loop.length }}</li>
		</ul>
	</li>
{% endfor %}
</ul>

Generating your own sequences

<p>{% for i in 0..10 %}{{ i }}{% endfor %}</p>
<p>{% for letter in 'a'..'z' %}{{ letter }}{% endfor %}</p>

More on if

If can also do comparisons and various checks

{% if username == 'bramus' %} YOLO {% endif %}
{% if user in ['bramus', 'rogier'] %} YOLO {% endif %}
{% if blogpost.visibility == 'password' %}
    <p>Blogpost is password protected</p>
{% elseif blogpost.visibility == 'link' %}
    <p>Blogpost is public for those who have the link</p>
{% else %}
    <p>Blogpost is public for all</p>
{% endif %}

Template Inheritance

Use block to define a few blocks in a parent template and use extends in the child template to extend from it.

In the child template, overwrite blocks from the parent template, using the same block. Use parent() to render the code of the parent block. Use set to set variables in the parent template.

Master/Parent template

<!doctype html>
<html>
<head>
	<title>{{ pageTitle }}</title>
	<style>
	{% block pageStyle %}
		div { padding-left: 1em; margin-left: 1em; border-left: 0.125em solid #666;}
	{% endblock %}
	</style>
</head>
<body>
	<h1>{{ pageTitle }}</h1>
	<div>
		{% block pageContent %}
		{% endblock %}
	</div>
	{% block pageFooter %}
	<footer>This is the footer</footer>
	{% endblock %}
</body>
</html>

Child template

{% extends 'layout.twig' %}

{% set pageTitle = pageTitle|replace({'e': 'a'}) ~ ' (Manipulated)' %}

{% block pageStyle %}
	{{ parent() }}
	footer { text-align: center; padding-top: 2em; }
{% endblock %}

{% block pageContent %}
	<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc quis neque libero, non rutrum nisi. Donec venenatis, nibh in aliquet consectetur, leo tellus elementum libero, at pretium ante enim nec tellus. Sed quis tempor erat.</p>
	<p>Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Etiam a urna sit amet augue iaculis fringilla. Nulla semper nulla mauris, at pellentesque mauris. Aenean viverra dictum ullamcorper. Nam eros dui, pellentesque et ultrices vitae, adipiscing feugiat sapien. Pellentesque tincidunt eros eu sem convallis fermentum. Donec dui ante, scelerisque in sollicitudin in, consectetur vel diam.</p>
{% endblock %}

Load the child template in your PHP:

// load template
$tpl = $twig->loadTemplate('child.twig');

// render template with our data
echo $tpl->render(array(
	'pageTitle' => 'Template Inheritance'
));

Inclusion of another template also possible

Suggested to place these partial templates into templates/partials/

{% include 'partials/sidebar.twig' %}