Wern Ancheta

Adventures in Web Development.

Using the Twig Templating Engine in PHP

| Comments

Separation of concerns is a design principle in Computer Science for separating a program into sections, each with their own responsibility. MVC, an architectural pattern used in most PHP frameworks allows developers to implement separation of concerns. One part of MVC is the View which handles the presentation layer of the application. In this tutorial I’ll walk you through Twig, a templating engine for PHP. This allows us to separate the view from the business logic of the app.

Installation

Execute the following on your terminal to install Twig.

1
composer require twig/twig

In your working directory, create a template folder for storing the Twig templates and a cache folder for storing the cached templates. Twig puts the compiled version of templates into this folder so that the next time it’s requested and there’s no change in the template, it serves the cached version instead. Be sure to change the file permissions of the cache folder so that Twig can write into it. I had to do the following to have it work.

1
sudo chmod -R 777 cache

Usage

To use Twig, include the vendor autoload file.

1
2
3
<?php
require_once 'vendor/autoload.php';
?>

Next create a new instance of the Twig_Loader_Filesystem class and supply the path to the templates directory as its argument. After that, create a new instance of the Twig_Environment class and pass in the loader and an array of options as its argument. In this case, only the cache item is specified. This allows you specify the path of the cache directory.

1
2
3
4
5
6
<?php
$loader = new Twig_Loader_Filesystem('templates');
$twig = new Twig_Environment($loader, array(
    'cache' => 'cache',
));
?>

To load a template, use the loadTemplate method on the Twig instance that you created earlier. Then pass in the path to the template that you want to use. After that, you can now output the view by calling the render method on the template. This accepts the data that you want to pass in to the view.

1
2
3
4
<?php
$template = $twig->loadTemplate('index.html');
echo $template->render(array('name' => 'John Doe', 'age' => 19));
?>

On the templates directory, create the index.html file that you were referring to in the loadTemplate method and then add the following code.

1
2
3
4
5
6
7
8
9
10
11
12
13

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>twig</title>
</head>
<body>
    <h1>Hi {{ name }}!</h1>
    <h2>You are {{ age }} years old</h2>
</body>
</html>

From the above code, you can see that the way the individual items in the array that you passed in the render method is by wrapping the name of the item in double curly braces. Here’s how it’s going to look like when access from the browser.

twig hello world

Note that Twig is pretty forgiving when it comes to data that you pass in to the template. For example, if you do not pass in the age, it wouldn’t throw an error at you.

1
2
3
<?php
echo $template->render(array('name' => 'John Doe'));
?>

Outputting Raw HTML

Twig automatically escapes HTML so if you pass in HTML as data for your template, it is outputted as is.

1
2
3
<?php
echo $template->render(array('name' => 'John Doe', 'html_string' => '<h3>hi Im an html inside a template</h3>'));
?>

If you want to get the HTML interpreted by the browser, you have to use the raw filter.

1
2
3
4
5
6
7

<body>
    <h1>Hi {{ name }}!</h1>
    <h2>You are {{ age }} years old</h2>
    {{ html_string | raw }}
</body>

Looping through Arrays

You can also load arrays for the data.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
$template = $twig->loadTemplate('index.html');

$data = array(
    'users' => array(
        array(
            'name' => 'Yoh Asakura',
            'age' => 10
        ),
        array(
            'name' => 'Ash Ketchum',
            'age' => 14
        ),
        array(
            'name' => 'Naruto Uzumaki',
            'age' => 25
        )
    )
);

echo $template->render($data);
?>

And the way you output them in your template is by using the for tag. Here’s an example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<h1>Users</h1>
<table border="1">
    <thead>
        <tr>
            <th>Name</th>
            <th>Age</th>
        </tr>
    </thead>
    <tbody>
        
        {% for user in users %}
        <tr>
            <td>{{ user.name }}</td>
            <td>{{ user.age }}</td>
        </tr>
        {% endfor %}
        
    </tbody>
</table>

