Adventure,PHP,Framework,PageController,FrontController,Pattern,Objektorientierung,OO,Software,Design,Wiederverwendbarkeit,UML,Tutorial,Benchmark,ausgezeichnete Performance

Suche:    
Downloads  |  SVN!  |  Roadmap  |  Forum!  |  Bugtracking  |  Gästebuch  |  Backlinks!  |  Referenzen!  |  Sitemap  |  Impressum  
 
Deutsch | English Adventure PHP Framework  Bookmark @ Technorati Bookmark @ del.icio.us Bookmark @ Mr. Wong Bookmark @ Simpy Bookmark @ Google Bookmark @ Digg.com Adventure PHP Framework Seite 011-Formulare drucken!

Formulare

Artikel bewerten:
Bitte bewerten Sie den Artikel per Klick auf einen der angezeigten Sterne:
Zurück zum Artikel!
Das Adventure-PHP-Framework unterstützt die dynamische Generierung und Abstraktion von Formularen out-of-the-box. Durch den generischen Tag-Parser können Formulare durch Tags in Templates und die entsprechenden DOM-Objekte im Objektbaum der Präsentations-Schicht abgebildet werden. Dadurch ist es möglich Formular-Elementen "interne Intelligenz" mitzugeben. Hierrunter fällt das automatische Ausfüllen anhand eines URL-Parameters und die Validierung von Benutzereingaben. Dies beiden Features können einfach durch die Definition des Verhaltens in den Templates gesteuert werden und der Entwickler benötigt keine weiteren Hilfmittel und Logiken mehr.


1. Aufbau von Formularen

Formulare werden im Framework wie Templates behandelt und sind Kinder eines Baum-Knotens. Mit der Methode __getForm() kann innerhalb eines Document-Controllers auf ein Formular zugegriffen werden. Das Formular unterstützt folgende wichtige Funktionen:
  • addFormElement()
    Fügt ein Formular-Element zum Formular hinzu. Die Methode ist für die dynamische Generierung von Formularen gedacht.
  • addFormContent()
    Fügt (HTML-/Text-)Inhalt zum Formular hinzu. Die Methode ist für die dynamische Generierung von Formularen gedacht.
  • addFormContentBeforeMarker()
    Fügt (HTML-/Text-)Inhalt vor einem Marker-Tag zum Formular hinzu. Die Methode ist für die dynamische Generierung von Formularen gedacht.
  • addFormContentAfterMarker()
    Fügt (HTML-/Text-)Inhalt nach einem Marker-Tag zum Formular hinzu. Die Methode ist für die dynamische Generierung von Formularen gedacht.
  • addFormElementBeforeMarker()
    Fügt ein Formular-Element vor einem Marker-Tag zum Formular hinzu. Die Methode ist für die dynamische Generierung von Formularen gedacht.
  • addFormElementAfterMarker()
    Fügt ein Formular-Element nach einem Marker-Tag zum Formular hinzu. Die Methode ist für die dynamische Generierung von Formularen gedacht.
  • setPlaceHolder()
    Füllt einen angegebenen Platzhalter mit einem Wert.
  • setAction()
    Setzt das "action"-Attribut des Formulars.
  • getFormElementByName()
    Gibt eine Referenz auf ein Formular-Objekt zurück.
  • getFormElementByID()
    Gibt eine Referenz auf ein Formular-Objekt zurück.
  • getFormElementByObjectID()
    Gibt eine Referenz auf ein Formular-Objekt zurück.
  • transformForm()
    Erzeugt die HTML-Ausgabe eines Formular-Objekts und gibt diese zurück.
  • transformOnPlace()
    Definiert, dass das Formular an der Stelle, an der es im Template-File definiert wurde ausgegeben wird. Damit ist es nicht mehr nötigt, das Formular per transformForm() zu transformieren und in einen Platzhalter einzusetzen.
Um ein Formular in einer Template-Datei zu definieren muss zuerst per
  <core:addtaglib namespace="tools::form::taglib" prefix="html" class="form" />
vor der Verwendung hinzugefügt werden. Anschließend kann beispielsweise ein Formular einer Login-Maske definiert werden:
  <html:form name="AdminLogin" method="post" action="">
    <form:placeholder name="LogInError" />
    Benutzer: <form:text name="Username" class="eingabe_feld" style="width: 200px; margin-left: 20px;"
    validate="true" button="AdminLogin" />
    <br />
    Passwort: <form:password name="Password" class="eingabe_feld" style="width: 200px; margin-left: 16px;"
    validate="true" button="AdminLogin" />
    <br />
    <br />
    <form:button name="AdminLogin" value="Login" class="eingabe_feld" style="margin-left: 227px;"/>
  </html:form>
