Drupal 10 : Twig et les thèmes

Au revoir PHPTemplate, bonjour Twig. Mais ça n’est pas tout !

Cet article a été initialement rédigé pour Drupal 8 mais son contenu est toujours d'actualité pour Drupal 9 et Drupal 10.

N'hésitez pas à nous contacter ou à vous inscrire à notre formation «Drupal pour les développeurs et développeuses» pour en savoir plus !

Au revoir PHPTemplate, bonjour Twig. Mais ça n’est pas tout ! Le responsive étant beaucoup plus présent dans cette nouvelle version de Drupal, les thèmes de base Bartik et Seven se basent sur un nouveau thème, Classy, qui a vocation à fournir un balisage et des classes de base pour la structure et la mise en page de votre site.
Si vous voulez démarrer un nouveau thème vierge, ignorez
Classy et vous ne serez pas encombré par les classes non désirées.

A l’instar des modules, les thèmes custom seront à créer dans un dossier themes à la racine de l’installation de Drupal (Ou dans sites/**/themes ou dans profiles/**/themes)

Depuis Drupal 10, Bartik a officiellement cédé sa place à Olivero et Seven à Claro. De plus, depuis Drupal 9, les thèmes par défaut fournis par le cœur ne s'appuient plus ni sur Classy ni sur Stable qui ont été dépréciés puis supprimés de Drupal 10 au profit d'un nouveau système de génération à partir de Starterkits (EN).

Ce qu’apporte l’utilisation de Twig

PHPTemplate a été retiré du cœur mais il sera sans doute rapidement disponible en module contribué bien qu’il soit recommandé de ne plus s’en servir pour des raisons de sécurité. Les bon vieux .tpl.php sont maintenant remplacés par des .html.twig.

Même s’il est toujours possible de créer une entrée de thème dont le rendu est généré par une fonction, la méthode par défaut, utilisée dans tout le cœur, est d’utiliser un template Twig.

Les fichiers de template sont de facto attendus dans un dossier templates/, plus besoin de spécifier le chemin vers le fichier de template depuis votre hook_theme().

Un fichier de template ressemble à cela :

# maintenance-task-list.html.twig
<h2 class="visually-hidden">{{ 'Installation tasks'|t }}</h2>
<ol class="task-list">
{% for task in tasks %}
 <li{{ task.attributes }}>
  {{ task.item }}
  {% if task.status %}<span class="visually-hidden"> ({{ task.status }})</span>{% endif %}
 </li>
{% endfor %}
</ol>

Les avantages de Twig

  • C’est un langage interprété, cela apporte plus de sécurité vis à vis de ce qui peut être fait par les thémeurs. Fini les requêtes SQL au milieu du template.
  • Auto escape par défaut : toute chaîne rendue est filtrée (de la même manière que check_plain() dans Drupal 7).
  • La séparation des responsabilité est plus claire, il n’est plus possible d’écrire de PHP dans les fichiers.
  • Le débug est plus simple, Twig fourni des fonctions qui permettent de trouver les variables et d’identifier les fichiers de template utilisés. Par exemple: la fonction dump().
  • C’est un langage “autonome”, c’est un projet qui mène sa propre vie, vous pouvez lire la documentation dédiée et le réutiliser sur des projets qui utilisent une autre technologie que Drupal.

Pour activer le débug de Twig, modifiez le fichier services.yml modifiez la valeur du paramètre debug de twig à true.

# services.yml
parameters:
  twig.config:
    debug: true

Vous pourrez ainsi voir le nom du fichier de template utilisé lors du rendu du contenu ainsi que les suggestions de noms de fichier pour surcharger le template. Il est également possible de désactiver le cache de Twig afin de le forcer à recompiler les templates à chaque fois qu’ils sont modifiés ou à chaque fois qu’ils sont demandés en modifiant respectivement les valeurs auto_reload ou cache du fichier services.yml.

Fonctionnalités courantes

Le moteur de Twig est très performant et extensible. Même s’il ne permet par l’utilisation directe de PHP, il remplace de manière sécuritaire et parfois enrichie les principales structures de contrôle et la gestion de variables. Afin de permettre aux thémeurs d’aller plus loin, Twig implémente aussi un système de fonctions, appelées “filtres” qui permettent de modifier une valeur avant de l’afficher.

Afin de se distinguer pleinement de PHP et HTML, la syntaxe de Twig se base sur un balisage par des accolades. Un appel de type inline se fera entre des doubles accolades et un appel de type block se fera entre une paire de balises délimitées par une accolade et un symbole de pourcentage. À noter que, comme en HTML, un appel de type block peut contenir d’autres appels de type inline. Il est aussi possible d’écrire des commentaires en les encadrant d’une accolade et d’un dièse.

# somewhere.html.twig

