Theming in Drupal 8 - alles neu mit Twig? (Teil 2)
Nachdem der erste Teil der Blogpostreihe eher allgemein auf Twig eingegangen ist, soll im zweiten Teil der Syntax anhand von Codebeispielen näher erklärt werden. Um die Unterschiede besser aufzuzeigen, stelle ich im Blogpost die uns bekannte Syntax direkt in den Vergleich zur neuen Twig-Syntax. Alle hier gezeigten Beispiele basieren auf dem aktuellen Entwicklungsstand der Drupal 8 Twig-Sandbox.
Der Themer sollte sich im Normalfall eigentlich nur noch um die Ausgabe vordefinierten Variablen (Platzhalter) oder einfacher Kontrollstrukturen (if-Abfragen oder for-Schleifen, die bspw. in Listen verwendet werden) kümmern müssen. Komplexere eigene Logik sollte man nicht in Templates hinterlegen - hier hat sich sicherlich jeder mal ausgetobt, um im Template 'eben mal schnell' noch einen View zu laden oder einzelne Felder benutzerdefiniert auszugeben. Dies führte am Ende meist zu recht komplexen und unübersichtlichen Templates, die nach einer gewissen Zeit eher schlecht wartbar wurden. Dies lag vor allem an der Tatsache, dass in PHP alle Möglichkeiten offenstanden und diese dann auch ausgiebig genutzt wurden.
Ausgabe von Variablen
Beispiel für die Ausgabe von Variablen und einer einfachen if-Anweisung in PHPTemplate:
- <div id="taxonomy-term-<?php print $term->tid; ?>">
- <?php if (!$page): ?>
- <h2><?php print $term_name; ?></h2>
- <?php endif; ?>
- <div class="content">
- <?php print render($content); ?>
- </div>
- </div>
Beispiel für die Ausgabe von Variablen und einer einfachen if-Anweisung in Twig:
Im gezeigten Beispiel sieht man schon die Unterschiede - statt der PHP-Funktionen print bzw. der Drupal eigenen render-Funktion wird in Zukunft zur Ausgabe nur noch {{ name_der_variable }} verwendet. Auch der Zugriff auf Array bzw. Objekt-Konstrukte innerhalb der Templates wurde vereinfacht. Hier setzt man nun auf eine konsistente Syntax, die nun - wie im Beispiel zu sehen - auf eine Punkt-Syntax setzt. Dabei spielt es keine Rolle, ob man auf Arrayelemente oder Objektelemente zugreifen möchte.
Beispiel aus einem Views-Exposed-Filter in PHPTemplate:
- <div class="custom-wrapper">
- <label for="<?php print $widgets['filter-myfield']->id; ?>">
- <?php print $widgets['filter-myfield']->label ?>
- </label>
- <?php print $widgets['filter-myfield']->widget ?>
- </div>
Beispiel aus einem Views-Exposed-Filter in Twig:
- <div class="custom-wrapper">
- <label for="{{ widgets.filter-myfield.id }}">{{ widgets.filter-myfield.label }}</label>
- {{ widgets.filter-myfield.widget }}
- </div>
Kontrollstrukturen
Neben der oben schon gezeigten if-Abfrage, gibt es noch die Möglichkeit zur Nutzung von for-Schleifen in den Templates innerhalb von {% %} Zeichen.
Beispiel für for-Schleife in PHPTemplate
- <?php foreach ($book_menus as $book_id => $menu): ?>
- <div id="book-block-menu-<?php print $book_id; ?>" class="book-block-menu">
- <?php print render($menu); ?>
- </div>
- <?php endforeach; ?>
Beispiel für for-Schleife in Twig
Wie auch schon in den früheren Drupal-Versionen, sollten wir direkt auf Theme-Ebene vermeiden, zu viel Logik in die Templates zu packen. Hierfür stehen uns weiterhin die preprocess-Funktionen zur Verfügung.Neben der neuen {% %} Syntax im Template sieht man hier auch die Nutzung des neuen nav-Elements aus dem HTML5-Standard, der somit auch in andere Twig-Templates Einzug gehalten hat.
Kommentare in Templates
Für die Dokumentation innerhalb von Templates wird in Twig die {# #}-Syntax verwendet.
Beispiel für Kommentar in PHPTemplate (phpdoc-Style):
- <?php
- // Hier steht ein einzeiliger Kommentar.
- /*
- * Hier steht ein mehrzeiliger Kommentar
- * mit weiteren Informationen zur Funktionsweise des Templates.
- */
- ?>
Beispiel für Kommentar in Twig:
- {# Hier steht ein einzeiliger Kommentar #}
- {# Hier steht ein mehrzeiliger Kommentar
- mit weiteren Informationen zur Funktionsweise des Templates.
- #}
Wiederverwendbarkeit von Templates über Includes
Obwohl auch in PHPTemplate durch PHP schon die Nutzung der include bzw. include_once möglich gewesen wäre, fand diese nur sehr selten Einsatz in den Templates. In Twig werden Includes nun aber häufiger anzutreffen sein. Ein gutes Beispiel hierfür liefert das image-Modul - hier wird je nach übergebenem Imagestyle ein eigenes Template über die include eingebunden.
- <figure class="{{ item.attributes.class }}"{{ item.attributes }}>
- <figcaption>
- {{ item.caption }}
- </figcaption>
- </figure>
Verwendung von Filtern
Über Filter lässt sich die Ausgabe von Variablen auf Theme-Ebene beeinflussen. Beispielhaft zu den Möglichkeiten von Filtern möchte ich hier die Twig-Alternativen zur t-Funktion und der check_plain-Funktion zeigen.
Übersetzungen in Templates
Beispiel für eine Übersetzung in PHPTemplate:
- <div class="poll">
- <div class="title"><?php print $title ?></div>
- <?php print $results ?>
- <div class="total">
- </div>
- </div>
- <div class="links"><?php print $links; ?></div>
- {{ name }} <small>{{ '(Machine name: @type)'|t({ '@type': type }) }}</small>
- <div class="description">{{ description }}</div>
Sonderzeichen maskieren
Mithilfe von check_plain konnte man in den vorherigen Drupal-Versionen in Text enthaltene Sonderzeichen in HTML umwandeln.
Beispiel in PHPTemplate:
- <?php
- echo check_plain($title);
- ?>
Beispiel in Twig:
Der escape-Filter kann auch über den Alias e verwendet werden und unterstützt über einen Parameter verschiedene escape-Möglichkeiten:
- html: Maskieren von Zeichen im HTML-Kontext
- js: Maskieren von Zeichen im Javascript-Kontext
- css: Maskieren von Zeichen im CSS-Kontext
- url: Maskieren von Zeichen für URI-Kontext oder für URL-Parameter
- html_attr: Maskieren von Zeichen im HTML-Attribut-Kontext
Weitere Informationen über die in Twig zur Verfügung stehenden Filter kann man in der Dokumentation nachlesen.