Automatische Generierung und Validierung von Formularen mit PEAR::HTML_QuickForm

Formulare für alle Fälle
Kommentare

Was wäre eine Web-Applikation ohne Formulare? Wahrscheinlich hat fast jeder PHP-Programmierer schon viel Zeit investiert, um die immer wiederkehrenden HTML-Eingabemasken zu erstellen. Da bleibt kaum Zeit, um Funktionen zur Validierung der Daten zu schreiben. Wäre es nicht schön, diese Aufgabe zu automatisieren? Genau dafür ist das Paket HTML_QuickForm gedacht. Dieser Artikel soll Ihnen zeigen, wie man sich mit QuickForm viel Arbeit erspart und ganz nebenbei seine Applikation professioneller gestaltet. Die kompletten Listings finden Sie aus Platzgründen auf der CD.

Formulare sind einer der wichtigsten Bausteine jeder Web-Applikation. Sie stellen das Bindeglied zwischen dem Benutzer und der Applikation bzw. der Datenbank dar. Entsprechend oft wiederholt sich für den Programmierer immer wieder das gleiche Spiel: Ein Formular mit Daten füllen, dieses dem Benutzer im Browser zur Verfügung stellen, die zurück gelieferten Daten überprüfen und am Ende das Ergebnis weiter verarbeiten (z.B. in einer Datenbank speichern oder daraus wieder ein neues Formular erstellen). Hier machen sich Viele das Leben unnötig schwer, indem sie für jedes Formular zahlreiche Funktionen immer wieder neu Programmieren. Man muss jedoch nicht jedes Mal das Rad neu erfinden. QuickForm bietet für fast alle wiederkehrenden Aufgaben beim Erstellen von Eingabeformularen eine schnelle und komfortable Lösung. Diese Klasse bzw. Klassensammlung stellt nicht nur zahlreiche Funktionen zum Erstellen von Formularen, sondern auch zur Validierung der daraus gewonnenen Daten zur Verfügung. Letzteres ist vor allem dann wichtig, wenn man die Benutzereingaben anhand bestimmter Kriterien überprüfen möchte, bevor man sie weiter benutzt. So sollten z.B. wichtige Felder nicht unbesetzt bleiben und eine eingegebene eMail-Adresse muss auf syntaktische Korrektheit geprüft werden. Dies alles lässt sich mit Hilfe von QuickForm effizient erledigen. Zudem ist die direkte Zusammenarbeit mit den Template Engines Smarty, ITX, Sigma und Flexy möglich. In diesem Artikel behandeln wir die Version 3.2. Die Beispiele sollten jedoch mit allen 3.x Versionen funktionieren. QuickForm kann ganz einfach über den Befehl pear install HTML_QuickForm installiert werden. Eventuell benötigt man noch das PEAR-Paket HTML_Common. Alternativ lässt sich auch das tgz-Archiv unter der Adresse pear.php.net/package/HTML_QuickForm herunterladen und mit dem Befehl pear install HTML_QuickForm-3.2.tgz installieren. Des weiteren findet man auf dieser Seite eine ausführliche Referenz aller Klassen und Funktionen, die von QuickForm angeboten werden.

<img src="http://cdn.sandsmedia.com/ps/onlineartikel/pspic/picture_file//60/import400e49f2aa108.bmp<
Abb. 1: Ein erstes Formular

Zum Erstellen eines neuen Formulars benötigen wir zunächst eine Instanz der Klasse HTML_QuickForm. Diese wird wie folgt erstellt:

Als ersten Parameter erwartet der Konstruktor den Namen des Formulars, wie er auch im form-Tag in HTML angegeben wird. Danach wird definiert, auf welche Weise (POST oder GET) die Daten wieder zum PHP-Skript zurückgeliefert werden. Zuletzt könnte man noch eine URL-Adresse angeben, an die die Daten geschickt werden. Normalerweise lässt man diesen Parameter jedoch weg, womit die Daten an das gleiche Skript zurückgesendet werden, das das Formular auch generiert hat. Wozu dies gut ist, werden wir später noch sehen. Jetzt wollen wir natürlich auch ein paar Elemente zu unserem Formular hinzufügen. Hierfür benutzen wir die Funktion addElement():