{# Exemple of inline call #}
Bienvenue {{ user.firstname }}!

{# Exemple of block call containing inline calls #}
{% if label %}
<span {{ label_attributes }}>{{ label }}</span>
{% endif %}

{# We can have
multi-line comments too! #}

Il est donc également possible d’utiliser un des nombreux filtres du système, l’un de ceux ajoutés par Drupal ou encore d’en créer vous même en étendant la classe TwigExtension. Appliquer un filtre se fait très simplement dans un appel inline en utilisant le symbole pipe “|”. Même si c’est assez peu utilisé dans Drupal, il est également possible de filtrer des blocs de contenu.

# somewhere.html.twig

{%  set label = 'My <strong>field</strong>' %}

<h1>{{ label|striptags }}</h1>
{# Outputs <h1>My field</h1> #}

{{ 'Translate this'|t }}
{# Outputs the translation of 'Translate this' in the current language #}

{% filter upper %}{% trans %}Enable {{ view.name }}{% endtrans %}{% endfilter %}
{# Outputs the translation of 'Enable @view.name' in the current language and
replaces @view.name then change the result to uppercase #}

Outre toutes les structures de contrôle de base permettant de gérer conditions et boucles, Twig offre également de très nombreuses autres possibilités comme l’inclusion ou l’héritage de templates.

À noter qu'un thème d'exemple existe pour mettre en avant les possilités de Twig dans un contexte "live", il s'agit du thème Pistachio. Il n'a pas vocation à être utilisé en production mais est là à titre d'exemple.

Créer un hook_theme

Peu de choses ont changé en ce qui concerne les Hooks de thème.

On les déclare toujours via le hook_theme() qui garde à peu près les mêmes clefs que dans Drupal 7.

# happy_alexandrie.module

/**
 * Implements hook_theme().
 */
function happy_alexandrie_theme() {
  $theme = [];

  $theme['happy_cover'] = [
    'variables' => ['cover_src' => '', 'cover_title' => ''],
  ];

  return $theme;
}

Par défaut, les fichiers templates se placent dans le répertoire templates à la racine du module. Il faut toujours remplacer les undescore (_) par des tiret (-) et l’extension du fichier est maintenant .html.twig. Sachez que les variables sont affichées en les mettant entre double accolade {{ variable }}.

# templates/happy-cover.html.twig
<p>
  <img src="{{ cover_src }}" alt="Cover for {{ cover_title }}" />
</p>

Une fois déclaré, le Hook de thème peut être utilisé dans un render array. Il suffit d’en indiquer le nom dans la clef #theme de votre render array et de passer vos diverses variables en préfixant leur nom d’un dièse. Toutes variables qui ne seraient pas présente dans le render array héritera de la valeur par défaut définie dans le hook_theme().

# RemoteCover.php

  /**
   * This method is the wrapper for each field value.
   */
  public function viewElements(FieldItemListInterface $items, $langcode = NULL) {
    $elements = array();
    foreach ($items as $delta => $item) {
      if ($item->value) {
        // Part calling a theme function.
        $elements[$delta] = array(
          '#theme' => 'happy_cover',
          '#cover_url' => $item->value,
          '#cover_title' => $items->getEntity()->label(),
        );
      }
    }
    return $elements;
  }

 

Commentaires

Andrzej Mardi 15 mai 2018 - 16:55
Bonjour, Pourriez-vous svp m'indiquer l'emplacement du fichier "services.yml" ? "Pour activer le débug de Twig, modifiez le fichier services.yml" Merci dr'avance et merci pour votre (bon) travail Andrzej
Anonyme Mardi 15 mai 2018 - 18:25
Bonjour, le fichier d'exemple default.services.yml est disponible dans le dossier sites/default, il suffit de le dupliquer et de le renommer en services.yml.

Votre commentaire

Le contenu de ce champ sera maintenu privé et ne sera pas affiché publiquement.
Votre adresse servira à afficher un Gravatar et à vous notifier des réponses. Votre commentaire sera anonymisé si ce billet est dépublié pendant plus de 3 mois.
Pour lutter contre le spam notre système enregistre votre adresse IP et votre adresse e-mail si vous la partagez.
Nous vous invitons à consulter notre politique de confidentialité pour comprendre les traitements faits de ces données et comment les rectifier.

À propos de Julien

Co-fondateur - Scrum master & Expert technique

Utilisateur de Drupal depuis 2008, j’ai fait mes armes comme développeur chez Commerce Guys puis me suis mis à encadrer les nouveaux arrivants avant de donner des formations, participer aux avant ventes et accompagner les équipes au passage à Scrum.

Je suis impliqué dans la communauté française de Drupal depuis 2009, j’ai été tour à tour président puis vice-président de l’association Drupal France et francophonie entre 2011 et 2013.