Der Interaktionsdesigner – PHP, jQuery und CSS

17. März 2009 (10:00 Uhr)

Cooles Templatesystem für PHP

Ich habe ein paar Stunden in ein Templatesystem für PHP investiert. Vorher habe ich mir natürlich Smarty und viele weitere Lösungen angesehen, aber keiner der Ansätze hat mich so richtig glücklich gestimmt.

Marker, wie in TYPO3 mit "ausgedachten" Zeichen zu umgeben, um anschließend eine neue Syntax für Schleifen und Bedingungen zu lernen, finde ich zu kompliziert. Außerdem habe ich mich hier im Blog schon einmal positiv über die Kurzschreibweisen von PHP geäußert. Da ist es natürlich nur noch ein kleiner Schritt zu einer funktionalen Klasse, welche ein PHP Template mit Inhalt befüllt.

Im folgenden Beitrag stelle ich meine einfach zu nutzende Möglichkeit vor. Es ist mein erster Ansatz Richtung Template und ich freue mich sehr über Kommentare und Verbesserungsvorschläge!

Vorüberlegungen

Viele Projekte münden in eine variable HTML Ansicht. Dabei muss der Kunde keine Templates erstellen, er hat nur viele verschiedene Anforderungen an ein und die selben Daten. Der Entwickler ist fähig, PHP Scripte zu schreiben und hat Spaß daran. Warum also keine PHP Templates?

Es ist natürlich gefährlich, was die Trennung von Layout und Logik angeht und erfordert an dieser Stelle besondere Vorsicht, aber belohnt wird man durch eine sehr schnelle Umsetzung und sehr variable Einsatzmöglichkeiten.

Das Template

Das PHP Template greift auf die Variablen des Objektes zu, über die Variable $this. Ein Beispiel:

<h1><?=$this->title?></h1>
<? if(isset($this->subtitle)): ?><h2><?=$this->subtitle?></h2><? endif; ?>
<p><?=$this->text?></p>
<small><?=$this->footer?></small>
Das ist ein sehr einfaches Template, gespeichert in der Datei einfaches-template.php.

Der Aufruf

Um im PHP Script dieses Template zu benutzen muss nur ein neues Template Objekt erzeugt werden:

$content = array(
  "title" => "Hallo Welt",
  "subtitle" => "Die Welt zu Gast im Template",
  "text" => "Lorem Ipsum usw."
);
include("class.template.0.2.php");
$output = new template("einfaches-template.php", $content);
echo $output;
Wie unschwer zu erkennen ist, macht sich die Template Klasse eine Menge der objektorientierten Programmierweisen zu nutze, wie z.B. die Funktion __toString(), um das geparste Template ausgeben zu können.

Alternativen

Ich habe versucht die Klasse so einfach und logisch wie möglich aufzubauen. So können Daten auch einzeln während der Laufzeit des Programms übergeben werden:

$output = new template("einfaches-template.php");
$output->title = "Hallo Welt 2";
$output->text = "Ich bin auch möglich.";
echo $output;

Automatische Verarbeitung

Um eine automatische Vearbeitung der Marker zu ermöglichen merkt sich die Klasse die angeforderten Schlüssel! Nach dem Parsen kann mit der Funktion $output->keys() ein Array der verwendeten Schlüssel zurückgegeben werden. Dabei akzeptiert die Funktion zwei Parameter: 'set' oder 'unset'. Erweitert man also das zweite Beispiel um eine Zeile:

echo "<hr><pre>".print_r($output->keys(), 1)."</pre>";
erhält man folgende Ausgabe:

Array
(
    [0] => title
    [1] => text
)

Und mit dem Parameter 'unset' dann:

Array
(
    [0] => footer
)

Sehr praktisch für die automatische Information bei der Verwendung von neuen Templates.

Dynamische Erweiterung

Aktuell hatten wir in der Agentur ein Projekt, in dem die Anforderung darin bestand, ein bestimmtes Wort immer kursiv darzustellen. Mit meiner Template Klasse habe ich, wie ich finde, einen sehr eleganten Weg gefunden dies zu realisieren ohne die Aktualisierbarkeit der Klasse zu verlieren. Zum Beispiel das Wort Welt. Der Trick liegt in einer neuen Klasse, welche die Funktion $this->afterParse() überschreibt:

