Templates

1. Bedeutung von Templates

Das Adventure PHP Framework (APF) kennt mehrere Bedeutungen des Begriffs Template:

  • Templates dienen als Grundlage für die HMVC-Pattern-Implementierung des Page-Controller. Dieser baut die DOM-Baum-Struktur an Hand von Template-Dateien (HTML-Dateien) oder Tags auf und ermöglicht dem Entwickler so, die Oberfläche einer Webseite oder Applikation dynamisch und gemäß den Anforderungen zu gestalten.
  • Als Templates werden ebenfalls wiederverwendbare Elemente innerhalb von Template-Dateien bezeichnet. Ein bekannter Vertreter ist der <html:template />-Tag, der zur bedingten Ausgabe von Inhalten innerhalb von Templates sowie der Ausgabe von sich wiederholenden Inhalten genutzt werden kann.

Die Definition des MVC-Pattern beschreibt die Bedeutung der Komponenten Model, View und Controller. Das HMVC-Pattern definiert eine hierarchische Struktur von MVC-Elementen, die in der Implementierung des APF basierend auf Template-DOM-Knoten aufgebaut wird. Der Page-Controller nutzt dafür die Informationen, die in den Template-Dateien enthalten sind und erzeugt daraus Kind-Elemente des aktuellen Knoten.

Jedem Template, bzw. jedem Knoten des HMVC-DOM-Baumes, kann ein (Document-)Controller gemäß der Definition des MVC-Pattern zugeordnet werden.

2. Aufbau von Templates

Template-Dateien beinhalten drei Typen von Inhalten:

  • APF-Tags (z.B. <html:placeholder />)
  • HTML-Code (z.B. <p>...</p>)
  • Beliebiger Text

Tags sind dem APF-Parser bekannte XML-Tags der Form <prefix:name />. Sie können eine beliebige Anzahl von Attributen der Form attribute="value" besitzten. Explit schließende Tags haben weitere Tags oder einfachen Text als Inhalt.

HTML-Code und beliebiger Text dienen der Gestaltung des Inhalte einer Webseite oder Applikation und werden vom APF-Parser nicht weiter verarbeitet. Sie können daher sowohl als Attribute von Tags als auch als Inhalte verwendet werden.