$form->addElement('header', 'myHeader', 'Newsletter abbonieren!');
$form->addElement('text', 'firstName', 'Vorname:');
$form->addElement('checkbox', 'inMailList', 'In Mailing-Liste aufnehmen:');

Alle Aufrufe von addElement() sollten mindestens die drei Parameter haben: Typ des Elements, zugehöriger Name (der das Element eindeutig identifiziert) und eine Zeichenkette, die als Label zusammen mit dem Element ausgegeben wird. Für den Elementtyp kann jedes von HTML her bekannte Element gewählt werden, so wie in diesem Beispiel text (Eingabefeld für Zeichenkette) und checkbox (ankreuzbares Kästchen). header ist ein von QuickForm zur Verfügung gestelltes Pseudoelement, das eine Kopfzeile zur Verschönerung des Formulars und zur visuellen Gruppierung der darunter liegenden Elemente erzeugt. In unserem Beispiel möchten wir vom Benutzer wissen, an welchem Tag er geboren ist. In reinem HTML/PHP hätten wir für die Erstellung eines Datum-Auswahlfelds viel Zeit und Code benötigt. Mit QuickForm können wir jedoch das Element date benutzen, aus dem QuickForm automatisch drei Auswahlfelder (je eins für Tag, Datum und Jahr) erzeugt. Um die Parameter für diese Auswahlfelder festzulegen, geben wir der Funktion addElement() noch ein Feld als vierten Parameter an:

$form->addElement('date', 'birthday', 'Geboren am:', array('format'=>'d-F-Y', 'language'=>'de', 'minYear'=>1900, 'maxYear'=>2000));

Damit legen wir neben dem Format und der Sprache (wichtig für die Monate, wenn sie als ausgesprochene Wörter bzw. in der abgekürzten Schreibweise aufgelistet werden) auch das Zeitintervall für die Jahre fest. Da QuickForm bei dem Datumsformat kompatibel zu der PHP-Funktion date() ist, können Sie zu dessen Einzelheiten in der PHP-Referenz unter der besagten Funktion nachsehen. Bevor das ganze Formular generiert wird, wollen wir noch einigen Elementen Standardwerte zuweisen. Diese Werte würden in der Praxis sicherlich aus einer Datenbank oder einer Konfigurationsdatei kommen. Die Definition in QuickForm bleibt jedoch dieselbe. Zum Festlegen der Standardwerte erstellen wir ein assoziatives Feld, welches das Format ElementName=>Wert besitzt. Dieses wird an die Funktion setDefaults() übergeben. Auf gleiche Weise kann man den einzelnen Elmenten auch konstante Werte zuordnen. Allerdings wird dabei das Feld an die Funktion setConstants() weitergeleitet. Konstanten unterscheiden sich von Standardwerten dadurch, dass sie im weiteren Verlauf des Skripts nicht mehr geändert werden können. Sie sollten jedoch beachten, dass die Werte der Elemente nur im PHP-Skript konstant sind. Der Benutzer kann sie, soweit das HTML-Element aktiviert und beschreibbar ist, durchaus ändern.

Erweiterte Elemente

Die Klasse HTML_QuickForm verwaltet alle Elemente eines Formulars. Die einzelnen Elemente sind dabei Instanzen der Klasse HTML_QuickForm_element. Möchte man einzelne Elemente, nachdem sie in einem Formular erstellt worden sind, bearbeiten, so kann man sich deren Referenzen mit Hilfe der Funktion getElement() zurückgeben lassen. In unserem Beispiel können wir auf diese Weise das Aussehen des select-Elements manipulieren:

$select = &$form->getElement('newsletter');
$select->setSize(4);
$select->setMultiple(true);

Bisher sind wir davon ausgegangen, dass jedes Element einzeln für sich steht. Oft jedoch werden mehrere Elemente zu einer logischen Einheit zusammengefasst. Besonders häufig werden Check- oder Radioboxen in einer solchen Elementgruppe gesammelt. Um eine Gruppe von Elementen in QuickForm zu realisieren, müssen wir zuerst ein Feld mit allen Formular-Elementen, die zu einer Gruppe gehören sollen, erstellen. Dafür benutzen wir die statische Funktion createElement():

$checkbox = array();
$checkbox[] = HTML_QuickForm::createElement('checkbox', 'garden', null, 'Gartenarbeit');
...
$form->addGroup($checkbox, 'hobby', 'Ihre Hobbys:', ' ');

