Warning message

Documentation is currently being migrated into the new system. Some pages might be temporarily missing, and some guides might appear empty. Thank you for your patience while we are improving Drupal.org documentation.

Comparison of PHPTemplate and Twig theming paradigms

Last updated on
October 13, 2016 - 05:42

    About Twig

    Twig is a PHP-based compiled templating language. When your web page renders, the Twig engine takes the template and converts it into a 'compiled' PHP template which is stored in a protected directory in sites/default/files/php/twig. The compilation is done once, template files are cached for reuse and are recompiled on clearing the Twig cache.

    The Drupal Twig initiative shares the same motivation as the Symfony initiative: to adopt a modern, powerful, OOP-based engine that will allow developers to concentrate on Drupal properly.

    1. Docblock


     * @file
     * File description


     * @file
     * File description

    2. File and function names

    PHPTemplate file: node--article.tpl.php
    Twig file: node--article.html.twig

    PHPTemplate function: THEME_node_links()
    Twig file: node-links.html.twig

    3. Variables

    Printing a variable:
    PHPTemplate: <div class="content"><?php print $content; ?></div>
    Twig: <div class="content">{{ content }}</div>

    Printing a hash key item1
    PHPTemplate: <?php print $item['#item']['alt']; ?>
    Twig: {{ item['#item'].alt }}

    Assigning a variable:
    PHPTemplate: <?php $custom_var = $content->comments; ?>
    Twig: {% set custom_var = content.comments %}

    Assigning an array:
    PHPTemplate: <?php $args = array('@author' => $author, '@date' => $created); ?>
    Twig: {% set args = {'@author': author, '@date': created} %}

    4. Conditionals

    PHPTemplate: <?php if ($content->comments): endif; ?>
    Twig: {% if content.comments %} {% endif %}

    PHPTemplate: <?php if (!empty($content->comments)): endif; ?>
    Twig: {% if content.comments is not empty %} {% endif %}

    PHPTemplate: <?php if (isset($content->comments)): endif; ?>
    Twig: {% if content.comments is defined %} {% endif %}

    PHPTemplate: <?php if ($count > 0): endif; ?>
    Twig: {% if count > 0 %} {% endif %}

    5. Control structures

    PHPTemplate: <?php foreach ($users as $user) {} ?>
    Twig: {% for user in users %} {% endfor %}

    6. Filters

    Escaped HTML special characters:
    PHPTemplate: <?php print check_plain($title); ?>
    Twig2: {{ title }}

    Raw values:
    PHPTemplate: <?php print $title; ?>
    Twig: {{ title|raw }}

    PHPTemplate: <?php print t('Home'); ?>
    Twig: {{ 'Home'|t }}

    Translate with substitutions:
    PHPTemplate: <?php print t('Welcome, @username', array('@username' => $user->name)); ?>
    Twig: {{ 'Welcome, @username'|t({ '@username': user.name }) }}
    Drupal 8 Twig (with trans tag extension):

    {% set username = user.name %}
    {% trans %}
      Welcome, {{ username }}
    {% endtrans %}

    Implode a list:
    PHPTemplate: <?php echo implode(', ', $usernames); ?>
    Twig: {{ usernames | join(', ') }}

    Implode a list with Markup:
    Twig: {{ usernames | safe_join(', ') }}

    The PHPTemplate example requires $usernames to be an array of strings. The same goes for the Original Twig example where "usernames" is an array of strings. The Drupal 8 Twig example on the other hand requires an array of renderable objects. This is actually the fundamental difference between Drupal 8 Twig and the original Twig. Drupal 8 Twig "prints" both plain text and renderable arrays.

    Another aspect of this example is that one expects all three example to produce the same output, but it doesn't (by default). Take this example:

      {% set numbers = [{'#markup': 'One'}, {'#markup':'Two'}, {'#markup':'Three'}] %}
      {{ numbers }}

    The above suggests that items are printed separated by commas. But the output is: OneTwoThree

    7. Whitespace control

    Twig has whitespace control which allows for removing the whitespace used for structuring a template file.

    <div class="body">
      {{- block.content -}}

    Is same as:

    <div class="body">{{ block.content }}</div>


    1. The hash key item example might change in the future ↩︎︎
    2. In the second example, we show how Twig is responsible for sanitizing data. Previously it was up to the template file or preprocess function to handle this as well. This last change is a really big deal for anyone hoping to create a PHPTemplate theme for Drupal 8 - you'll need to sanitize your own data. ↩︎︎

    For more information, see: