(Document-)Controller

1. Zweck eines (Document-)Controllers

Wie unter Standard TagLibs und Templates bereits mehrfach angesprochen, werden (MVC-Document-)Controller zur Generierung von dynamischen Inhalten verwendet. Um diese Aufgabe wahr nehmen zu können muss ein Document-Controller einem DOM-Knoten bekannt gemacht werden. Dies passiert in der ersten Zeile einer Template-Datei durch ein <@controller @>-Tag. Der Page-Controller weist dem aktuellen DOM-Knoten damit den dort angegebenen Document-Controller zu und führt diesen bei der Transformation des Knotens aus.

2. Aufbau eines (Document-)Controllers

Jeder Document-Controller erbt vom Basis-Controller BaseDocumentController. Dieser besitzt zur Verarbeitung der bekannten TagLib-Tags notwendige Methoden. Beispiel hierfür ist die Funktion getTemplate() um eine Referenz auf ein im Knoten enthaltenes Template zugreifen zu können, oder die Methode setPlaceHolder(), mit der ein <html:placeholder />-Tag gefüllt werden kann.

Das Gerüst eines Document-Controllers hat immer folgende Gestalt:

PHP-Code
class SampleController extends BaseDocumentController { public function transformContent(){ } }
Bitte verwenden Sie in Release 1.16 und früher die Klasse base_controller als Basis für Ihre Document-Controller Implementierungen. Die Klasse BaseDocumentController steht erst ab Release 1.17 zur Verfügung.

Ein Document-Controller ist im Prinzip eine PHP-Klasse "wie jede andere auch". Dem Entwickler steht es frei eigene Klassenvariablen zu definieren, eigene Methoden einzuführen und weitere Klassen einzubinden. Wichtig ist nur, dass das zuvor gezeigte Interface eingehalten wird.

Wie der API-Dokumentation zu entnehmen ist verfügt der BaseDocumentController über folgende Methoden:

  • getDocument(): Liefert eine Referenz auf den aktuellen DOM-Knoten zurück. Dies ermöglicht den Zugriff auf den kompletten Baum über die Methoden getChildren() und getParentObject().
  • getTemplate($name): Liefert eine Referenz auf ein Template-Objekt (Instanz von TemplateTag) das im aktuellen Dokument definiert ist.
  • getForm($name): Liefert eine Referenz auf ein Formular-Objekt (Instanz von HtmlFormTag) das im aktuellen Dokument definiert ist.
  • getLabel($name): Liefert eine Referenz auf ein Label-Objekt (Instanz von LanguageLabelTag) das im aktuellen Dokument definiert ist.
  • getIterator(): Liefert eine Referenz auf ein Iterator-Objekt (Instanz von HtmlIteratorTag) das im aktuellen Dokument definiert ist.
  • placeHolderExists($name): Prüft, ob im aktuellen Dokument ein Platzhalter-Tag mit dem übergebenen Namen existiert.
  • templatePlaceHolderExists(TemplateTag &$template, $name) Prüft, ob im aktuellen Dokument in einem Template ein Platzhalter-Tag mit dem übergebenen Namen existiert.
  • setPlaceHolder($key, $value): Füllt einen Platzhalter mit dem übergebenen Wert.
  • setPlaceHolders(array $placeHolderValues): Füllt eine Liste von Platzhaltern mit den übergebenen Werten.
  • setPlaceHolderIfExist($name, $value): Füllt einen Platzhalter mit dem gewünschten Wert, falls dieser existiert.
  • setPlaceHoldersIfExist(array $placeHolderValues): Füllt eine Liste von Platzhaltern, falls diese existieren.

Des Weiteren verfügt der BaseDocumentController über alle Methoden der Klasse APFObject.

Bitte beachten Sie, dass die Methode getIterator() erst ab Release 1.17 zur Verfügung steht. In Versionen vor 1.17 ist die Methode in der Klasse iteratorBaseController definiert (siehe Spezielle TagLibs).
Über die bisher genannten Methoden besitzt jeder Document-Controller eine Referenz auf das Dokument im APF-DOM-Baum, für dessen Transformation er zuständig ist. Dieses kann mit Hilfe der Methode $this->getDocument() bezogen werden. Anschließend ist es möglich, per
PHP-Code
$this->getDocument()->getAttribute('foo')
auf den Wert des Attributs foo zuzugriffen.

3. Beispiele für (Document-)Controller

