Twig is a PHP template engine1 that can greatly help clean up your code, as well as significantly speeding up development times. By separating the template data from the rest of the application, the UI can be updated without affecting the core logic of the program, such as pulling in information from a database.

Consider the following code, using PHPs deprecated mysql_query() methods.

<?php

require('/vendor/autoload.php');

// Connect to database
mysql_connect($server, $username, $password);

$resPeople = mysql_query("SELECT * FROM people");

?>

<table>
    <thead>
        <tr>
            <th>Name</th>
            <th>Age</th>
            <th>Colour</th>
        </tr>
    </thead>
    <tbody>
    <?

    $isFirst = true;

    if(mysql_num_rows($resPeople) > 0) {
        while($person = mysql_fetch_assoc($resPeople)) {
            ?>
            <tr<?=($isFirst ? " class=\"first_person\"" : "") ?>>
                <td><?=ucfirst($person['name'])?></td>
                <td><?=$person['age']?></td>
                <td><?=$person['colour']?></td>
            </tr>
            <?
            $isFirst = false;
        }
    } else {
        ?>
        <td colspan="3">No results</td>
        <?
    }

    ?>
    </tbody>
</table>

It is clear that the data source and the view is tightly coupled, even in a simple example. The code needs to be edited to switch to either mysqli or pdo, however it means that the HTML also needs to be affected.

In the next example, you can see the same program, however this time it is using Twig.

<?php

require('/vendor/autoload.php');

// Create a twig instance, loading templates from a directory.
$twig = new Twig_Environment(new Twig_Loader_Filesystem("templates"));

// Create database and fetch people (Note - This is only a quick example)
$db = new PDO($dsn, $username, $password);
$people = $db->query("SELECT * FROM people")->fetchAll();

echo $twig->render("people.twig", array(
    "people" => $people
));

Twig template:

<table>
    <thead>
        <tr>
            <th>Name</th>
            <th>Age</th>
            <th>Colour</th>
        </tr>
    </thead>
    <tbody>
        
        {% for person in people %}
        <tr {% if loop.first %}class="first_person" {% endif %}>
            <td>{{ person.name|title }}</td>
            <td>{{ person.age }}</td>
            <td>{{ person.colour }}</td>
        </tr>
        {% endfor %}
        
    </tbody>
</table>

The code is far easier to read, and very simple to maintain. If the script changes in future, and $people is fetched from a cache or API request, the HTML template can stay exactly how it is, making the changes far quicker to implement.

Setting Up

Twig needs to be made available as a dependency, using Composer2. Add twig to your composer.json file like so:

{
    "require": {
        "twig/twig": "1.18.*@dev"
    }
}

and then run $ composer install to download the package.

<?php

// Include composer packages
require('/vendor/autoload.php');

// Create a twig instance, loading templates from a directory.
$twig = new Twig_Environment(new Twig_Loader_Filesystem("templates/"));

This will create a new twig instance, loading in files from the templates directory.

Rendering data is as easy as:

<?php

...

echo $twig->render("people.twig", array(
    "people" => $people
));
  1. Twig - http://twig.sensiolabs.org/ 

  2. Composer - https://getcomposer.org/ 

Comments