Bitte beachten Sie, dass der APF-Parser HTML-Code in Attributen nur verarbeiten kann, wenn darin keine Anführungszeichen (") enthalten sind.

Innerhalb von APF-Tags können Sie prinzipiell beliebigen HTML-Code platzieren, solange dieser konsistent ist und die Schachtelung von Tags nicht stört.

Details zum APF-Parser erfahren Sie unter Implementierung von Tags.

2.1. Template-Dateien

Template-Dateien werden im Adventure PHP Framework zum Aufbau der UI einer Webseite oder Applikation genutzt und der Front-Controller wird stets mit einem initialen Template gestartet.

Innerhalb einer Template-Datei können APF-Tags (siehe Standard TagLibs), HTML-Code oder beliebiger Text platziert werden. Im einfachsten Fall enthält ein Template - z.B. das initiale Template - das Grundgerüst der Webseite oder Applikation und definiert Platzhalter für dynamische Inhalte oder bindet weitere Templates ein. Zur Ausgabe von dynamischen Inhalten kann ein Template einen (Document-)Controller referenzieren, der bei der Transformation ausgeführt wird.

Das folgende Code-Beispiel beinhaltet das Grundgerüst einer Webseite:

APF-Template
<@controller class="VENDOR\pres\controller\MainController" @> <!DOCTYPE html> <html> <head> <title><html:placeholder name="title" /></title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <header> <h1><html:placeholder name="title" /></h1> <core:importdesign namespace="VENDOR\pres\templates" template="navi" /> </header> <div id="content"> <core:importdesign namespace="VENDOR\pres\templates" template="content" /> </div> <footer> <core:importdesign namespace="VENDOR\pres\templates" template="footer" /> </footer> </body> </html>

Das Template definiert zwei Platzhalter-Tags, die über den Controller MainController gefüllt werden und bindet über drei <core:importdesign />-Tags weitere Templates ein, die sich um die Navigation, den Inhalt und den Footer kümmern.

Eine Liste von bekannten Tags finden Sie unter Standard TagLibs bzw. Spezielle Tags. Das Tutorial Implementierung von Tags erläutert Ihnen, wie Sie die Tags und Funktionen des APF für Ihre Webseite oder Applikation erweitern können.

2.2. HTML Templates

HTML Templates dienen zur Definition von wiederverwendbaren HTML-Fragmenten um beispielsweise Inhalte unter bestimmten Bedindungen darzustellen oder Listen zu erzugen. Es empfiehlt sich, je Element ein Template zu erstellen, das vom Controller verwendet werden kann. HTML Templates werden nicht direkt am Platz ihrer Definition ausgegeben, sondern sind nur Struktur-Elemente die zur Generierung von Inhalten genutzt werden können.

Die folgende Code-Box zeigt ein HTML Template, das zur Ausgabe einer dynamischen Tabelle genutzt werden kann:

APF-Template
<@controller class="VENDOR\pres\controller\ListController" @> <table> <thead> <tr> <td>Frage</td> <td>Antwort</td> </tr> </thead> <tbody> <html:placeholder name="table-rows" /> </tbody> </table> <html:template name="table-row"> <tr> <td><template:placeholder name="question" /></td> <td><template:placeholder name="answer" /></td> </tr> </html:template>

Das Template beinhaltet den Rumpf der auszugebenden Tabelle und der <html:template />-Tag definiert die sich wiederholende Zeile der Tabelle. Zur Generierung der Inhalte kann folgender Controller genutzt werden:

PHP-Code
use APF\core\pagecontroller\BaseDocumentController; class ListController extends BaseDocumentController { public function transformContent() { $row = $this->getTemplate('table-row'); $buffer = ''; foreach ($this->getItems() as $item) { $row->setPlaceHolder('question', $item->getQuestion()); $row->setPlaceHolder('answer', $item->getAnswer()); $buffer .= $row->transformTemplate(); } $this->setPlaceHolder('table-rows', $buffer) } /** * @return FaqEntry[] */ private function getItems() { ... } }
Templates, die nicht für die Generierung von Listen oder sich wiederholenden Inhalten eingesetzt werden, können direkt an der Stelle der Definition ausgegeben werden. Nutzen Sie hierzu die Methode transformOnPlace() im Document-Controller. Beispiel:
PHP-Code
class MainController extends BaseDocumentController { public function transformContent(){ $tmpl = &$this->getTemplate('template-name'); $tmpl->transformOnPlace(); } }

Um die Ausgabe von Listen zu vereinfachen, können Sie Platzhalter auch direkt befüllen. Hierzu lassen sich zwei Funktionalitäten kombinieren: mit dem dritten Parameter der Methode setPlaceHolder() kann weiterer Inhalt zu einem Platzhalter hinzugefügt werden und das TemplateTag untertützt die direkte Ausgabe, da es innerhalb der __toString()-Methode das Template automatisch transformiert.

Die Implementierung des Controllers kann damit wie folgt vereinfacht werden:

PHP-Code
use APF\core\pagecontroller\BaseDocumentController; class ListController extends BaseDocumentController { public function transformContent() { $row = $this->getTemplate('table-row'); foreach ($this->getItems() as $item) { $row->setPlaceHolder('question', $item->getQuestion()); $row->setPlaceHolder('answer', $item->getAnswer()); $this->setPlaceHolder('table-rows', $row, true); } } /** * @return FaqEntry[] */ private function getItems() { ... } }

3. Erweiterte Template-Funktionen

Bitte beachten Sie, dass die in diesem Kapitel beschriebe Funktionalität erst im Release 2.1. verfügbar ist!

Zusätzlich zu den im Kapitel 2 beschriebenen Funktionen lassen sich innerhalb von APF-Templates auch dynamische Template-Ausdrücke nutzen. Diese bieten Ihnen eine Kurzschreibweise für Platzhalter wie z.B. <html:placeholder /> sowie eine Pseudo-Sprache für den Zugriff auf Data-Attribute von APF-DOM-Knoten. Darüber hinaus lassen sich auch Methoden-Aufrufe und Listen-Zugriffe auf Data-Attribute realisieren.

Die folgenden Kapitel zeigen Ihnen die Nutzung der beiden Funktionen und geben Ihnen Anwendungsbeispiele.

3.1. Platzhalter

Neben den bekannten APF-Tags für Platzhalter wie beispielsweise

APF-Template
<html:placeholder name="foo" />

lässt sich auch die Kurzformen

APF-Template
${foo}

nutzen. Dies hilft die Größe Ihres Template-Codes zu reduzieren und gegebenfalls Probleme mit der IDE-Unterstützung für HTML-Dateien zu vermeiden.

Die Kurzschreibweise von Platzhaltern setzt sich aus ${, einem eindeutigen Bezeichner und einer schließenden Klammer - } - zusammen. Der Bezeichner darf keine weiteren Klammern enthalten. Erlaubt sind große und kleine Buchstaben sowie Binde- und Unterstriche.

Der Zugriff auf Platzhalter in der Kurzform unterscheidet sich nicht von der herkömmlichen Notation. Möchten Sie die Platzhalter des Templates

APF-Template
<@controller class="VENDOR\..\controller\SampleController" @> <div class="${css-class}"> <p> ${intro-text} </p> <p> ${detail-text} </p> <p> <a href="${link-target}">${link-label}</a> </p> </div>

füllen, so können Sie dazu den folgenen Controller-Code nutzen:

PHP-Code
namespace VENDOR\..\controller; use APF\core\pagecontroller\BaseDocumentController; class SampleController extends BaseDocumentController { public function transformContent() { $model = $this->getModel(); $this->setPlaceHolder('css-class', $model->getCssClass()); $this->setPlaceHolder('intro-text', $model->getIntroText()); $this->setPlaceHolder('detail-text', $model->getDetailText()); $this->setPlaceHolder('link-target', $model->getMoreLink()->getTarget()); $this->setPlaceHolder('link-label', $model->getMoreLink()->getLabel()); } /** * @return ContentModel */ private function getModel() { return new ContentModel(); } }

3.2. Objekt-Zugriff

Die Pseudo-Template-Sprache des APF ermöglicht Ihnen, mit einem dynamischen Ausdruck auf Data-Attribute von APF-DOM-Knoten zuzugreifen und die dort abgelegten Inhalte innerhalb von Templates auszugeben.

Das in Kapitel 3.1 beschriebene Template-Beispiel lässt sich mit Hilfe der Pseudo-Sprache wie folgt vereinfachen:

APF-Template
<@controller class="VENDOR\..\controller\SampleController" @> <div class="${news->getCssClass()}"> <p> ${news->getIntroText()} </p> <p> ${news->getDetailText()} </p> <p> <a href="${news->getMoreLink()->getLinkTarget()}"> ${news->getMoreLink()->getLinkLabel()} </a> </p> </div>

Der Controller verkürzt sich ebenfalls:

PHP-Code
namespace VENDOR\..\controller; use APF\core\pagecontroller\BaseDocumentController; class SampleController extends BaseDocumentController { public function transformContent() { $this->setData('news', $this->getModel()); } /** * @return ContentModel */ private function getModel() { return new ContentModel(); } }

Auf diese Weise lässt sich wiederholender Code aus Controllern entfernen und damit die Übersichtlichkeit erhöhen.

Grundlage für die Pseudo-Template-Sprache ist das APF-DOM-Modell. Dieses ermöglicht - analog zu HTML-Knoten - Data-Attribute zu definieren. Die Klasse Document stellt hierzu die Methoden setData() und getData() zur Verfügung. Innerhalb des BaseDocumentController können Sie mit den gleichnamigen Methoden ebenfalls auf die Data-Attribute des aktuellen Knotens zuzugreifen.

Die folgenden Kapitel stellen Ihnen die Funktionalitäten der Template-Sprache genauer vor.

3.2.1. Listen-Zugriff

Mit der Pseudo-Template-Sprache des APF lassen sich Listen-Zugriffe für Data-Attribute analog zur PHP-Syntax realisieren. Dabei werden einfach, sowie mehrfach verschachtelte Arrays mit nummerischen und alphanummerischen Adressen unterstützt.

Sie können im Template auf einfache und verschachtelte Listen mit einfachen Inhalten, aber auch auf Listen mit komplexen Inhalten (Objekte) zugreifen. Der Zugriff auf komplexe Inhalte erfordert gegebenenfalls weitere Schritte. Beachten Sie hierzu bitte Kapitel 3.2.2 und Kapitel 3.2.3.

Die folgende Code-Box zeigt Ihnen den Zugriff auf Listen im Template:

APF-Template
<@controller class="VENDOR\..\controller\SampleController" @> <!-- Zugriff auf das erste, nummerische Offset --> ${news[0]} <!-- Zugriff auf das Offset xyz --> ${news['xyz']} <!-- Zugriff auf das nummerische Offset 1 und darin auf das nummerische Offset 2 --> ${news[1][2]} <!-- Zugriff auf das nummerische Offset 1 und darin auf das alphanummerische Offset xyz --> ${news[1]['xyz']} <!-- Zugriff mit Mischformen --> ${news[1][2][3][4]} ${news[1]['two'][3]['four']}

Um mit den beschriebenen Ausdrücken auf Inhalte zugreifen zu können sind die Data-Attribute im Controller wie folgt zu befüllen:

PHP-Code
namespace VENDOR\..\controller; use APF\core\pagecontroller\BaseDocumentController; class SampleController extends BaseDocumentController { public function transformContent() { $model = $this->getModel(); // Zugriff auf das erste, nummerische Offset $this->setData( 'news', array( 0 => $model ) ); // Zugriff auf das Offset xyz $this->setData( 'news', array( 'xyz' => $model ) ); // Zugriff auf das nummerische Offset 1 und darin auf das nummerische Offset 2 $this->setData( 'news', array( 1 => array( 2 => $model ) ) ); // Zugriff auf das nummerische Offset 1 und darin auf das alphanummerische Offset xyz $this->setData( 'news', array( 1 => array( 'xyz' => $model ) ) ); // Zugriff mit Mischformen $this->setData( 'news', array( 1 => array( 2 => array( 3 => array( 4 => $model ) ) ) ) ); $this->setData( 'news', array( 1 => array( 'two' => array( 3 => array( 'four' => $model ) ) ) ) ); } /** * @return ContentModel */ private function getModel() { return new ContentModel(); } }
Implementieren die in der Liste befindlichen Objekte die __toString()-Methode, so können Sie die Ausgabe der Objekte durch einen Listen-Zugriff erzeugen ohne weitere Methoden-Aufrufe zu definieren.
3.2.2. Objekt-Zugriff

Neben dem Zugriff auf Listen, bietet die Pseudo-Template-Sprache des APF auch den Zugriff auf Objekte in Data-Attributen. Die Syntax folgt auch hier der PHP-Syntax.

Methoden-Aufrufe lassen sich in beliebiger Anzahl und Abfolge definieren und können auch in Verbindung mit Listen genutzt werden. Beachten Sie hierzu bitte die Dokumentation in Kapitel 3.2.3.

Die folgende Code-Box zeigt Ihnen Beispiele für Methoden-Aufrufe:

APF-Template
<@controller class="VENDOR\..\controller\SampleController" @> <!-- Zugriff auf die Methode getCssClass() der Klasse ContentModel --> ${news->getCssClass()} <!-- Zugriff auf die Methode getLinkLabel() der Klasse LinkModel, das von der Methode getMoreLink() der Klasse ContentModel zurückgegeben wird --> ${news->getMoreLink()->getLinkLabel()}

Um mit den beschriebenen Ausdrücken auf Inhalte zugreifen zu können muss das Data-Attribute news im Controller wie folgt zu befüllt werden:

PHP-Code
namespace VENDOR\..\controller; use APF\core\pagecontroller\BaseDocumentController; class SampleController extends BaseDocumentController { public function transformContent() { $this->setData('news', $this->getModel()); } }
3.2.3. Kombinierter-Zugriff

Die in Kapitel 3.2.1 und Kapitel 3.2.2 beschriebenen Listen- und Methoden-Zugriffe lassen sich auch zu komplexeren Abfragen kombinieren. So kann durch eine Kombination eines Listen- und ein oder mehrerer Methoden-Aufrufe der Zugriff auf eine Liste von Einträgen und deren Eigenschaften realisieren.

Bitte beachten Sie, dass mehrere Methoden-Aufrufe bzw. Listen-Zugriffe jeweils durch -> getrennt sind.

Beabsichtigen Sie in einem Template die ersten drei News-Einträge auszugeben, so lässt sich dies mit dem folgenden Template realisieren:

APF-Template
<@controller class="VENDOR\..\controller\SampleController" @> <ul class="news-list"> <li>${news[0]->getIntroText()}</li> <li>${news[1]->getIntroText()}</li> <li>${news[2]->getIntroText()}</li> </ul>

Zur Erzeugung der Ausgabe ist folgender Controller-Code notwendig:

PHP-Code
namespace VENDOR\..\controller; use APF\core\pagecontroller\BaseDocumentController; class SampleController extends BaseDocumentController { public function transformContent() { $this->setData('news', $this->getNews()); } /** * @return ContentModel[] */ private function getNews() { ... } }

Die Methode getNews() liefert dabei eine Liste von ContentModel-Objekten zurück.

Die Implementierung der Pseudo-Template-Sprache ermöglicht darüber hinaus weitere Kombinationen von Ausdrücken:

APF-Template
<!-- Aufruf von getBar() auf das dritte von getFoo() zurückgegebene Element --> ${news->getFoo()->[3]->getBar()} <!-- Aufruf von getBaz() auf das Ergebnis von getBar(), das im Offset foo des 5.ten Elements im Data-Attribut news steht --> ${news[5]['foo']->getBar()->getBaz()}
Bitte beachten Sie, dass die im letzen Code-Block aufgeführten Beispiele jeweils eine entsprechende Daten-Struktur voraussetzen! Fehlerhafte Ausdrücke führen zu Fehlern und damit zum Abbruch der Applikation.

Kommentare

Möchten Sie den Artikel eine Anmerkung hinzufügen, oder haben Sie ergänzende Hinweise? Dann können Sie diese hier einfügen. Die bereits verfassten Anmerkungen und Kommentare finden Sie in der untenstehenden Liste.
Für diesen Artikel liegen aktuell keine Kommentare vor.