Ab Version 1.14 ist es ausreichend, einen Document-Controller mit den Attributen namespace und class zu adressieren. Das Attribut file ist nicht mehr notwendig.

3.1. Darstellung dynamischer Inhalte in Meta-Tags

In diesem Kapitel soll nun die Implementierung eines Document-Controllers erläutert werden, der das in Templates, Kapitel 2.1, aufgeführte Template mit Inhalten füllt. Dazu ist das Template zunächst um die Definition des Document-Controllers zu erweitern und sieht daher wie folgt aus:

APF-Template
<@controller namespace="sites::apfdocupage::pres::documentcontroller" class="WebsiteController" @> [..] <meta name="keywords" lang="de" content="PHP,Framework,Page-Controller,Front-Controller,Pattern,[..]" /> <meta name="date" content="<html:placeholder name="Date" />" /> <meta name="robots" content="index,follow" /> <meta name="revisit-after" content="5 days" /> [..]

Der zugehörige Document-Controller implementiert in diesem Fall lediglich die Methode transformContent() die bei der Transformation aufgerufen wird. Der Quellcode der Klasse sieht dann wie folgt aus:

PHP-Code
class WebsiteController extends BaseDocumentController { public function transformContent(){ // Platzhalter-Tag "URI" setzen $this->setPlaceHolder('URI',$_SERVER['REQUEST_URI']); // Platzhalter-Tag "Date" setzen $this->setPlaceHolder('Date',date('Y-m-d')); } }

3.2. Darstellung dynamischer Listen

Die folgenden Zeilen greifen das in Templates, Kapitel 2.2, aufgeführte Template zur Darstellung einer Liste. Dazu wird das Template - wie oben - zunächst um die Definition desc Document-Controllers erweitert:

APF-Template
<@controller namespace="sites::apfdocupage::pres::documentcontroller" class="ListController" @> [..] <html:placeholder name="List" /> <html:template name="ListHeader"> <table cellpadding="0" cellspacing="0" border="0"> <tr> <td> <strong>ExampleList</strong> </td> </tr> <template:placeholder name="TableElements" /> </table> </html:template> <html:template name="ListItem"> <tr> <td> <template:placeholder name="ItemValue" /> </td> </tr> </html:template>

Der zugehörige Document-Controller implementiert nun einerseits die Methode transformContent(), wird aber die privaten Methoden buildList() und buildListItem() erweitert. Somit werden die Tasks nochmal in eigene "Helper-Methoden" verpackt und der Code gestaltet sich übersichtlicher und besser lesbar. Das Laden der Liste übernimmt eine fiktive Business-Komponente (listLoader), die eine Liste (=Array) von listItem- Objekten zurückgibt. Letzters ist ein Daten-Objekt, das von APFObject erbt und genau eine Eigenschaft mit dem Namen ListContent besitzt das mit get() abgefragt werden kann. Die Liste wird dann iteriert und daraus eine HTML-Ausgabe generiert:

PHP-Code
import('sites::demosite::biz','listLoader'); class ListController extends BaseDocumentController { public function transformContent(){ // Liste in Platzhalter-Tag "List" einsetzen $this->setPlaceHolder('List',$this->buildList()); } private function buildList(){ // listLoader erzeugen $listLoader = &$this->getServiceObject('sites::demosite::biz','listLoader'); // Liste laden $List = $listLoader->loadList(); // HTML-Puffer initialisieren $Buffer = (string)''; // Referenz auf Header-Template holen $templateListHeader = &$this->getTemplate('ListHeader'); // Liste durchlaufen und Items generieren foreach($List as $lKey => $lItem){ // Ausgabe für Item generieren $Buffer .= $this->buildListItem($lItem); } // Items in das Header-Template einsetzen $templateListHeader->setPlaceHolder('TableElements',$Buffer); // Template transformieren und zurückgeben return $templateListHeader->transformTemplate(); } private function buildListItem(&$listItem){ // Referenz auf ListItem-Template holen $templateListItem = &$this->getTemplate('ListItem'); // Inhalt des Templates setzen $templateListItem->setPlaceHolder('ItemValue',$listItem->get('ListContent')); // Template transformieren und zurückgeben return $templateListItem->transformTemplate(); } }

3.3. Weiterführende Beispiele

Weiterführende Controller-Beispiele sind unter Objektorientierte Implementierung eines Gästebuchs und Kontaktformular-Tutorial zu finden. Das Thema Formulare wird auf der Seite Formulare nochmals genauer behandelt.

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.