To use the for tag, assign an alias for each item in the array that you specified. In this case, the array is users and each item is represented by the user variable. Inside the for tag, you can then access each user field. After you have outputted all the user details, close it with the endfor tag.

for

Conditions

Twig allows you to use tags such as if, else, elseif, and if not for checking for simple conditions in your templates. Here’s an example of using the if tag for checking if the age of the user is greater than or equal to 14.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<h1>Users</h1>
<table border="1">
    <thead>
        <tr>
            <th>Name</th>
            <th>Age</th>
        </tr>
    </thead>
    <tbody>
        
        {% for user in users %}
            {% if user.age >= 14 %}
            <tr>
                <td>{{ user.name }}</td>
                <td>{{ user.age }}</td>
            </tr>
            {% endif %}
        {% endfor %}
        
    </tbody>
</table>

if

Layouts

Layouts can be used in order to avoid repitition of re-occurring elements of the page such as the header and the footer. To use layouts, you need a base template (base.html). This is the template that contains all the re-occurring elements of the page. This is essentially the main template in which all the other templates (child templates) inherits from. Your main template is where you usually declare the content block. This is the block that’s going to get replaced by the content that you supply on your child template.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="assets/css/style.css" />
        <title></title>
    </head>
    <body>
        <div id="content">
        
        {% block content %}{% endblock %}
        
        </div>
    </body>
</html>

From your child template (child.html), use the extends tag to let Twig know which template you want to inherit from. Below it, you use the same block that you used in your main template. In this case the name of the block is content. Inside the block, you put in the contents that you want to get rendered.

1
2
3
4
5
6

{% extends "base.html" %}
{% block content %}
   <h1>Hello World!</h1>
{% endblock %}

Notice that in the main template there’s also a stylesheet. You need to create it on the assets/css directory. Here’s the contents of the style.css file.

1
2
3
body {
    background: orange;
}

Finally, from your PHP file, all you need to do is render the child template.

1
2
3
4
<?php
$template = $twig->loadTemplate('child.html');
echo $template->render(array('title' => 'my page'));
?>

Here’s how its going to look like:

layouts

Filters

Twig also comes with filters. Filters as the name suggests, allows you to filter the content that you pass into it.

Format

If you need to perform a find and replace on a string, you can use the format filter. Here’s how you can use it.

1
2
3
4
5
6
<?php
$data = array(
    'name' => 'Ami Damaru',
    'age' => 110
);
?>
1
2
3
4
5
<p>

{{ "Hi I'm %s, I am %s years old" | format(name, age) }}

</p>

As you have seen above, to use the format filter, simply pipe it to the string that you want to perform find and replace on. Each string that you want to replace within the string should be %s. So in this case, the name and age is substituted for that value. It should result in the following output:

1
Hi I'm Ami Damaru, I am 110 years old
nl2br

The nl2br filter allows you to replace line breaks (\n) in your string with <br /> tags. This is useful if you want to output a string which uses line breaks instead of <br /> tags.

1
2
3
4
5
6
7
<?php
$data = array(
    'string' => "The quick brown fox\n jumps over the heade\n of the lazy dog"
);

echo $template->render($data);
?>
1
2
3
4
5
<p>

    {{ string | nl2br }}

</p>
date and date_modify

The date and date_modify filters allows you to modify the formatting of a date.

1
2
3
4
5
6
7
<?php
$date = array(
    'date' => '2015-03-17'
);

echo $template->render($data);
?>
1
2
3
4
5

<p>
    {{ date | date_modify("+1 week") | date('M d, Y') }}
</p>

The code above will output.

1
Aug 03, 2015
upper and lower

upper and lower filters allows you to change the individual letters in a string into uppercase or lowercase.

1
2
3
4

{{ 'MAKE ME LOWER' | lower }}
{{ 'make me higher' | upper }}

The output will be:

1
make me lower MAKE ME HIGHER

Conclusion

That’s it! In this tutorial, you’ve learned how to work with Twig, a templating engine for PHP. For more information about Twig, check out the official docs.

Comments