In diesem Beispiel übergeben wir beim Erstellen eines neuen Checkbox-Elements noch einen vierten Parameter an den Konstruktor. Dabei handelt es sich um den Text, der hinter einer Checkbox erscheint. Sie sollten sich im Übrigen nicht wundern, wenn die Anzahl und Art der Parameter bei verschiedenen Elementtypen unterschiedlich sein sollten. Sowohl die Funktion addElement() als auch createElement() erwarten eigentlich nur einen Parameter, nämlich die Angabe des Elementtyps. Anhand dieser Angabe wird die richtige Klasse für das Element ausgewählt (jeder Elementtyp ist eine eigene Klasse, die von HTML_QuickForm_element abgeleitet ist). Die übrigen Parameter werden an den Konstruktor dieser neuen Klasse weitergeleitet.

Datenverarbeitung

Jetzt sind wir an dem Punkt angekommen, wo wir bereits ein einfaches Formular besitzen, in das der Benutzer seine Daten eintragen kann. Drückt der Anwender auf den OK-Button, so werden die Formulardaten an das Skript zurückgeschickt. Wie können wir nun auf diese Daten zugreifen? Schauen wir uns dazu die letzen Zeilen von Listing 1 an:

if ($form->validate()) {
$form->process('process_data', false);
} else {
$form->display();
}

Ein Formular, das mit QuickForm erstellt wurde, kennt zwei Zustände: Entweder soll es noch dargestellt werden oder es wurde bereits von einem Benutzer ausgefüllt und die Daten wieder an das Skript zurückgeschickt. Im zweitem Fall wird zusätzlich unterschieden, ob die Validierung der Daten, auf die wir gleich noch zu sprechen kommen, erfolgreich war oder nicht. Die Funktion validate() überprüft, in welchem Zustand sich das Formular befindet. Soll es zum ersten Mal gezeichnet werden, so gibt sie ein false zurück und das Formular wird mit Hilfe von display() im Browser ausgegeben. Der gleiche Wert wird aber auch dann zurückgeliefert, falls bereits Daten von dem Formular an das Skript geschickt wurden, diese aber nicht korrekt validiert werden konnten. In diesem Fall muss der Benutzer einige Daten erneut eingeben, weswegen das Formular nochmals, eventuell durch aussagekräftige Fehlermeldungen erweitert, gezeichnet wird. Nur unter der Bedingung, dass alle Daten die Validierung bestehen, liefert validate() ein true zurück. Jetzt können die Daten im PHP-Skript weiter bearbeitet werden. Hierfür haben wir uns eine eigene Funktion process_data() geschrieben, die alle Formulardaten in ihrer Rohform anzeigt. Diese Funktion wird durch die QuickForm-Funktion process() mit den validierten Formulardaten aufgerufen. So kann process_data() immer davon ausgehen, dass sie nur mit korrekten Daten gestartet wird. Sie selbst braucht sich nicht mehr um das Testen zu kümmern.

Filter und Validierung

applyFilter(‚firstName‘, ‚trim‘);. Anstatt eines konkreten Elementnamens können wir auch ‚__ALL__‘ angeben, was zur Folge hat, dass der angegebene Filter auf alle Elemente des Formulars angewendet wird. Als Filterfunktion kann jede beliebige Funktion genutzt werden, die einen String als Parameter erwartet und einen String zurück liefert. Regeln werden ähnlich wie Filter für die einzelnen Formular-Elemente definiert. Hier ein Ausschnitt aus Listing 2, das unser erstes Beispiel um einen Filter und ein kleines Regelwerk erweitert:

$form->addRule('firstName', 'Bitte hier den Vornamen eingeben:', 'required');
$form->addRule('surname', 'Nachname muss mindestens 5 Zeichen lang sein:', 'minlength', 5);

Damit fügen wir dem Formular zwei Regeln hinzu. Mit der ersten gehen wir sicher, dass der Benutzer seinen Vornamen eingeben muss, um einen Newsletter zu abonnieren. Die zweite Regel sorgt dafür, dass der Nachname, sofern er angegeben wird, mindestens fünf Zeichen lang sein muss. Für jedes Element können beliebig viele Regeln zur Validierung der Daten definiert werden. Neben der Angabe des Elementnamens erwartet die Funktion addRule() eine Fehlermeldung, die neben dem Element erscheint, falls das Datum des Elements nicht validiert werden konnte. Als dritten Parameter müssen wir noch angeben, anhand welcher Regel die Überprüfung erfolgen soll. QuickForm bringt von vorn herein zahlreiche Regeln mit. Tabelle 1 zeigt die wichtigsten davon.

