Theming patterns of Drupal's PHPTempate and Twig Engines

As you most likely know, Drupal 8 will have not only PHPTemplate, but also Twig for it's templating engine. In the future, after support of Twig is deep and polished, PHPTemplate will most likely be deprecated. All developers, who have been theming for Drupal, have either already learned Twig, or are actively in the process of doing so. Here are the basics of applying Twig in Drupal context.

When writing this article, I especially kept in mind Twig team documentation, currently only available as a Google doc file. I am also thankful to FabianX for answering my questions in irc about current Twig template engine caching and to jenlampton for a valuable update. There is also a good Twig documentation to look at. Below are the patterns we used in PHPTemplate, and their Twig counterparts.

What is Twig and why Twig

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

The idea behind the Drupal Twig initiative is the same as behind the Symfony initiative. Adoption of a modern, powerful, OOP-based engine allows developers to concentrate on Drupal proper.

Following is the PHPTemplate to Twig comparison. When saying Twig, however, I mean a Drupal's Twig template engine, which is Twig proper adapted for Drupal. Twig implementation in Drupal is currently in progress, so there will be changes and additions to this doc.

1. Doc block

PHPTemplate:

  <?php
 
/**
   * @file
   *  File description
   */
 
?>

Twig:

  {#
  /**
   * @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>

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 (!empty($content->comments)): endif; ?>
Twig: {% if content.comments %} {% 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

Check_plain:
PHPTemplate: <?php print check_plain($title); ?>
Twig: {{ title | striptags }}

Translate:
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 }) }}

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

Escape:
PHPTemplate: <?php echo check_plain($title); ?>
Original Twig: {{ title|e }}
Drupal 8 Twig2: {{ title }}

7. Whitespace control

Twig has whitespace control ,which allows to remove the whitespace used for structuring of file.

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

Is same as:

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

Notes

These are some notes and updates that I felt like I needed to include:

  1. In this first example, we show how Twig will be responsible for flattening renderable structures (currently arrays, maybe soon also objects) into flat strings of HTML. Previously, it was up to the template file or preprocess function to do this. (jenlamption)
  2. In the second example, we show how Twig will also be 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. Yes, all of it. (jenlamption)