17.10 HTML_QuickForm_Controller 

HTML_QuickForm ist ein sehr leistungsfähiges Paket für die Erstellung und Verarbeitung von Formularen. Erfordert Ihre Problemstellung allerdings ein Formular, das über mehrere Seiten geht, bietet QuickForm Ihnen keine Möglichkeit, die einzelnen Werte zwischenzuspeichern. Natürlich können Sie diese auch selbst in Sessions ablegen, aber es ist deutlich einfacher, an dieser Stelle auf HTML_QuickForm_Controller zurückzugreifen.
Das Paket gibt Ihnen die Möglichkeit, mehrere verschiedene Formulare in einer Datei elegant zu kombinieren und sicherzustellen, dass Werte, die eingegeben wurden, nicht verloren gehen. Hierbei stellt auch ein Vor- und Zurückblättern kein Problem dar. Zugegebenermaßen ist die Arbeit mit dem Paket nicht immer ganz trivial, da Funktionalitäten von HTML_QuickForm überschrieben werden müssen.
Für jedes Formular wird eine eigene Klasse angelegt, die die Klasse HTML_QuickForm_Page erweitert und die dort enthaltene Methode buildForm() überschreiben muss. Die Methode buildForm() ist eine Art Container, in der ein einzelnes Formular verwaltet wird. In der Methode muss allerdings kein neues HTML_QuickForm-Objekt instanziiert werden. Um die Methoden nutzen zu können, die zum Hinzufügen von Elementen, Regeln und Filtern dienen, greifen Sie auf $this zurück.
In der Methode muss die Eigenschaft _formBuilt mit dem Wert true belegt werden, um zu verdeutlichen, dass das Formular bereits einmal ausgegeben wurde. Beim Aufbau des Formulars können Sie alle Methoden nutzen, die in Abschnitt 17.9 beschrieben wurden. Allerdings können Sie hier noch keine Templates zuweisen.
Um HTML_QuickForm_Controller die Möglichkeit zu geben, die Formulare korrekt verwalten zu können, müssen Sie für das Vor- und Zurückblättern Submit-Buttons vorsehen. Um einen Button zum Vorwärtsblättern zu integrieren, nutzen Sie beispielsweise folgende Zeile:
$this->addElement('submit', $this->getButtonName('next'), 'Weiter >>');
Der Name des Buttons wird durch die Methode getButtonName() generiert und kann nicht selbst vergeben werden. Um vor- und zurückblättern zu können, benötigen Sie zwei Buttons. Wenn Sie diese zu einer Gruppe zusammenfassen, darf die Gruppe keinen Namen haben.
$navi[] = $this->createElement('submit', $this->getButtonName('back'), '<< Zurück'); $navi[] = $this->createElement('submit', $this->getButtonName('next'), 'Weiter >>'); $this->addGroup($navi, null, '', ' ');
Übergeben Sie der Gruppe einen Namen, werden Sie feststellen, dass Sie nicht zum vorhergehenden Formular zurückgelangen können. Wie Sie sehen, bekommt die Methode getButtonName() entweder die Konstante 'back' oder 'next' übergeben. Dies legt die Funktionalität des Buttons fest. Anstelle von Buttons können Sie natürlich auch auf Grafiken, also <input type ="image" ... />, zurückgreifen.
Blättern Sie von einem Formular zum anderen, so werden die eingegebenen Werte in einer Session abgelegt, die Sie selbst starten müssen, so dass ein einmal eingegebener Wert nicht verloren geht. Zusätzlich muss in jedem Formular definiert werden, welche »Aktion« auszuführen ist, wenn es abgeschickt wird, ohne dass einer der Buttons genutzt wurde. In Listing 17.24 finden Sie ein Beispiel, in dem in einem ersten Formular der Vorname und in einem zweiten der Nachname erfragt wird.
<?php require_once 'HTML/QuickForm/Controller.php'; require_once 'HTML/QuickForm/Action/Display.php'; // Session starten session_start(); // Klasse zur Ausgabe der ersten Seite class Form_Vorname extends HTML_QuickForm_Page { // buildForm gibt das eigentliche Formular aus public function buildForm() { //Speichern, dass das Formular aufgerufen wurde $this->_formBuilt = true; // Formular konstruieren $this->addElement('text', 'vorname', 'Ihr Vorname:'); $this->addElement('submit', $this->getButtonName('next'), 'Weiter >>'); // Regel hinzufuegen $this->addRule('vorname','Vorname erforderlich', 'required'); // Legt fest, was passieren soll, wenn das Formular nicht // ueber den Submit-Button abgeschickt wird. $this->setDefaultAction('next'); } } // Klasse fuer die zweite Seite class Form_Nachname extends HTML_QuickForm_Page { function buildForm() { $this->_formBuilt = true; $this->addElement('text', 'nachname', 'Ihr Nachname:'); //Buttons hinzufuegen $navi[] = $this->createElement('submit', $this->getButtonName('back'), '<< Zurück'); $navi[] = $this->createElement('submit', $this->getButtonName('next'), 'Fertig'); $this->addGroup($navi, null, '', ' '); $this->addRule('nachname', 'Der Nachname ist erforderlich', 'required'); $this->setDefaultAction('next'); } } // Klasse zur Ausgabe der Formulare class ActionDisplay extends HTML_QuickForm_Action_Display { // Methode _renderForm() ueberschreiben public function _renderForm($page) { // Neuen Renderer ableiten $renderer = $page->defaultRenderer(); // RequiredNote setzen; hier koennen auch // Templates zugewiesen werden $page->setRequiredNote('<span style="color:F00">*</span> Feld erforderlich.'); // Renderer-Objekt an ActionDisplay uebergeben $page->accept($renderer); echo $renderer->toHtml(); } } // Klasse zur Verarbeitung der Formulare class ActionProcess extends HTML_QuickForm_Action { // Methode zum Verarbeiten der Daten function perform($page, $actionName) { // Auslesen der Daten $values = $page->controller->exportValues(); echo 'Die Eingaben lauteten:<pre>'; var_dump($values); echo '</pre>'; } } // Neue Formular-Objekte mit eindeutigem Namen ableiten $seite1 = new Form_Vorname('seite1'); $seite2 = new Form_Nachname('seite2'); // Neues Controller-Objekt ableiten $controller = new HTML_QuickForm_Controller('namen', true); // Formularseiten hinzufuegen $controller->addPage($seite1); $controller->addPage($seite2); // Aktionen hinzufuegen $controller->addAction('display', new ActionDisplay()); $controller->addAction('process', new ActionProcess()); // Controller ausfuehren $controller->run(); ?>
Listing 17.24 Ausgabe eines einfachen Formulars mit QuickForm_Controller
Zusätzlich zu den Klassen für die Formulare müssen Sie noch die Klassen HTML_QuickForm_Action_Display und HTML_QuickForm_Action erweitern. Genauer gesagt muss die Klasse HTML_QuickForm_Action_Display nicht wirklich erweitert werden. In dieser Klasse müssen Sie die Methode _renderForm() nur dann überschreiben, wenn Sie eigene Templates verwenden wollen oder den Hinweis, dass eine Eingabe erforderlich ist, durch einen eigenen ersetzen wollen. Dabei ist es wichtig, dass Sie die Schritte, die in Listing 17.24 zu finden sind, mit aufgreifen. Das heißt, es muss ein Renderer-Objekt abgeleitet und der Seite zugewiesen werden. Der Aufruf der Methode setRequiredNote() ist optional.
Bei der Erweiterung der Klasse HTML_QuickForm_Action muss die Methode perform() überschrieben werden. Sie wird genutzt, um die Daten nach Ende der eigentlichen Abfragen zu verarbeiten. Die eingegebenen Informationen stellt $page->controller->exportValues() Ihnen zur Verfügung. Die exportValues()-Methode des enthaltenen Controller-Objekts liest die Eingaben aus der Session aus und gibt sie in einem Array zurück. In diesem Beispiel sieht der Aufbau des Arrays folgendermaßen aus:
array(2) { ["vorname"]=> string(7) "Carsten" ["nachname"]=> string(6) "Möhrke" }
Die Feldnamen dienen direkt als Schlüssel, ohne dass die Namen der Seiten zusätzlich einfließen.
Nachdem Sie die Klassen und Methoden erstellt haben, können Sie das eigentliche »Hauptprogramm« aufbauen. Um die einzelnen Formulare nutzen zu können, müssen Sie Objekte aus den dazugehörigen Klassen ableiten. Diese müssen einem HTML_QuickForm_Controller-Objekt zugewiesen werden. Dem Konstruktor dieses Objekts übergeben Sie zuerst einen eindeutigen Namen. Dieser ist insbesondere dann notwendig, wenn Sie mehrere Controller-Objekte in einer Datei verwenden, da diese anhand ihres Namens unterschieden werden. Der zweite Wert ist eine boolesche Konstante. Mit dieser definieren Sie, ob der Benutzer nur dann von einem Formular zum nächsten kommen kann, wenn die Regeln erfüllt werden (true). Wenn Sie ein false übergeben, werden die Regeln nicht geprüft.
Die einzelnen »Formular-Objekte« werden jeweils mit addPage() an das Controller-Objekt übergeben.
Zu guter Letzt werden noch den einzelnen Aktionen die neu erstellten Klassen zugewiesen. Das heißt, die Aktion 'display' bekommt mit $controller->addAction('display', new ActionDisplay()) die Klasse ActionDisplay zugewiesen. Auch diese Zeile ist nur dann notwendig, wenn der Darstellungsprozess durch Einsatz von Templates o. Ä. verändert werden soll. Der Aktion 'process' muss jedoch die Klasse zugewiesen werden, die die Daten verarbeiten soll. Andernfalls würden die Daten nicht ausgewertet, was das Formular ad absurdum führen würde. In der letzten Zeile von Listing 17.24 wird die Verarbeitung der Daten dann schließlich mit der Methode run() gestartet.
Das ist nur ein relativ kurzer Abriss dessen, was HTML_QuickForm_Controller leisten kann. Aus Platzgründen ist es hier aber nicht möglich, komplexere Beispiele zu bringen. So ist es beispielsweise möglich, das Erscheinungsbild des zweiten Formulars von den Eingaben im ersten abhängig zu machen. Dazu ist es dann allerdings notwendig, die Klassen für die Aktionen 'next' und 'back' zu überschreiben. Hierzu sind allerdings gute Beispiele in dem Archiv des Pakets enthalten.