Regel Beschreibung
required Feld darf nicht leer sein
maxlength Maximale Länge des Feldes
minlength Minimale Länge des Feldes
rangelength Länge des Feldes darf nur im angegebenen Intervall liegen
email Feld ist syntaktisch eine gültige eMail Adresse
regex Feld passt zu dem angegebenen Regulären Ausdruck
lettersonly Feld darf nur aus Buchstaben bestehen
alphanumeric Feld darf nur aus Buchstaben und Zahlen bestehen
numeric Feld muss eine Zahl sein

QuickForm ist jedoch nicht nur auf seine eigenen Validierungsregeln beschränkt. Jede Funktion, die einen String entgegennimmt und einen booleschen Wert zurückliefert, kann zum Validieren von Daten genutzt werden. Sie muss lediglich als Regel mit Hilfe der Funktion registerRule() registriert werden. So haben wir in unserem zweiten Beispiel eine Funktion checkMailInDatabase() eingebaut, die in einer Datenbank prüft, ob die eMail des Benutzers bereits registriert ist. Ist dies der Fall, so bekommt der Benutzer eine entsprechende Fehlermeldung geliefert und darf sich nicht erneut unter dieser eMail-Adresse im System registrieren. Bisher wurde die Validierung auf dem Server ausgeführt. Es kann aber durchaus nützlich sein, diese bereits im Browser mit Hilfe von JavaScript durchzuführen. Um eine Regel so zu erweitern, dass sie clientseitig durchgeführt wird, muss lediglich der Funktion addRule() als fünfter Parameter die Zeichenkette ‚client‘ angegeben werden (’server‘ ist der Standardwert dieses Parameters). Diese Felder werden vor dem Submit des Formulars validiert. Im Falle eines Fehlschlags öffnet sich eine Browser-Box, die die entsprechenden Fehlermeldungen ausgibt. Da man sich jedoch meistens nicht darauf verlassen kann, dass im Browser JavaScript aktiviert ist, sollte für kritische Überprüfungen entweder auf die Validierung im Browser verzichtet oder die gleiche Regel, jedoch diesmal serverseitig, dem Element hinzufügt werden. Beim Zusammenstellen von Filtern und Regeln, sollte man zusätzlich beachten, dass QuickForm zuerst die Filter auf die Formulardaten anwendet und erst dann versucht, diese zu validieren.

Individuelle Gestaltung

Das Aussehen unseres Formulars ist schon ganz nett, einige Sachen würden wir aber sicherlich gerne anpassen. Auch hier zeigt sich QuickForm äußerst flexibel. Zuerst werden wir den dezenten Text, der den Benutzer auf die Pflichtfelder aufmerksam macht, ändern. Mit Hilfe der Funktion setRequiredNote() können wir einen beliebigen HTML-Text eingeben, der dann anstelle der bisherigen, englischen Variante ausgegeben wird. QuickForm ist nicht selber für das Zeichnen von Formularen verantwortlich, sondern überlässt diese Arbeit einem Renderer, der ein Objekt der Klasse HTML_QuickForm_Renderer_Default ist. Eine Referenz auf dieses Objekt können wir uns mit Hilfe der Funktion defaultRenderer() angeben lassen. Damit ist es möglich das gesamte Aussehen sowohl des Formulars als auch jedes einzelnen Elements zu ändern. Zum Zeichnen benutzt der Renderer einfache Templates, die über die drei Funktionen setFormTemplate(), setHeaderTemplate() und setElementTemplate() neu gesetzt werden können. Widmen wir uns zuerst dem grundlegenden Aussehen des Formulars. QuickForm stellt den gesamten Inhalt in einer Tabelle dar und erwartet daher das Template in der folgenden Form:

{content}