class custom_template extends template {
  function afterParse() {
  [tab]$this->_output = str_replace("Welt", "<i>Welt</i>", $this->_output);
  }  
}
Die einzige Herausforderung besteht darin, die Variable $this->_output zu erkennen und zu bearbeiten. Für das Beispiel oben muss dann nur noch der Aufruf des Templates angepasst werden:
$output = new custom_template("einfaches-template.php");
Und schon ist jedes Auftreten von Welt kursiv!

Funktionen, die überschrieben werden wollen sind:
function afterParse() - aufgerufen nach dem Parsen. Der geparste Inhalt steht in $this->_output.
function beforeParse() - wird aufgerufen bevor das Parsen beginnt. Alle verfügbaren Variablen stehen in $this->_data.
function out($value, $set) - wird aufgerufen wenn ein Platzhalter im Template ersetzt werden soll. In dieser Funktion definiert man, was bei nicht vorhandenen Inhalten ausgegeben werden soll (dann steht $set auf false). Die Standardfunktion sieht so aus:

function out($value, $set) {
  if(!$set)
  [tab]return '{'.$value.'?}';
  
  return $value;
}

Einschränkungen

Interne Variablen beginnen in der Klasse immer mit einem Unterstrich. Deshalb dürfen diese weder gesetzt, noch im Template abgefragt werden. Beides führt zu einer Fehlermeldung.

Ansonsten habe ich noch keine Einschränkungen entdeckt. Es sind viele interessante Dinge möglich, wie Schleifen, Abfragen, dynamische Reaktion auf Inhalte usw. Das verleitet natürlich zur Vermischung von Logik und Layout. Bitte immer doppelt nachdenken, wo eine Funktion hin gehört.

Fazit

Ich bin von meiner Lösung recht begeistert und empfinde die Arbeit mit dieser Klasse als sehr angenehm. Über Hinweise und Kommentare freue ich mich sehr! Die komplette Klasse kann man sich hier ansehen oder als Zip Datei herunterladen. Natürlich gebe ich keine Garantie für die korrekte Funktionsweise, wünsche aber viel Spaß beim Ausprobieren und Erweitern!

Wenn jemand Einsatzmöglichkeiten in seinem eigenen Projekt dafür sieht, dann ist die Vorraussetzung eine kurze Meldung bei mir, vielen Dank!

Dennis Becker 7. Juli 2009 (14:34 Uhr)

Die Kurzschreibweise von PHP mag ja durchaus ganz nett sein, allerdings kollidert das ganze mit XML, was ich persönlich doof finde. Außerdem wird php_short_open_tags mit PHP 6 entfernt, daher sollte man am besten schon jetzt nicht mehr auf die Kurzschreibweise setzen und sich die normalen PHP Tags angewöhnen!

Löblich erwähnen möchte ich aber, dass du PHP selbst als Template Engine verwendest (wofür es ja auch gedacht und entwickelt wurde) anstatt noch einen zusätzlichen Template-Engine-Layer oben drauf zu klatschen, der völlig überflüssig ist.

Kann man bei deinem Ansatz auch for-Schleifen nutzen oder Partials einbinden? Das wird mir aus den Snippets nicht ganz klar.

Ansonsten: interessanter Blog :)

Paul 7. Juli 2009 (17:34 Uhr)

Hi Dennis, danke für deinen Kommentar!

Schleifen sind kein Problem. Im Programm zuweisen:
$output->mehr_als_eins = array(”Hallo”, “Welt”, “Wie gehts`?”);

Und im Template ausgeben:
< ? foreach($this->mehr_als_eins as $key => $value): ?>
Da steht mehr als < ?=$value?> auf Position < ?=$key?>
< ? endforeach; ?>

Ich mag diese Kurzschreibweisen total, deshalb hat mich dein Kommentar ziemlich geschockt, dass die entfernt werden… hoffentlich nur ein Gerücht.

Was meinst du mit Partials? Ist mir neu….

Schöne Grüße!

Einen Kommentar schreiben

(wird nicht veröffentlicht)

(wird veröffentlicht!)