Eine Einführung in die Smarty Template-Engine: Schichtentrennung leicht gemacht
Template-Engines erlauben es, die Applikationslogik – also die eigentliche PHP-Programmierung – vom Design – sprich von der HTML-Ausgabe – strikt zu trennen. Sie bieten jedoch noch weitere Vorteile, wie einen schnelleren Seitenaufbau durch Caching oder – im Falle von Smarty – eine einfache und trotzdem mächtige Erweiterbarkeit durch eine durchdachte Plugin-Architektur.
Anwendungslogik vs. Präsentationslogik
Smarty versteht sich selbst als „kompilierende Template-Engine“. Dies bedeutet, dass auch im (HTML-)Template logische Konstrukte wie if-Blöcke oder sich wiederholende Abschnitte vorkommen können. Damit verstößt man aber nicht zwingend gegen die eigentliche Idee der Trennung von Logik und Design. Es bleibt Aufgabe der Entwickler, die Applikationslogik von einer Präsentationslogik zu unterscheiden. Als Beispiel werden wir in diesem kurzen Tutorial mit Smarty das Frontend eines klassischen Weblogs bauen. Wenn wir uns die „Detailansicht“ eines Blogeintrags vor Augen führen, so stehen unterhalb des eigentlichen Blog-Eintrags die zugehörigen Leserkommentare. Diese Kommentare sind vom Design und strukturell-semantischen Aufbau identisch und unterscheiden sich nur in den jeweiligen Inhalten (Autor, E-Mail, Kommentar). Es ist also sinnvoll, nur einen einzigen Kommentar in HTML und CSS zu gestalten und diesen dann entsprechend der Anzahl der Kommentare zu wiederholen. Wir werden später sehen, dass Smarty dies über eine foreach-Schleife im HTML-Template erledigt. Es handelt sich hier also um eine Präsentationslogik.
Vorglühen
Für die Gestaltung unseres Weblogs haben wir bereits ein komplett in (X)HTML und CSS gebautes Layout vorliegen, dass die Ansicht eines Blogeintrags inklusive Kommentaren darstellt.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>Mein kleines Weblog mit Smarty</title> <link rel="stylesheet" xhref="layout.css" /> </head> <body> <h1>Mein Weblog</h1> <div class="blog-entry"> <h2>Lorem ipsum dolor sit amet</h2> <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam aliquet ipsum varius dolor. Nam tempus metus facilisis nisi.</p> <p class="author">geschrieben von Michael am 16.11.2007</p> </div> <h3>Kommentare:</h3> <div class="blog-comments"> <p>Geschrieben von: John Doe</p> <p>E-Mail <a xhref="mailto:john@doe.com">John@doe.com</a></p> <p>Duis pede. Nulla id urna. Vestibulum diam. Aliquam in erat.</p> </div> </body> </html>
Listing 1
Die jeweils aktuellen Klassen der Smarty-Engine stehen auf der offiziellen Website des Projekts [1] bereit. Die Dateien des Template nennen wir „blog-detail.html“ und
speichern sie im Ordner „templates“ unserer Anwendung. Zusätzlich muss
der Ordner „templates_c“ angelegt und mit Schreibrechten versehen
werden. Smarty wird dort später die Templates kompilieren und
abspeichern, sodass nicht bei jedem Aufruf das Template erneut
übersetzt werden muss.
Das Template vorbereiten
Mit Hilfe von Smarty möchten wir das Template nun mit einer Logik versehen. Dazu müssen wir zunächst das Template entsprechend vorbereiten. Wir markieren bestimmte Bereiche als Variablen, die später durch echte Daten aus der Datenbank ersetzt werden. Solche Bereiche sind zum Beispiel die Überschrift, der Autor und natürlich der Blog-Eintrag selbst.
Innerhalb von Smarty werden Variablen durch geschweifte Klammern gefolgt von einem Dollar-Zeichen dargestellt. Wir überlegen uns also, welche Bereiche im Template dynamisch durch Inhalte einer Datenbank ersetzt werden sollen.
<div class="blog-entry"> <h2>{$titel}</h2> <p>{$text}</p> <p class="author">geschrieben von {$autor} am {$timestamp|date_format:"%d. %m. %Y"}</p> </div>
Listing 2
Auf den sogenannten „Modifier“ date_format der „timestamp“-Variable komme ich später noch zu sprechen.
Wir legen nun, sofern nicht schon geschehen, entsprechend unseres Dateilayouts die index.php an und konfigurieren dort die Template-Engine.
<?php require_once('Smarty.class.php'); $template = new Smarty; $template->assign('titel','Mein erster Testeintrag'); $template->assign('text','Das hier ist mehr oder weniger sinnvoller Text'); $template->assign('autor','Michael'); $template->assign('timestamp',time()); $template->display('blog.html'); ?>
Listing 3
Zunächst laden wir mit „require_once()“ die benötigte Smarty-Bibliothek.
Danach legen wir eine neue Instanz der Klasse Smarty mit dem Namen
„$template“ an. Mit der Methode „assign“ unseres Objektes „template“
können wir dem HTML-Template nun die vorher definierten Variablen
zuweisen. So belegen wir hier die Variable {$titel}, die
wir im Template definiert haben, mit dem Text „Mein erster
Testeintrag“. Anhand der Methode „display“ bestimmen wir, welches
Template Smarty anzeigen soll. Alle zuvor über „assign“ zugewiesenen
Variablen werden automatisch ersetzt. Rufen wir jetzt die index.php im
Browser auf, sehen wir die Ergebnisse unserer Arbeit.
Anstatt die Werte über „assign“ statisch festzulegen, können wir nun Werte aus einer Datenbank zuweisen. Hier gehen wir davon aus, dass die entsprechende Datenbank mit Tabellen bereits vorhanden ist.
<?php /** Datenbankverbindung und Smarty-Instanziierung */ $sql = mysql_query("SELECT title,text,author,tstamp FROM blog WHERE id = 1"); $result = mysql_fetch_array($sql); $template->assign('titel',$result['title']); $template->assign('text',$result['text']); $template->assign('autor',$result['author']); $template->assign('timestamp',$result['tstamp']); $template->display('blog-detail.html'); ?>
Listing 4
Zaubern mit Smarty
Was nun noch fehlt, ist die Darstellung der Kommentare. Bis jetzt haben wir in unserem HTML-Layout nur einen Kommentar angelegt und gestaltet. Jetzt kommt die zuvor erwähnte Präsentationslogik zum Tragen. Wir definieren den Bereich um einen Kommentar als wiederholbar.
<h3>Kommentare:</h3> {foreach key=id item=comment from=$comments} <div class="blog-comments"> <p>Geschrieben von: {$comment.author}</p> <p>E-Mail {mailto address=$comment.mail}</p> <p>{$comment.text}</p> </div> {foreachelse} <p>Bisher keine Kommentare</p> {/foreach}
Listing 5
Der Bereich innerhalb der {foreach}-Anweisung wird für jeden Eintrag in dem aus der Datenbank ausgelesenen Array „comments“ wiederholt. Sind keine Einträge vorhanden, springt Smarty in den foreachelse-Block und zeigt diesen an. Mit der zunächst etwas ungewohnt erscheinenden Punkt-Syntax innerhalb einer Smarty-Variable greifen wir auf ein Feld des assoziativen Arrays „$comment“ zu. Unsere PHP-Datei erweitern wir nun um die Zuweisung des Arrays „$comments“.
<?php /** vorhergegangene assign() Funktionen und Instanziierung */ $sql = mysql_query("SELECT id,author,text,mail FROM comments WHERE blog_id = 1"); while($row = mysql_fetch_array($sql)) { $sqlComments[] = $row; } $template->assign('comments',$sqlComments); $template->display('blog-detail.html'); ?>
Listing 6
In der Ausgabe sehen wir jetzt ein Beispiel mit zwei Kommentaren.
<h3>Kommentare:</h3> <div class="blog-comments"> <p>Geschrieben von: Michi</p> <p>E-Mail <a xhref="mailto:koenig@bananenrepublik.de">koenig@bananenrepublik.de</a> </p> <p>Ein toller Eintrag!</p> </div> <div class="blog-comments"> <p>Geschrieben von: John Doe</p> <p>E-Mail <a xhref="mailto:john@doe.com">john@doe.com</a> </p> <p>Ich bin gegen ungeschütztes Mandarinenschälen in der Öffentlichkeit.</p> </div>
Listing 7
Das Tor in eine andere Welt
Smarty kann noch wesentlich mehr. So kann man zum Beispiel mit der „Cycle“-Funktion in wiederholenden Blöcken alternierende Ausgaben (oder auch CSS-Klassen) definieren oder durch sogenannte Modifier-Variablen im Template verändern. Durch den Modifier „date_format“, den wir in Listing 2 gesehen haben, lässt sich ein Unix-Timestamp in jedes gewünschte Format bringen. Die Funktionen sind im guten und umfangreichen Smarty-Manual [2] nachzulesen, das auch auf Deutsch vorliegt.