Die beiden Platzhalter {attributes} und {content} werden vom Renderer vorausgesetzt und entsprechend ersetzt. In unserem dritten Beispiel (Listing 3), bei dem wir das Aussehen des Anmeldefensters für den Newsletter unseren Wünschen anpassen, zentrieren wir das ganze Formular und weisen der Tabelle eine CSS-Klasse zu. Ähnlich gestaltet sich die Anpassung des Templates für die Header, dessen Standardform wie folgt aussieht:

{header}

Zuletzt passen wir das Aussehen der eigentlichen Formular-Elemente an. Das Ausgangstemplate ist dafür etwas komplexer:


*
{label}


{error}
{element}

Die drei Platzhalter {label}, {error} und {element} nehmen jeweils den HTML-Code für die Textbeschreibung, die Fehlermeldung und das eigentliche Element auf. Zusätzlich finden wir noch zwei HTML-Kommentare vor, die unbedingt erforderlich sind. Der Kommentar required umschweift den Code, der neben den notwendigen Elementen ausgegeben wird (standardmäßig ist dies ein roter Stern), error markiert die Fehlermeldung, die bei gescheiterter Validierung über dem Element dargestellt werden soll. Abpictureung 2 zeigt unser fertiges Beispiel mit neuem Aussehen.

<img src="http://cdn.sandsmedia.com/ps/onlineartikel/pspic/picture_file//60/import400e49f2b1683.bmp<
Abb. 2: Altes Formular, neues Aussehen

Wenden wir uns einem etwas anderen Thema zu, dem Upload von Dateien über den Browser. Auch für dieses, oft auftretende Problem, hat QuickForm eine schnelle und saubere Lösung parat: das Element file. Dass man damit ohne viel Aufwand eine Upload-Funktion erzeugt, zeigt der folgende Ausschnitt aus Listing 4:

$form->addElement('header', 'myHeader', 'Newsletter abbonieren!');
$form->addElement('text', 'firstName', 'Vorname:');
$form->addElement('checkbox', 'inMailList', 'In Mailing-Liste aufnehmen:');

Das file-Element, von dem wir uns eine Referenz zurückgeben lassen, sorgt vorerst nur dafür, dass im Browser ein normales Text-Eingabefeld und daneben ein Durchsuchen-Button erscheint. Über diesen Button öffnet sich der bekannte Windows-Dialog zur Auswahl einer Datei. Bestätigt der Benutzer das Formular, so gelangen wir zu dem positiven Zweig der if-Anweisung. Die Funktion isUploadedFile() überprüft für uns, ob der Benutzer eine Datei ausgewählt hat und diese auch erfolgreich zum Server transportiert werden konnte. Nun können wir ganz bequem die Datei mit Hilfe der Funktion moveUploadedFile() in ein Verzeichnis unserer Wahl verschieben und bei Übergabe eines zweiten Parameters auch gleich umbenennen. Mit getValue() bekommen wir zudem einige Informationen wie z.B. den Originalnamen und Größe der Datei geliefert. Die Klasse HTML_QuickForm_file, die alle die Hilfsmittel rund um den Datei-Upload bereitstellt, fügt außerdem vier nützliche Validierungsregeln dem schon vorhandenen Regelwerk hinzu:

  • uploadedfile: Benutzer muss Datei ausgewählt haben und diese beim Server angekommen sein.
  • maxfilesize: Datei darf die in Byte angegeben Größe nicht überschreiten.
  • mimetype: Datei muss vom angegebenen MIME-Typ sein.
  • filename: Prüft, ob Dateiname mit dem angegebenen Regulären Ausdruck übereinstimmt.

HTML_QuickForm bringt eine Menge von Klassen mit sich, die dem Programmierer von Web-Applikationen beim Erstellen von Eingabeformularen oft unter die Arme greifen. Damit kann man sich oft viel Ärger vom Hals halten und vor allem Zeit sparen. Leider konnten in diesem Artikel bei weitem nicht alle Möglichkeiten, die dieses mächtige Paket liefert, vorgestellt werden. Wer QuickForm intensiv einsetzen möchte, sollte sich vor allem die Möglichkeit der Einbindung in eine der vier weiter oben genannten Template-Engines genauer anschauen. Ansonsten kann man jedem, der sich in die Materie weiter vertiefen möchte, die gute Dokumentation aller Klassen von QuickForm unter pear.php.net/manual/en/package.html.html-quickform.php wärmstens empfehlen.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -