Über den Sinn von PHP-Template-Engines

Auch ich habe bei meinen Projekten gerne Smarty als Template-Engine verwendet. Smarty schien mir ein elegantes und mächtiges Werkzeug zu sein. Doch ist für die Trennung von Programm und Design wirklich immer ein so umfangreiches Paket notwendig? Smarty kann immerhin locker mal größer sein, als das eigentliche Hauptprogramm.

Die Szene ist sich nicht gerade einig

Beispielhaft zwei recht gegensätzliche Aussagen:

In general, template engines are a "good thing". (Template Engines)

... why template engines are a bad idea. (PHP and Templates)

Also was nun?

Auf jeden Fall ist es gut, Programm-Logik von Design-Logik zu trennen. Eine vollständige Trennung von Programmierung und Design kommt jedoch schnell an seine Grenzen: mit bloßem Einsetzen von Werten in Platzhalter kommt man nicht weit - das Design ist in der Regel immer irgendwie abhängig von den Daten und so werden Kontrollstrukturen wie Schleifen und if/else-Abfragen in den Templates notwendig. So hat sich Smarty beispielsweise bereits zu einer Art Sub-Skritsprache unter PHP entwickelt.

Aber worin soll der Vorteil dieser Schreibweise liegen...

{foreach from=$users item=user}
<tr>
<td>{$user.name}</td>
<td><a href="{$user.homepage}">{$user.homepage}</a></td>
</tr>

{/foreach}

...gegenüber normalem PHP?

<?php foreach($content['users'] as $user): ?>
<tr>
<td><?php echo $user['name'?></td>
<td><a href="<?php echo $user['homepage'?>"><?php echo $user['homepage'?></a></td>
</tr>
<?php endforeach ?>

PHP ist bereits ein Template-System!

Warum das Rad neu erfinden? Bevor der Designer Smarty lernen soll, kann er doch auch gleich die für ihn relevanten PHP-Ausdrücke lernen. Und tatsächlich ist PHP bereits ein Template-System! Es wurde speziell dafür entwickelt, um es in HTML einbinden zu können (siehe PHP Manual - Einleitung: Was ist PHP?).

In speziellen Fällen kann eine eigene Template-Skriptsprache natürlich Sinn machen, etwa wenn Templates aus nicht vertrauenswürdigen Quellen kommen, z.B. wenn User eigene Templates erstellen können. In vielen Fällen kann man sich die Trennung von Programm-Logik und Design-Logik aber auch einfacher machen. Für's erste kann eine einfache, nur wenige Zeilen lange Template-Klasse ausreichen:

Eine simple Template-Klasse

Template.class.php:

<?php
class Template 
 
{
  var 
$content;

  function 
assign($name,$value)
   {
    
$this->content[$name] = $value;
   }

  function 
display($template)
   {
    if(
$this->content$content $this->content;
    include(
$template);
   }
 }
?>

Ein Beispiel-Skript:

<?php
// Template-Klasse einbinden und Template-Instanz erzeugen:
require('Template.class.php');
$template = new Template();

// Daten-Array, könnte z.B. aus einer Datenbank kommen: 
$users[0]['name'] = 'Alex';
$users[0]['homepage'] = 'http://mylittlehomepage.net/';
$users[1]['name'] = 'Tom';
$users[1]['homepage'] = 'http://tom.tom/';
$users[2]['name'] = 'John';
$users[2]['homepage'] = 'http://john.john/';

// Daten dem Template zuwesen:
$template->assign('users',$users);
$template->assign('title','Template test');
$template->assign('headline','Users');

// Template anzeigen:
$template->display('templates/index.tpl.php');
?>

Das Template index.tpl.php:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title><?php echo $content['title'?></title>
</head>
<body>

<h1><?php echo $content['headline'?></h1>

<table>
<tr>
<th>Name</th>
<th>Homepage</th>
</tr>

<?php foreach($content['users'] as $user): ?>
<tr>
<td><?php echo $user['name'?></td>
<td><a href="<?php echo $user['homepage'?>"><?php echo $user['homepage'?></a></td>
</tr>
<?php endforeach ?>

</table> 

</body>
</html>

Noch etwas erweitert

Ein wichtiges Feature von Template-Engines wie Smarty ist der Caching-Mechanismus: beim ersten Aufruf einer Seite wird eine Cache-Datei erstellt und von da an muss nur noch diese gespeicherte Datei ohne weiteres parsen angezeigt werden.
In diesem Skript habe ich obige Template-Klasse um entsprechende Methoden zum Cachen erweitert, die enthaltenen Beispiele verdeutlichen die Funktionsweise:

template_class.zip

Wichtig:

  • es findet hier keine Überprüfung des Alters der Cache-Datei statt, d.h. bei einer Änderung der Daten muss der Cache gelöscht werden ($template->clear_cache() bzw. $template->clear_cache($cache_id) um nur eine bestimmte Datei zu löschen).
  • Das Cache-Verzeichnis muss vom Server beschreibbar sein (CHMOD 777).

Letztendlich...

...haben wir hier auch wieder nur eine weitere Template-Engine erstellt! Doch sie ist sehr einfach geblieben, verwendet keine eigene Syntax und soll uns eigentlich nur disziplinieren, Programm-Logik und Design-Logik auseinander zu halten.

Kommentare

Frank, Freitag, August 01, 2008, 08:49:

Schöne Erklärung und Beispiel. Gefällt mir danke !




(optional, E-Mail-Adresse wird nicht angezeigt)

Seite zuletzt geändert: 30.07.2008, 20:24  

Kontakt | Impressum