In Prosa: das Formular definiert die Attribute name, damit im Controller später auf dieses zugegriffen werden kann, method um die Methode des Abschickens zu definieren und action um die Ziel-URL zu definieren. Letzteres muss in der Template- Datei nicht zwingend gesetzt werden, da die TagLib dieses selbst mit der aktuellen URL setzt oder füllt, falls es nicht vorhanden ist.

Innerhalb des Formulars werden viel Formular-Elemente definiert: ein Platzhalter, für die Aufnahme von Hinweistexten, ein Text- und ein Passwort-Feld und ein Button. Diese sind jeweils mit den unter Standard-TagLibs beschriebenen Attributen ausgestattet. Im Document-Controller kann nun per
  $Form__AdminLogin = &$this->__getForm('AdminLogin'); 
eine Referenz auf das Formular geholt werden. Anschließend kann per
  $Form__Placeholder_LogInError = &$Form__AdminLogin->getFormElementByName('LogInError');
  
$Form__Placeholder_LogInError->setPlaceHolder('Login failed!'); 
der Inhalt des Platzhalters manipuliert oder mit
  if($Form__AdminLogin->get('isValid') && $Form__AdminLogin->get('isSent')){

     
// Aktion ausführen, die bei abgeschicktem und
     // valide ausgefülltem Formular passieren soll...

   // end if
  
abgefragt werden, ob das Formular abgeschickt wurden und die Eingaben valide sind.

Um das Formular auszugeben gibt es zwei Möglichkeiten: Ausgabe über einen im Template-File definierten Platzhalter oder Verwendung von transformOnPlace():
   function transformContent(){

      ...

      
// Formular transformieren und in einen Platzhalter einsetzen ...
      
$this->setPlaceHolder('...',$Form__AdminLogin->tranformForm());

      
// ... oder das Formular an der Definitionsstelle ausgeben
      
$Form__AdminLogin->tranformOnPlace();

      ...

    
// end function
   

2. Validierung

Wie bereits erwähnt ist die Validierung von Formular-Feldern bereits out-of-the-box möglich. Hierzu muss ein Formular-Feld lediglich um die Attribute
  • validate
  • validator
  • button
wie unter Standard-TagLibs, Kapitel 2.3., beschrieben, erweitert werden. Für die Validierung des oben genannten Login-Formulars muss das Textfeld wie folgt definiert werden:
  <form:text name="Username" validate="true" button="AdminLogin" />
Wichtig ist die Angabe des Button-Namens, da das Formular erst nach dem Abschicken validiert werden soll. Ist das Button-Attribut nicht gesetzt, wird von der TagLib ein Fehler ausgegeben. Zur Ausgabe-Formatierung kann dieser Tag um weitere Attribute wie "class" und style" erweitert werden.
  <form:text name="Username" class="eingabe_feld" style="width: 200px; margin-left: 20px;"
  validate="true" button="AdminLogin" />
Ist das Attribut "validator" nicht gesetzt, so wird validiert, ob das Feld > 3 Zeichen enthält.


3. Manipulation von Formularwerten

Die Implementierung der Formular-TagLibs des Frameworks bringt einige Möglichkeiten zur Manipulation von Formularelementen oder deren Werte mit. Die folgenden Kapitel zeigen häufig auftretende Anwendungsbeispiele.


3.1. Vorbefüllung von Formularen

Zur Vorbefüllung von Formularen (z.B. in einem Bearbeiten-Dialog) können Methoden getFormElementByID(), getFormElementByID() oder getFormElementByObjectID() eingesetzt werden um eine Referenz auf ein Formular-Element zu beziehen. Anschließend stehen die Standard-Methoden get() und getAttribute(), bzw. set() und setAttribute() zur Verfügung.

Die folgenden Codebox definiert ein Beispiel-Formular, das im anschließend abgedruckten PHP-Code befüllt wird:
  <core:addtaglib namespace="tools::form::taglib" prefix="html" class="form" />
  <html:form name="UserEdit" method="post">
    <strong>FirstName</strong>:
    <form:text name="FirstName" validate="true" button="Edit" />
    <br />
    <strong>LastName</strong>:
    <form:text name="LastName" validate="true" button="Edit" />
    <br />
    <br />
    <form:button name="Edit" value="Save" />
    <form:hidden name="userid" />
  </html:form>
   // Referenz auf das Form-Objekt beziehen
   
$Form__Edit = &$this->__getForm('UserEdit');

   
// Referenz auf das Hidden-Feld beziehen und Wert befuellen
   
$UserID = &$Form__Edit->getFormElementByName('userid');
   
$UserID->setAttribute('value','...');

   
// Referenz auf das FirstName-Feld beziehen und Wert befuellen
   
$FirstName = &$Form__Edit->getFormElementByName('FirstName');
   
$FirstName->setAttribute('value','...');

   
// Referenz auf das LastName-Feld beziehen und Wert befuellen
   
$LastName = &$Form__Edit->getFormElementByName('LastName');
   
$LastName->setAttribute('value','...'); 

3.2. Befüllen von Select-Feldern

Die Behandlung Select- und Multiselect-Feldern unterscheidet sich ein wenig von einfachen Formular-Elementen. Das Framework stellt jedoch auch hier Methoden zur Verfügung, mit denen das Befüllen von Feldern vereinfacht wird. Im nachfolgend aufgeführten Code wird ein Formular vorausgefüllt, das zusätzlich zu den Standard-Text-Felder auch Auswahlfelder beinhaltet:
  <core:addtaglib namespace="tools::form::taglib" prefix="html" class="form" />
  <html:form name="UserCreate" method="post">
    <strong>Salutation</strong>:
    <form:select name="Salutation" />
    <br />
    <strong>FirstName</strong>:
    <form:text name="FirstName" validate="true" button="Edit" />
    <br />
    <strong>LastName</strong>:
    <form:text name="LastName" validate="true" button="Edit" />
    <br />
    <br />
    <strong>Salutation</strong>:
    <br />
    <form:multiselect name="Group[]" validate="true" button="Edit" />
    <br />
    <br />
    <form:button name="Edit" value="Save" />
    <form:hidden name="userid" />
  </html:form>
Wie in der Definition des Multiselect-Feldes Groups[] zu sehen ist, müssen bei einem Multiselect-Feld die Namen eckigen Klammern versehen werden. Vergisst der Template-Entwickler dies, wird eine entsprechende Fehlermeldung ausgegeben.

Der folgende PHP-Code befüllt das Formular:
   // Referenz auf das Form-Objekt beziehen
   
$Form__Create = &$this->__getForm('UserCreate');

   ...

   
// Referenz auf das Salutation-Feld beziehen und Wert befuellen
   
$Salutation = &$Form__Create->getFormElementByName('Salutation');

   for(
$i 0$i count($Salutations); $i++){
      
$Salutation->addOption($Salutations[$i]['Value'],$Salutations[$i]['DisplayName']);
    
// end for
   
}


   
// Referenz auf das Groups[]-Feld beziehen und Werte befuellen
   
$Group = &$Form__Create->getFormElementByName('Groups[]');

   for(
$i 0$i count($Groups); $i++){
      
$Group->addOption($Groups[$i]['Value'],$Groups[$i]['DisplayName']);
    
// end for
   
}

   ... 

3.3. Auslesen von Formular-Elementen

Das Auslesen von Formular-Elementen gestaltet sich ähnlich wie das Befüllen. Eine Besonderheit stellen auch hier die Einfach- und Mehrfachselektionsfelder dar. Das folgende Code-Beispiel zeigt, wie die Werte des unter 3.1 dargestellten Formulars im DocumentController ausgelesen werden können:
   // Referenz auf das Form-Objekt beziehen
   
$Form__Edit = &$this->__getForm('UserEdit');

   
// Hidden-Feld auslesen
   
$UserID = &$Form__Edit->getFormElementByName('userid');
   echo 
$UserID->getAttribute('value');

   
// FirstName-Feld auslesen
   
$FirstName = &$Form__Edit->getFormElementByName('FirstName');
   echo 
$FirstName->getAttribute('value');

   
// LastName-Feld auslesen
   
$LastName = &$Form__Edit->getFormElementByName('LastName');
   echo 
$LastName->getAttribute('value'); 
Um die selektierten Optionen eines Einfach- oder Mehrfachselektionsfeldes auszulesen, stehen die Methoden getSelectedOption() und getSelectedOptions() zur Verfügung. Die folgende Codebox zeigt den Anwendungsfall:
   // Referenz auf das Form-Objekt beziehen
   
$Form__Create = &$this->__getForm('UserCreate');

   
// Feld Salutation fuellen
   
$Salutation = &$Form__Create->getFormElementByName('Salutation');
   for(
$i 0$i count($Salutations); $i++){
      
$Salutation->addOption($Salutations[$i]['Value'],$Salutations[$i]['DisplayName']);
    
// end for
   
}

   
// Salutation auslesen
   
$Option = &$Salutation->getSelectedOption();
   echo 
$Option->getAttribute('value').', '.$Option->get('Content');


   
// Feld Group fuellen
   
$Group = &$Form__Create->getFormElementByName('Groups[]');

   for(
$i 0$i count($Groups); $i++){
      
$Group->addOption($Groups[$i]['Value'],$Groups[$i]['DisplayName']);
    
// end for
   
}

   
// Gruppen auslesen
   
$SelectedGroups = &$Group->getSelectedOptions();
   for(
$i 0$i count($SelectedGroups); $i++){
      echo 
$SelectedGroups[$i]->getAttribute('value').', '.$SelectedGroups[$i]->get('Content');
    
// end for
   

4. Dynamische Formulare

In einigen Anwendungsfällen ist es notwenig, Formulare dynamisch nach Anforderung zu erstellen. Hierzu besitzt die Implementierung der Formular-TagLib (html_taglib_form) die Methoden
  • addFormElement()
  • addFormContent()
und seit dem Release 1.7
  • addFormContentBeforeMarker()
  • addFormContentAfterMarker()
  • addFormElementBeforeMarker()
  • addFormElementAfterMarker()
an. Die ersten beiden Funktionen lassen sich dazu nutzen, Inhalte oder konkrete Formular-Elemente an das Ende des Formulars anzuhängen. Die zu letzt genannten Methoden sind dazu gedacht, Inhalte oder Formular-Elemente an konkreten Stellen zu platzieren. Zur Positionierung steht das <form:marker />-Tag zur Verfügung. Das Tag selbst generiert keine Ausgabe, sondern dient lediglich als Positionierungshilfe.

Die folgenden Kapitel sollen zeigen, wie ein dynamisches Formular zur Eingabe von Form-Koordinaten (Dreieck, Quadrat, ...) realisiert werden kann. Je nach Auswahl des Typs sollen die jeweils notwenigen Felder angezeigt werden. Bei Auswahl des Typs "square" werden vier Felder angezeigt ...

APF - Dynamische Formular-Generierung; Auswahl des Typs square

... und bei Auswahl von "triangle" drei:

APF - Dynamische Formular-Generierung; Auswahl des Typs triangle


4.1. Formular-Definition

Bei der Definition des Formulars sollte bereits bedacht werden, welche Art der Formular-Generierung angestrebt wird. Kommen die Methoden addFormElement() und/oder addFormContent() zum Einsatz, ist keinen Marker erforderlich. In diesem Beispiel wird jedoch ein Marker eingesetzt, da das Formular bereits Inhalte besitzt, die nach den dynamisch erzeugten Elementen angezeigt werden sollen.

Die folgende Code-Box zeigt das notwenige Formular mit einem Auswahlfeld. Bei der Implementierung wurde auf CSS-Formatierung verzichtet um die wesentlichen Elemente besser hervorheben zu können. Das Formular besteht dabei aus einem statisch definierten Auswahlfeld, das den Typ der geometrischen Form vorgibt und aus einem Marker-Tag, der als Positionierungshilfe für die dynamisch erzeugten Felder dient. Weiterhin wird ein DocumentController definiert, der die gewünschten Felder dynamisch an der Stelle des Markers hinzufügt:
<@controller namespace="..." file="..." class="select_controller" @>
<core:addtaglib namespace="tools::form::taglib" prefix="html" class="form" />
<html:form name="type" method="post">
  <table>
    <tr>
      <td>
        Please choose the desired form type:
        <form:select name="type">
          <select:option value="triangle">triangle</select:option>
          <select:option value="square">square</select:option>
        </form:select>
      </td>
      <td>
        <form:button name="submit" value="send" />
      </td>
    </tr>
    <tr>
      <td>
        <form:marker name="fields" />
      </td>
    </tr>
  </table>
</html:form>

4.2. Controller

Der DocumentController übernimmt im beschriebenen Beispiel die Generierung der abhängigen Formularfelder, die je nach Auswahl angezeigt werden sollen. Hierzu wird im Controller zunächst definiert, welche Formular-Felder für welchen Typ angezeigt werden. Anschließend wird das Typ-Feld ausgewertet und das Formular mit Inhalten und Text-Feldern gemäß Typ ergänzt. Die folgende Code-Box zeigt die Implementierung des DocumentControllers:
class select_controller extends baseController
{

   
// specify form element container
   
var $__FormElements = array();


   function 
select_controller(){

      
// define form elements for the triangle
      
$this->__FormElements['triangle'][] = array('label' => 'coord 1','name' => 'coordone');
      
$this->__FormElements['triangle'][] = array('label' => 'coord 2','name' => 'coordtwo');
      
$this->__FormElements['triangle'][] = array('label' => 'coord 3','name' => 'coordthree');

      
// define form elements for the square
      
$this->__FormElements['square'][] = array('label' => 'coord 1','name' => 'coordone');
      
$this->__FormElements['square'][] = array('label' => 'coord 2','name' => 'coordtwo');
      
$this->__FormElements['square'][] = array('label' => 'coord 3','name' => 'coordthree');
      
$this->__FormElements['square'][] = array('label' => 'coord 4','name' => 'coordfour');

    
// end function
   
}


   function 
transformContent(){

      
// get form reference
      
$Form = &$this->__getForm('type');

      
// get current decision
      
$Select = &$Form->getFormElementByName('type');
      
$Option = &$Select->getSelectedOption();
      if(
$Option === null){
         
$CurrentType 'triangle';
       
// end if
      
}
      else{
         
$CurrentType $Option->getAttribute('value');
       
// end else
      
}

      
// add form elements
      
for($i 0$i count($this->__FormElements[$CurrentType]); $i++){

         
// add label
         
$Form->addFormContentBeforeMarker('fields',$this->__FormElements[$CurrentType][$i]['label'].': ');

         
// add text field (name attribute is present to enable validation and presetting!)
         
$CurrentElementID $Form->addFormElementBeforeMarker(
                                          
'fields',
                                          
'form:text',
                                          array(
'name' => $this->__FormElements[$CurrentType][$i]['name'])
                                                              );

         
// configure further form element attributes
         
$CurrentElement = &$Form->getFormElementByObjectID($CurrentElementID);
         
$CurrentElement->setAttribute('style','width: 200px;');

         
// add a line break
         
$Form->addFormContentBeforeMarker('fields','<br />');

       
// end for
      
}

      
// display form
      
$Form->transformOnPlace();

    
// end function
   
}

 
// end class

4.3. Wichtige Hinweise

Ein APF-Formular-Element benötigt bereits bei der Erstellung des Objekts die Information über den Namen des Feldes. Ist dieser nicht bekannt, kann es nicht vorausgefüllt oder validiert werden. Um die Presetting und Validierung von Formular-Elementen nutzen zu können besitzen die Methoden addFormElement(), addFormElementBeforeMarker() und addFormElementBeforeMarker() einen optionalen, dritten Parameter. Dieser erwartet eine assoziative Liste von Tag-Attributen, die dem Formular-Tag bei der Erstellung mitgegeben werden. Es daher sinnvoll, der Methode mindestens den Namen des Feldes in der Form
array(
      'name' => 'current_name'
     )
als drittes Argument mitzugeben. Dies kann unter Umständen auch für die spätere Adressierung der Objekte über die Methoden getFormElementByName() und getFormElementByID() von Interesse sein.


Kommentare

Bitte geben Sie Ihren Kommentar hier ein. Füllen Sie alle mit * gekennzeichneten Felder vollständig und korrekt aus. Um zum Artikel zurückzukehren klicken sie bitte hier. Zur Formatierung des Textes können folgende BBCode-ähnliche die Zeichen verwendet werden:
  • [f]..[/f]: fett
  • [k]..[/k]: kursiv
  • [u]..[/u]: unterstrichen
Hinweis: Formatierungszeichen in Name und E-Mail-Adresse werden nicht akzeptiert.

Name:*
E-Mail:*

Kommentar:


Bestätigungscode:*



Powered by WebRing.