Twig in Drupal

What does it mean?

  • No PHP in templates (cannot)
  • Debugging is different
  • Introduces some of the more modern template patterns into Drupal
  • More reusable and more standardization within templating

No PHP??

  • All gone, PHP cannot be used in a twig file
  • Twig eventually compiles into PHP, but PHP code cannot be invoked directly
  • Twig comes with some filters/functions out of the box
  • Extending Twig within Drupal is fairly easy to create reusable code snippets

Setup Twig: Debug and Caching

  • Twig is setup out of the box, but not ideally for development
  • Need to turn on debugging and autoloading, and turn off twig template caching

Setup

  • Copy example.settings.local.php in the sites/ dir and rename to settings.local.php in sites/default/
  • Under 'Disable Dynamic Page Cache', uncomment the setting
  • In settings.php, uncomment the lines that add settings.local.php if it exists
  • In development.services.yml add the following
parameters:
  twig.config:
    debug: true
    auto-reload: true

Debug Info

  • Debug gives you info about the template
    • Available suggestions, currently used one
  • Useful, but also verbose
  • If caching isn't disabled, you'll need to clear cache any time a change in a twig template is made

Using Twig: Render Arrays!

  • Twig {{ content }} syntax will render Drupal render arrays
<?php print render($content); ?>
{{ content }}

Hiding

  • Hiding fields from the bulk content render is also pretty similar
  • Implemented with a filter
  • Note: printing a field does NOT automatically hide it from the global content array
<?php hide($content['field_name'); ?>

<div class="main"><?php print render($content); ?></div>

<div class="separate"><?php print render($content['field_name']); ?></div>
<div class="main">{{ content|without('field_name') }}</div>

<div class="separate">{{ content.field_name }}</div>

Drill Down

  • Dot syntax or bracket syntax to drill down into an array
  • If the key contains a special character, like #, you must use brackets
{{ content.field_shorttext }}

{{ content['field_shorttext'] }}

{{ content.field_shorttext.0['#context']['value'] }}

That's It!

  • In terms of rendering content, that's generally as much as you do in a twig template
  • Any extended functionality comes from functions, filters, and macros that you define elsewhere but can employ within a twig template, control statements, and extends

{% extends %}

  • Extending templates is generally one of the biggest standout features of using a templating engine like Twig
  • PHP templating does not support the concept of extending a template
  • Extending is almost the opposite of including
  • Point to where the template inherits from.

How does extending work?

  • A template will extend a parent
  • This parent template will be used
  • Parent templates can 'yeild' content blocks to templates which are extending them
  • These blocks can have defaults
  • You can also modify variables set in the extended template
  • Example!

The Good!

  • In Drupal extending will probably most often be used to define a flexible default, ie node.html.twig which more specific templates may extend, ie node--page.html.twig
  • Can be great for keeping code dry
  • This doesn't mean you should always extend, it's not always appropriate

The Not-So-Good!

  • In the rest of the PHP world, the concept of extending templates is often used to determine page layouts
  • This only makes sense in a bottom up type of rendering system, ie - a router hits the template to render, and you go up the ladder building the page
  • Drupal is a top down system
  • Extension will be limited to keeping code DRY and modular as opposed to determining structure

Filters!

  • These allow you to directly modify content you are rendering in your template file
    • upper, lower, capitalize, escape
  • The PHP logic hides in the filter and is implemented in the twig template
  • Filters can take parameters
{{ 'I am a string!'|upper }} ... I AM A STRING!

{{ 'Look, ma, no spaces!|squish }} ... Look,ma,nospaces!

{{ 'Still no spaces, amazing!'|remove_char(' ') }} ... Stillnospaces,amazing!

What is the role of filters?

  • In Drupal, this can be a bit vague for a few reasons
  • Drupal handles a lot of layout and display features via field formatters
  • A filter can be used in a custom field formatter for example, or directly in a node template.
  • In Twig, filters generally take a string
  • In Drupal, you only have a string if you drill down into the render array to find it
  • Examples!

Extending Twig

  • Twig is easy to extend in Drupal by creating a simple module
  • Standard info file
# e3_twig/e3_twig.info.yml

name: E3 Twig Extensions
description: Define some reusable Twig extension
package: Custom

type: module
core: 8.x

Services File

  • Defines the new class that will provide the functionality
# e3_twig/e3_twig.services.yml

services:
  e3_twig.my_twig_extension:
    class: Drupal\e3_twig\TwigExtension\MyTwigExtension
    tags:
      - { name: twig.extension }

New Class

<?php
namespace Drupal\e3_twig\TwigExtension;
class MyTwigExtension extends \Twig_Extension {
    /* Generates a list of all Twig filters that this extension defines. */
    public function getFilters() {
      return array(
        'leet' => new \Twig_Filter_Function(array($this, 'makeLeet')),
        'dasherize' => new \Twig_Filter_function(array($this, 'dasherize')),
      );
    }
    /* Gets a unique identifier for this Twig extension. */
    public function getName() {
      return 'e3_twig.my_twig_extension';
    }
    /* Makes passed string 1337 */
    public static function makeLeet($string) {
      $leet_string = str_replace(array('e', 'E', 'a', 'A', 'o', 'O', 'l', 'L', 't', 'T'), array('3', '3', '4', '4', '0', '0', '1', '1', '7', '7'), $string);
      return $leet_string;
    }
    /* Dasherizes passed string */
    public static function dasherize($string) {
      $string = str_replace(' ', '-', $string);
      $string = strtolower($string);
      return preg_replace('/[^A-Za-z0-9\-]/', '', $string);
    }
}

Custom Functions

  • Can be defined in the same module
  • Use getFunctions instead of getFilters
  • Functions are things like, max, min, random

Macros

  • Prebuilt shortcuts for chunks of code given certain passed parameters
  • Like, Live Templates in PHP storm

Lots of Opportunity

  • For internal collaboration
  • To reuse code snippets within a project
  • To reuse code snippets across projects
  • Create a larger set of available tools for themekit

Drupal and Twig

By Anthony Simone

Drupal and Twig

Using twig in Drupal 8

  • 916