|
Dokumentation |
Separate Template Engine Version 1.6 (03.03.2018, PHP7) |
Was ist Separate Template Engine?
Separate Template Engine, oder kurz Separate, ist eine objektorientierte Template Engine für PHP7,
die im Entwicklungsprozess von webbasierten Anwendungen große Abhilfe schafft.
Mit Separate ist es möglich, Business Logik (z.B. das Auslesen
der Daten aus einer Datenbank) von der Darstellung (HTML-Quelltext) zu trennen
und somit einen sauberen, übersichtlichen und gut strukturierten Quelltext zu
produzieren. Die Generierung von fertigen HTML Seiten wird dabei automatisch
von der Template Engine gemanagt.
Architektur von Separate
Wichtige Eigenschaften der Architektur
Während der Entwicklung wurde großen Wert auf die
dynamische Funktionserweiterung (wie z.B. Value Formatter oder die Vererbungs-Möglichkeit der Template-Klasse)
gelegt. Insgesamt wurden folgende, für die Entwicklung wichtige, Eigenschaften umgesetzt:
- Minimale funktionale Beschränkungen (Erweiterung mit eigenen Funktionalitäten ist möglich)
- Einfache API (z.B. nur die Template.php Datei wird benötigt)
- Unabhängig von anderen Bibliotheken (wie z.B. Pear,...)
Aufbau einer Separate-basierten Anwendung
Anwendungen, die auf Separate basieren, bestehen aus zwei Schichten – der
Darstellungsschicht (Presentation Layer) und der Business Logik. Die Darstellungsschicht
besteht aus HTML-Quelltext und aus Template-Variablen bzw.
sonstigen Separate-relevanten Konstrukten. In der Business Logik werden
Berechnungen durchgeführt (z. B. das Auslesen der Daten aus der Datenbank)
und anschließend die daraus generierten Werte bestimmten Template Variablen zugewiesen.
Die obere Abbildung zeigt die Business Logik sowie die Darstellungsschicht (Presentation Layer),
welche von Separate verarbeitet wird.
Als Ergebnis wird ein HTML-Quelltext zurückgegeben.
Integration in das eigene Projekt
Separate benötigt PHP7 oder höher.
Um Separate zu benutzen, muss die bereitgestellte Template-Klasse in Ihr Projekt eingefügt werden.
require_once './Template.php';
|
Als nächstes muss eine Templatedatei geladen werden. Dazu wird die Methode \separate\Template::initialize('...') benutzt.
$t = \separate\Template::initialize('./index.htm');
|
Nach einem erfolgreichen Laden der Templatedatei kann die
eigentliche Implementierung, wie z. B. die Zuweisung von Werten zu bestimmten
Template Variablen, stattfinden.
$t->assign('MY_VARIABLE', 'my value');
|
Die anschließende Generierung der HTML-Seite
erfolgt mit der \separate\Template::display() Methode.
\separate\Template::display();
|
Der folgende Quelltext fasst alle oben erwähnten Schritte noch einmal zusammen.
<?php
require_once './Template.php';
$t = \separate\Template::initialize('./index.htm');
$t->assign('MY_VARIABLE', 'my value');
\separate\Template::display();
|
Template-Variablen
Für jede dynamisch generierte Informationseinheit muss
in der Templatedatei eine Template-Variable angelegt werden. Während der
Seitengenerierung ersetzt die Template Engine diese Variablen durch
einen zuvor zugewiesenen Wert. Die Syntax sieht wie folgt aus:
Dynamische Blöcke
Mit dynamischen Blöcken können Sie HTML-Quelltext in Abschnitte aufteilen.
Diese Abschnitte können während der Laufzeit beliebig oft wiederholt werden. Das ist
sinnvoll, um z.B. eine Tabelle mit dynamischem Inhalt zu generieren. Die Syntax sieht wie folgt aus:
<!-- BEGIN <Block Name> -->
HTML-Quelltext...
<!-- END <Block Name> -->
|
|
Im PHP-Quelltext wird jeder Block durch ein Template-Objekt repräsentiert.
Mit der Template->fetch(...)-Methode wird ein neuer Block erstellt. Diesem können anschließend beliebige Werte zugewiesen werden.
Mit der Template->assign(...)-Methode wird dann der modifizierte Block dem Root-Template übergeben.
Abhängig von der Datensatz-Anzahl muss dieser Vorgang mehrmals wiederholt werden.
Das untenstehende Beispiel zeigt eine einfache Implementierung von dynamischen Blöcken.
|
PHP-Quelltext:
<?php
require_once './Template.php';
$rootTemplate = \separate\Template::initialize('./index.htm');
for($row = 1; $row <= 3; $row++)
{
//fetch row block from root template
$rowBlock = $rootTemplate->fetch('row');
for($column = 1; $column <= 3; $column++)
{
//fetch column block from row block
$columnBlock = $rowBlock->fetch('column');
$columnBlock->assign('ROW_NUMBER', $row);
$columnBlock->assign('COLUMN_NUMBER', $column);
//assign modified column block back to row block
$rowBlock->assign('column', $columnBlock);
}
//assign modified row block back to root template
$rootTemplate->assign('row', $rowBlock);
}
\separate\Template::display();
?>
|
Template-Quelltext (index.htm):
<html>
<body>
<table>
<!-- BEGIN row -->
<tr>
<!-- BEGIN column -->
<td>Row: ${ROW_NUMBER} Column: ${COLUMN_NUMBER}</td>
<!-- END column -->
</tr>
<!-- END row -->
</table>
</body>
</html>
|
Wie Sie im oberen Beispiel sehen, können in Blöcken auch weitere Blöcke definiert werden.
Der daraus generierte HTML-Quelltext sieht dann wie folgt aus:
<html>
<body>
<table>
<tr>
<td>Row: 1 Column: 1</td>
<td>Row: 1 Column: 2</td>
<td>Row: 1 Column: 3</td>
</tr>
<tr>
<td>Row: 2 Column: 1</td>
<td>Row: 2 Column: 2</td>
<td>Row: 2 Column: 3</td>
</tr>
<tr>
<td>Row: 3 Column: 1</td>
<td>Row: 3 Column: 2</td>
<td>Row: 3 Column: 3</td>
</tr>
</table>
</body>
</html>
|
Zuweisung von Platzhalterwerten
Werte für vordefinierte Template-Variablen werden mit bestimmten
Methoden im PHP-Quelltext zugewiesen. Es existieren drei
unterschiedliche Arten von Zuweisungen:
1. Einfache Zuweisung von Platzhalterwerten
Bei dieser Zuweisungsart sind die zugewiesenen Werte auf einen Template-Block
oder einen
Root-Template beschränkt. Template-Platzhalter, die außerhalb von diesem Bereich liegen,
werden einfach ignoriert. Die Zuweisung erfolgt mit einer Template->assign(...)-Methode.
$t->assign('MY_VARIABLE', 'my value');
|
2. Block-relevante Zuweisung von Platzhalterwerten
Mit Block-relevanter Platzhalterzuweisung kann ein Wert einer Variable
zugewiesen werden, die sich innerhalb eines Blocks (inkl. der Unterblocks) befindet.
Variablen, die sich in anderen Blöcken
befinden, werden dagegen ignoriert.
$t->assignForBlock('MY_BLOCK_VARIABLE', 'my block value');
|
3. Globale Zuweisung von Platzhalterwerten
Bei dieser Zuweisungsart können Werte zu allen Template-Variablen zugewiesen
werden. Es spielt also keine Rolle, ob sich eine Template Variable in
irgendwelchen Blöcken befindet oder direkt auf Root-Ebene des Templates. Die Verwendung
von dieser Zuweisungsart ist nur bei Template-Variablen sinnvoll, die häufig in
mehreren Quelltextbereichen vorkommen. Für die Zuweisung von globalen Werten
wird die Template->assignForGlobal(...)-Methode benutzt.
$t->assignForGlobal('MY_GLOBAL_VARIABLE', 'my global value');
|
Formatierung von Platzhalterwerten
Standardmäßig werden alle Werte ohne Veränderung im HTML-Quelltext dargestellt.
Manchmal ist es jedoch notwendig, diese vorher zu verändern.
Zum Beispiel dann, wenn auf einer Seite bestimmter Text dargestellt wird, der
HTML-Steuerzeichen (<, >, &, ...) enthält.
Diese Zeichen müssen beim Generieren der Seite umgewandelt werden. Um das Ganze möglichst
elegant und dynamisch zu machen, unterstützt Separate sogenannte Value Formatter.
Ein Value Formatter besteht aus Anweisungen, die eine Zeichenkette
umwandeln. Wenn ein Wert einer Template-Variable zugewiesen wird, die Value Formatter verwendet,
dann wird der zugewiesene Wert vor der Darstellung im generierten HTML-Quelltext durch den jeweiligen Value Formatter
umgewandelt. Die Syntax für eine Template-Variable mit festgelegtem Value Formatter sieht wie folgt aus:
${(<Value Formatter Name>)<Variable Name>}
|
Folgendes Beispiel demonstriert eine einfache Value-Formatter-Implementierung, welche
den Unix Timestamp in ein lesbares Datum bzw. Zeit umwandelt.
PHP-Quelltext:
<?php
require_once './Template.php';
require_once './formatter/DateFormatter.php';
require_once './formatter/TimeFormatter.php';
$t = \separate\Template::initialize('./index.htm');
$t->assign('UNIX_TIMESTAMP', time());
\separate\Template::display();
?>
|
Template-Quelltext (index.htm):
<html>
<body>
Timestamp: ${UNIX_TIMESTAMP}<br>
Date: ${(Date)UNIX_TIMESTAMP}<br>
Time: ${(Time)UNIX_TIMESTAMP}
</body>
</html>
|
Der daraus generierte HTML-Quelltext sieht dann wie folgt aus:
<html>
<body>
Timestamp: 1520104433<br>
Date: 03.03.2018<br>
Time: 19:13
</body>
</html>
|
Default Value Formatter
Mit der Methode Template::setDefaultFormatter(...) kann ein
Value Formatter gesetzt werden, welcher standardmäßig bei allen Template-Variablen
verwendet wird.
\separate\Template::setDefaultFormatter(new TextFormatter());
|
Vorhandene Value Formatter
Mit Separate werden mehrere Value Formatter bereits mitgeliefert.
Formatter Klasse |
Name |
Beschreibung |
DateFormatter |
Date |
Konvertiert Unix Timestamp in ein lesbares Datum, z.B. 03.03.2018 |
TimeFormatter |
Time |
Konvertiert Unix Timestamp in eine lesbare Zeitangabe, z.B. 19:13 |
DateTimeFormatter |
DateTime |
Konvertiert Unix Timestamp in ein lesbares Datum mit
zusätzlicher Zeitangabe, z.B. 03.03.2018 19:13
|
TextFormatter |
Text |
Ersetzt alle HTML-Steuerzeichen (z.B. <, > oder &) durch dafür vorgesehene HTML-Zeichen (z.B. <, > oder &). |
UrlFormatter |
Url |
Erstellt eine URL-konforme Zeichenkette, welche
primär für Hyperlinks vorgesehen ist.
|
HashFormatter |
Hash |
Hash wird in einem IF-Konstrukt benutzt,
um zwei unbekannte Zeichenketten zu vergleichen.
|
IsEmptyFormatter |
IsEmpty |
IsEmpty wird in einem IF-Konstrukt benutzt,
um zu prüfen, ob ein Platzhalter leer ist.
|
Eigene Value Formatter erstellen
Neben bereits vorhandenen Value Formatter können auch eigene Value Formatter erstellt werden.
Dazu muss eine Klasse angelegt werden, die \separate\ValueFormatter Klasse vererbt.
Anschließend muss die Methode \separate\ValueFormatter->formatValue(...) mit eigener Business Logik überschrieben werden.
Bei der Benennung von benutzerdefinierten Formatter-Klassen muss eine bestimmte Schreibweise eingehalten
werden. Der Klassenname fängt mit einem Formatter Namen an, welcher bei Template-Variablen verwendet wird,
und endet immer mit dem Wort "Formatter".
Syntax der Klassenbezeichnung für einen benutzerdefinierten Value Formatter:
<Formatter Name>Formatter
|
Folgendes Beispiel zeigt eine Implementierung von
Value Formatter, welcher den Platzhalterwert in Großbuchstaben umwandelt.
PHP-Quelltext:
<?php
require_once './Template.php';
class ToUpperFormatter extends \separate\ValueFormatter
{
public function formatValue(string $value) : string
{
return strtoupper($value);
}
}
$t = \separate\Template::initialize('./index.htm');
$t->assign('MY_VARIABLE', 'my value');
\separate\Template::display();
?>
|
Template-Quelltext (index.htm):
<html>
<body>
${(ToUpper)MY_VARIABLE}
</body>
</html>
|
Der daraus generierte HTML-Quelltext sieht dann wie folgt aus:
<html>
<body>
MY VALUE
</body>
</html>
|
Platzhalter ohne Formatierungsmöglichkeit
Manchmal ist eine maximal mögliche Geschwindigkeit der HTML-Quelltext Generierung sehr wichtig.
Für diese Anforderung existiert eine spezielle Platzhalter-Art, welche im Rendering sehr schnell ist,
dafür aber keine Formatierung durch Value Formatter unterstützt.
Im Template-Quelltext beginnen Platzhalter dieser Art mit einem #-Zeichen:
Im PHP-Quelltext müssen hierfür spezielle Assign-Methoden benutzt werden.
Diese Methoden sind mit normalen Assign-Methoden
identisch, fangen jedoch mit einem x-Zeichen an.
$t->xassign('MY_VARIABLE', 'my value');
$t->xassignForBlock('MY_BLOCK_VARIABLE', 'my block value');
$t->xassignForGlobal('MY_GLOBAL_VARIABLE', 'my global value');
|
Template Including
In eine Templatedatei können auch andere Templatedateien eingebunden werden.
Syntax des Include-Befehls:
<!-- INCLUDE <File Name> -->
|
Folgendes Beispiel zeigt eine Implementierung des Include-Befehls im Template-Quelltext.
Header-Datei (header.htm):
Footer-Datei (footer.htm):
Template-Quelltext (index.htm):
<!-- INCLUDE header.htm -->
<p>Hallo</p>
<!-- INCLUDE footer.htm -->
|
IF-Konstrukt
Manchmal ist es notwendig, bestimmte Entscheidungen auf die Darstellungsschicht zu verlagern.
Um dies möglich zu machen, werden IF-Konstrukte unterstützt. Die Syntax
eines IF-Konstrukts sieht wie folgt aus:
<!-- IF <Bedingung 1> -->
HTML-Quelltext...
<!-- ELSE IF <Bedingung 2> -->
HTML-Quelltext...
<!-- ELSE -->
HTML-Quelltext...
<!-- END IF -->
|
Die Bedingung kann aus mehreren Template-Variablen zusammengestellt werden.
Es können alle Vergleichsoperatoren verwendet werden, die auch im PHP existieren.
Im Folgenden ist eine einfache Beispielimplementierung von einem IF-Konstrukt abgebildet.
PHP-Quelltext:
<?php
require_once './Template.php';
$t = \separate\Template::initialize('./index.htm');
$t->assign('MY_VARIABLE', 'hallo');
\separate\Template::display();
?>
|
Template-Quelltext (index.htm):
<html>
<body>
<!-- IF '${MY_VARIABLE}' == 'hallo' -->
The value of MY_VARIABLE is 'hallo'
<!-- ELSE -->
The value of MY_VARIABLE is '${MY_VARIABLE}'
<!-- END IF -->
</body>
</html>
|
Besonderheiten beim Vergleich von Werten
Um eine maximale Geschwindigkeit zu ermöglichen, werden von der Template Engine
bestimmte Validierungen nicht durchgeführt. Aus diesem Grund
muss der Entwickler einige Besonderheiten beim Erstellen einer IF-Abfrage beachten.
Um zwei Variablen mit unbekannten Werten zu vergleichen, muss ein Hash Formatter benutzt werden,
welcher die Werte beim Vergleich in einen Hash-String umwandelt.
<!-- IF '${(Hash)MY_VARIABLE_A}' == '${(Hash)MY_VARIABLE_B}' -->
...
<!-- END IF -->
|
Um zu überprüfen, ob eine Variable einen leeren String enthält, muss der IsEmpty Formatter benutzt werden.
Wenn die Variable einen leeren String enthält, wird der Wert durch den Formatter in "TRUE" umgewandelt.
Ansonsten wird der Wert in "FALSE" umgewandelt.
<!-- IF '${(IsEmpty)MY_VARIABLE}' == 'TRUE' -->
...
<!-- END IF -->
|
Um boolesche Vergleiche zu vereinfachen, steht die \separate\Template::booleanToString(...) Methode zur Verfügung.
Diese wandelt einen booleschen Wert in "TRUE" oder "FALSE" um.
PHP-Quelltext:
$t->xassign('LOGGED_IN_FLAG', \separate\Template::booleanToString(...));
|
Template-Quelltext:
<!-- IF '#{LOGGED_IN_FLAG}' == 'TRUE' -->
...
<!-- END IF -->
|
Template Parameter
Mit Template Parametern können beliebige Einstellungen im Template definiert werden.
Diese Parameter können dann im PHP-Quelltext ausgelesen werden. Aber wofür braucht man das?
Hier ist ein Beispiel aus der Praxis:
Manchmal kommt es vor, dass eine Webanwendung unterschiedliche Layouts besitzt.
Zum Beispiel wenn neben dem normalen Layout ein weiteres Layout für mobile Endgeräte angeboten wird.
In der Praxis werden für dieselbe Business-Logik zwei unterschiedliche Templates entwickelt - eins für
Standard-Layout, und eins für mobile Endgeräte.
Nehmen wir mal an, dass wir
eine dynamisch generierte Tabelle mit vielen Datensätzen haben, die wiederum
auf mehrere Seiten verteilt sind. Bei dem Standard-Layout werden auf jeder Seite 100 Datensätze angezeigt.
Im Layout für mobile Endgeräte sollen aber max. 10 Datensätze pro Seite angezeigt werden, da es ansonsten zu viel wird.
Um es zu realisieren,
ohne irgendwelche Änderungen im PHP-Quelltext zu tätigen, wurden sogenannte Template-Parameter entwickelt.
Template-Parameter Syntax:
<!-- PARAMETER <Parameter Name> '<Parameter Wert>' -->
|
Beispiel:
<!-- PARAMETER NUMBER_OF_ROWS '100' -->
|
Diese Parameter können mit der Template::getParameters()-Methode ausgelesen werden. Außerdem können
auch eigene Parameter während der Ausführung festgelegt werden oder der Inhalt von bereits
vorhandenen Parametern geändert werden. Dazu steht die Template::setParameterValue(...)-Methode zur Verfügung.
Template-Kommentare
Jeder weiß, dass im HTML eine Möglichkeit existiert, Quelltext Kommentare zu schreiben. Die Kommentare sehen dabei wie folgt aus:
<!-- HTML-Kommentar... -->
|
Solche Quelltext-Kommentare haben aber zwei Nachteile: Diese werden an den Client gesendet und erzeugen unnötigen Traffic.
Ein weiterer Nachteil besteht darin, dass solche Kommentare auf der Client-Seite (im HTML-Quelltext) sichtbar sind.
Aus diesem Grund bietet Separate eine Möglichkeit an, spezielle Template-Kommentare zu erstellen.
Diese Template-Kommentare sind im generierten HTML-Quelltext nicht sichtbar und werden somit auch nicht an den Client weitergeleitet.
Die Syntax sieht wie folgt aus:
<!--- Template-Kommentar... --->
|
Empfehlungen
Die Benennung von vielen Quelltext-Komponenten ist dem Programmierer
selbst überlassen. Trotzdem wird empfohlen, eine vorgegebene Namensgebung zu verwenden.
Benennung von Template-Variablen im PHP-Quelltext
Es wird empfohlen, alle Template-Objekte in einer Array (z. B. $t) abzuspeichern.
Der Blockname wird dabei einfach als Key übergeben.
Im unteren Beispiel steht $t['.'] für das Root-Template und $t['block']['.'] bzw. $t['block']['sub_block']['.'] für jeweilige Blöcke.
$t['.'] = \separate\Template::initialize('./index.htm');
for(...)
{
$t['block']['.'] = $t['.']->fetch('block');
for(...)
{
$t['block']['sub_block']['.'] = $t['block']['.']->fetch('sub_block');
//...
$t['block']['.']->assign('sub_block', $t['block']['sub_block']['.']);
}
$t['.']->assign('block', $t['block']['.']);
}
\separate\Template::display();
|
Benennung von Template-Variablen in großen Projekten
In großen Projekten kann es vorkommen, dass ein Variablenname mehrere fachliche Bedeutungen hat.
Zum Beispiel kann bei einer mehrsprachigen Anwendung die Template-Variable NAME für einen
Benutzernamen (wie z.B. "Max Mustermann") sowie für die Aufschrift in aktueller Sprache (z.B. "Name") stehen. Um diese Konflikte zu vermeiden,
macht es Sinn, einen Präfix für jede fachliche Bedeutung zu definieren:
#{LANGUAGE.NAME}: ${VALUE.NAME}
|
Im oberen Beispiel beginnen alle Template-Variablen für Phrasen in aktueller
Sprache mit LANGUAGE und alle Variablen für dynamische Werte mit VALUE.
Ein weiterer Vorteil besteht darin, dass es bei jeder Seitengenerierung möglich ist,
Werte für die LANGUAGE-Variablen automatisch zu setzen.
Um alle LANGUAGE-Variablen zu ermitteln, die im aktuellen Template existieren,
kann die Methode Template->getVariableNames() verwendet werden.
Anschließend können die Werte mit der Methode Template->xassignForGlobal(...) gesetzt werden.
Lizenz
Separate Template Engine wurde von Eduard Sudnik entwickelt und ist ein open-source Framework für PHP, welches
unter der MIT-Lizenz zur Verfügung steht.
|
|