Die Verwendung der Theme-Schicht
Siehe auch: Theme Handbuch (Drupal 6) und Theming guide (en).
Drupal Module haben die Fähigkeit, ihre Ausgabe für die Verwendung auf individuellen Seiten überschreiben zu lassen. Diese Fähigkeit wird auch "theming" genannt.
Um für die Theme-Schicht verwendbar zu sein, muss das Modul dementsprechend richtig geschrieben sein. Dies tut man am Besten, indem man die Logik soweit wie möglich von der Darstellung trennt.
Dies wird erreicht, indem die Module soviel wie möglich ihrer Arbeit auf den Daten direkt ausführen und dann diese Daten an die Präsentationsschicht übergeben. Module stellen dann Standardimplementierungen bereit, die die Basisausgabe erstellen. Diese Ausgabe dient dann Themes, die eine andere Ausgabe bevorzugen, als Basis.
Erledigt wird das von der theme()
Funktion. Jeder Teil der Ausgabe, der mittels der theme()
zur Anzeige vorbereitet wird, wird als "theme hook" bezeichnet. Es gibt zwei Wege, die Standardimplementierung bereitzustellen. Der Leichtere, jedoch weniger empfohlene Weg ist, eine Funktion zur Verfügung zu stellen. Der empfohlene Weg ist, ein Template und eine entsprechende proprocessor Funktion zu erstellen. Nachfolgend wird auf den zweiten Weg näher eingegangen.
Idealerweise generiert Dein Modul nicht eine einzige Zeile HTML-Ausgabe, die nicht in einer theme Implementierung enthalten ist. In der Realität sind Administrationsseiten und sehr kleine Elemente nicht themebar, jedoch erkennt man ein gut geschriebenes Modul an der leichten Überschreibbarkeit von angezeigten Daten.
Theme hooks registrieren
Um einen theme hook verwenden zu können, muss Dein Modul diesen erst registrieren. Dies ist eine Änderung, die mit Drupal 6 eingeführt wurde. Die Registrierung wurde notwendig, da die Zeit die benötigt wurde, um automatisch alternative Implementierungen zu ermitteln, ziemlich hoch ist. Durch die Registrierung wird diese Suche nur ausgeführt, wenn sie wirkich notwendig ist; das Ergebnis ist dann jedoch immer verfügbar (jedenfalls bis die theme registry geleert wird).
Im Endergebnis ist die Themeschicht ein wenig schneller geworden, obwohl sie jetzt mehr Arbeit verrichtet.
Die hook_theme
(hook API Dokumentation für Details zu hooks) Deines Moduls gibt eine Liste mit allen theme hooks, die Dein Modul implementiert, zurück. Eine einfache Implementierung von hook_theme()
könnte wie folgt aussehen:
<?php
function forum_theme() {
return array(
'forums' => array(
'template' => 'forums',
'arguments' => array('forums' => NULL, 'topics' => NULL, 'parents' => NULL, 'tid' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL),
),
);
}
?>
Diese Registrierung sagt uns, dass ein theme hook namens forums
implementiert wurde. Die Standard-Implementierung ist ein Template. Da es verschiedene Template-Engines gibt, verwendet die Registrierung keine Dateiendung (obwohl der Drupal Kern nur PHPTemplate für Module und somit die Endung '.tpl.php' unterstützt).
Es gibt noch weitere Optionen, die man hier setzen kann, jedoch sind diese Beiden bei Weitem am Wichtigsten. Mehr Informationen zu den Optionen bietet die Dokumentation von hook_theme.
Standard-Templates implementieren
Wenn die Implementierung als Template vorgenommen wurde, ist die .tpl.php Datei erforderlich. Sie sollte im gleichen Verzeichnis wie die .module Datei liegen (obwohl die Angabe von 'path' verwendet werden kann, um die Datei in ein anderes Verzeichnis zu legen).
Templates sollten hauptsächlich pures HTML enthalten, jedoch gibt es ein paar Funktionen, die im Template verwendet werden sollten. Zuerst wäre da die Funktion t(). Module sollten immer darauf achten, übersetzbar zu sein; für Templates gilt dasselbe. Leute, die Themes erstellen benötigen den blanken Text, um damit arbeiten zu können und Übersetzer erwarten, dass sämtlicher Text durch die Funktion t()
geschleust wurde. Aus diesen Gründen wird die Verwendung von t()
in Templates zwingend empfohlen.
Eine weitere in Templates zu verwendende Funktion ist format_date(). Da diese Funktion (wirklich) eine Funktion zur Darstellung von Daten ist, ist die Darstellungsschicht der richtige Ort, sie zu verwenden.
Jedoch scheint die Funktion ein wenig obskur und schwierig für Leute, die mit PHP nicht wirklich vertraut sind. Davon mal abgesehen sollte sie in Templates verwendet werden.
Bei anderen Funktionen bedarf es einer gründlichen Abwägung, ob sie wirklich in der Präsentationsschicht benötigt werden. Wenn nicht, können sie genauso gut in der preprocessor Schicht verwendet werden. Alle Templates können eine optionale preprocess Funktion namens template_preprocess_HOOK
haben. Für unseren forums
theme hook wäre die entsprechende preprocess Funktion beispielsweise template_preprocess_forums
.
Der Sinn der preprocess Funktion ist es, sämtliche Logik abzuarbeiten, die ausgeführt werden muss, um die Daten anzeigbar zu machen. Weiterhin bereinigt die Funktion die Daten, so dass deren Ausgabe sicher ist. Es ist äussert wichtig, dass die Ausgaben sicher sind und nicht etwa XSS (Cross Site Scripting) Schwachstellen enthalten. Und da die angezeigten Daten oftmals direkt von Nutzer eingegeben wurden, müssen diese Daten vor der Ausgabe bereinigt werden.
Da wir annehmen, dass Themer nicht notwendigerweise auch Entwickler sind, müssen wir auch annehmen, dass sie die Wege zur Bereinigung nicht vollkommen verstehen. Dies ist jedoch nicht so schlimm, da wir die Daten ja bereits in der preprocess Funktion bereinigen können, indem wir check_plain, check_markup, filter_xss_admin oder andere Funktionen zum Bereinigen aufrufen.
Hier ist ein einfaches Beispiel:
<?php
function template_preprocess_poll_bar(&$variables) {
if ($variables['block']) {
$variables['template_files'][] = 'poll-bar-block';
}
$variables['title'] = check_plain($variables['title']);
$variables['percentage'] = round($variables['votes'] * 100 / max($variables['total_votes'], 1));
}
?>
Zuerst, beachte dass die preprocessor Funktion eine Referenz auf ein Array mit Variablen als Argument hat. Dieses Array wird mit den (über die theme()
Funktion gesendeten und vom Bereich 'arguments' in der hook Registrierung benannten) Argumenten gesetzt. Da es eine Referenz ist, reicht es das Array einfach zu modifizieren, um die Änderungen an das begleitende Template zu übergeben.
Das obige Beispiel illustriert drei wichtige Konzepte:
- Das Feld 'title' ist unsicher, da es von Nutzern eingegeben wird. Der Inhalt wird durch
check_plain()
geleitet, so dass ihn das Template ohne Bedenken ausgeben kann. - Der theme hook erhält die Gesamtzahl an Stimmen (votes) und die Anzahl der Stimmen für diesen speziellen Eintrag, das Template soll jedoch eine Prozentangabe ausgeben. Diese Arbeit sollte jedoch nicht in einem Template getan werden. Stattdessen wird die Berechnung hier ausgeführt. Die Variablen existieren jedoch weiterhin; ein Themer, der die Funktion überschreibt, kann also ohne Probleme etwas anderes als die Prozentangabe ausgeben.
- Um alternative Templates zu nutzern kann die spezielle Variable 'template_first' kann verwendet werden. Die Variable ist ein Array von Template Dateien und arbeitet nach dem LiFo (Last in, First out) Prinzip. Das bedeutet, das zuletzt zum Array hinzugefügte Template wird zuerst verwendet. Sollte dieses Template nicht existieren, wird das Nächste in der Liste verwendet. Die Funktion kann bei der Verwenung von verschiedenen Templates sehr hilfreich sein, jedoch ist es nur auf Templates beschränkt.
Das Theme Developer module (ein Teil des Projekts Devel) beinhaltet ein Template log, mit dem im unteren Bereich jeder Seite alle Template Dateien, die zur Darstellung der Seite verwendet sein könnten, aufgelistet werden. Dies kann bei der Erstellung von Modulen, jedoch insbesondere auch beim Theming der Seite nützlich sein. ferner könnte auch der "Themer information popup" von Nutzen sein.
Ein kurzer Hinweis: Template Dateien sollten mit Bindestrichen anstelle von Unterstrichen benannt werden. Wenn der theme hook 'forum_list' heisst, sollte die Template Datei 'forum-list.tpl.php' genannt werden.
Theme Funktionen erstellen
Drupal erlaubt die Verwendung von Funktionen für Standard Theme Implementierungen. Dies ist ein wenig schneller, da nicht nach alternativen Templates gesucht werden muss (da es ja keine gibt).
Der nachteil dabei ist, dass es in diesem Fall keine preprocess Funktion gibt. Dies macht es für einen Themer schwieriger, diese theme Funktionen zu überschreiben (es sei denn, sie sind ebenfalls Entwickler). Das macht sich besonders starkk bemerkbar, wenn die theme Funktion mehr Programmlogik als Präsentationslogik enthält. Um dieses Risiko zu minimieren, ist es generell immer besser, Templates zu verwenden.
Die Namen von theme Funktionen beginnen mit 'theme_', gefolgt vom Namen des hooks. Die Argumente, die an theme('hook')
übergeben werden, werden - ohne jegliche Veränderung - an die theme Funktion weitergereicht. Die in der hook Registrierung gesetzten Standardwerte sind hier nicht verfügbar, sie müssen als ganz gewöhnliche Standardwerte für Argumente übergeben werden.
<?php
function theme_forums($topics = NULL, $parents = NULL, $tid = NULL, $sortby = NULL, $forum_per_page = NULL) {
...
return $output;
}
?>
Dynamisches Theming
Zusätzlich zur Möglichkeit, alternative Templates in der preprocess Funktion anzugeben, können dynamische theme Implementierungen auch unter Verwendung von Platzhaltern erstellt werden. Dieser Prozess beinhaltet zwei Schritte.
Zuerst - in hook_theme()
- wird ein Muster ("pattern") spezifiziert. Muster sind einfache reguläre Ausdrücke. ^
(Anfang der Zeile) wird von vornherein angenommen, $
(Ende der Zeile) jedoch nicht. Um den dynamischen Teil des Musters hervorzuheben, wird meistens ein doppelter Unterstrich verwendet; das ist zwar nicht erforderlich, wird jedoch dringend empfohlen.
Zweitens (beim Aufruf der theme()
Funktion) kann anstelle eines Strings im ersten Argument ein Array übergeben werden. Dieses Array ist ähnlich zu dem 'template_files' oben, jedoch arbeitet es nach dem FiFo (First in, First out) Prinzip, so dass das zuerst eingefügte Element verwendet wird.
Ein praktisches Beispiel: das Modul Views würde gern jeden View über dessen Namen themen lassen. Bei der Registrierung registriert sich der hook 'views_view' also mit dem Muster 'views_view__'. Beim themen eines Views ruft das Modul also Folgendes auf:
$output = theme(array("views_view__$view->name", 'views_view'), $view);
Views wird ebenfalls einen Standard view für 'views_view' implementieren. Wenn ein Theme 'views_view__foo' registriert und Views einen View namens 'foo' themed, wird diese spezielle überschriebene Funktion aktiviert und anstelle der Standardimplementierung verwendet. Im Gegensatz zu Variable 'template_files' in der preprocess Funktion funktioniert dies sowohl mit der theme Funktion, als auch mit Templates.
theme('table') und theme('item_list')
Drupal stellt ein paar Hilfsfunktionen zum einfachen Erzeugen von komplexen HTML Konstrukten zur Verfügung. Diese sind sehr hilfreiche Features, und mit deren Verwendung ist es ein Leichtes, gleich aussehende Tabellen und Listen zu generieren. Der Nachteil ist, dass ein Themer nicht einfach auf diese Funktionen zugreifen kann. Stattdessen fügen sie Quelltext, der eigentlich in die Präsentationsschicht gehört, in die Logikschicht ein, so dass nur Themer mit erweiterten Fähigkeiten alles mit den Funktionen machen können.
Bei der Erstellung von Ausgaben, die wahrscheinlich abgeändert werden, sollte auf die Verwendung dieser Hilfsfunktionen verzichtet und Tabellen bzw. Listen mit richtigen HTML erzeugt werden. Die themes des Forum Moduls bieten perfekte Beispiele, wie man dies tun kann und trotzdem konsistenten HTML Quelltext erzeugen kann.
- Anmelden oder Registrieren um Kommentare zu schreiben
Neue Kommentare
vor 18 Stunden 43 Minuten
vor 18 Stunden 52 Minuten
vor 19 Stunden 6 Minuten
vor 1 Tag 3 Stunden
vor 1 Tag 3 Stunden
vor 1 Tag 4 Stunden
vor 1 Tag 6 Stunden
vor 1 Tag 6 Stunden
vor 2 Tagen 5 Stunden
vor 2 Tagen 6 Stunden