Ankündigung

Einklappen
Keine Ankündigung bisher.

Formular Validierung

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • #31
    Hallo!

    Entschuldigt das doppelte Posting, aber es hat sich bei mir etwas getan. Ich hatte ja vor das Formular auch über die Ausgabe des Objekts der Form-Klasse zu erstellen. Dazu habe ich die Klasse Form_Element um das Array $attributs und um die Methode addAttr() erweitert. So ist es mir möglich den verschiedenen Eingabefeldern erschiedene Attribute zuzuweisen. Damit ich aber überhaupt eine Ausgabe erhalte musste ich ersteinmal eine Klasse Form_Element_Text implementieren. Das habe ich auch getan. Die Klasse Form habe ich um die magische Methode __toString() erweitert.

    Wo liegt also mein problem hört sich doch alles gut an? Das Problem ist, dass ich nicht weiß, was ich als action-Attribut in den Kopf des Formulars schreiben soll. Zudem wird bei folgendem Aufruf nur das erste Eingabefeld und sofort ein Fehler, und das auch noch mehrfach, angezeigt.
    PHP-Code:
    <?php
        error_reporting
    (E_ALL E_STRICT);

        
    // require needed classes
        
    require_once('Form.php');
        require_once(
    'Form_Element_Text.php');
        require_once(
    'Validator_Length.php');
        require_once(
    'Validator_Alnum.php');
        require_once(
    'Validator_Alpha.php');

        
    // Creating Form
        
    $form = new Form();
        
        
    // Creating Form Elements
        
    $text1 = new Form_Element_Text('feld1');
        
    $text1->addValidator( new Validator_Length(5,8) );
        
    $text1->addValidator( new Validator_Alnum() );
        
        
    $text2 = new Form_Element_Text('feld2');
        
    $text2->addValidator( new Validator_Length(5,20) );
        
    $text2->addValidator( new Validator_Alpha() );
        
        
    // Adding Elements to form
        
    $form->addElement($text1);
        
    $form->addElement($text2);
        
        
    // set form data
        
    $form->setData($_POST);
        
        
    // check for errors
        
    if( $form->isValid() )
            echo 
    "<b>Succesfull.</b><br />";
        else
            echo 
    "<b>Error accured.</b><br />";
        
        
    // print out form
        
    echo $form;
    ?>
    Wie kann ich diese Fehler beheben? Zudem würde mich interessieren, wie ich das Layout des Formulars anpassbarer machen kann. Wäre euch für eure Hilfe und weiter Anregungen und Kommentaren zu diesen Klassen sehr dankbar. Den Code der entsprechenden Klassen findet ihr unten. Ein großes Danke an dieser Stelle nochmal allen, die mir bisher geholfen haben und vorallem robo47 für den sehr sehr hilfreichen Code.

    MfG, Andy

    PHP-Code:
    <?php
    error_reporting
    (E_ALL E_STRICT);

    /***
    * Class Form 
    *
    * The Form class supports 
    * the handling of different forms.
    * You are able to assign different elements,
    * to each form.
    *  
    * @package Form
    * @version 0.1
    **/  
    Class Form
    {
        
    // protected class variables
        
    protected $elements = array();
        protected 
    $errors = array();

        
    /**
        * addElement() - Adds an element to the form
        *
        * @access public
        * @param Obj $element
        * @return NONE
        */
        
    public function addElement($element)
        {
            
    // create hash
            
    $hash md5(get_class($element));
            
            
    // check if entry exists
            
    if( !isset($this->validators[$hash]) )
            {
                
    $this->elements[$hash] = $element;
            }
        }

        
    /**
        * setData() - Assigns data to the form (e.g. $_POST)
        *
        * @access public
        * @param Arr $data
        * @return NONE
        */
        
    public function setData($data)
        {
            
    // iterate over all elements
            
    foreach ($this->elements as $element)
            {
                
    // ierate over data array
                
    foreach($data as $key => $value)
                {
                    
    // check if element exists
                    
    if( $key == $element->getName() )
                    {
                        
    // assign value
                        
    $element->setValue($value);
                        break;
                    }
                }
            }
        }

        
    /**
        * isValid() - Checks if any errors accured in this form
        *
        * @access public
        * @return Boolean
        */
        
    public function isValid()
        {
            
    // initiate return parameter
            
    $isValid true;
            
            
    // check if all elements are valid
            
    foreach($this->elements as $element)
            {
                
    // check if element is valid
                
    $elementValid $element->isValid();
                
                
    // element is not valid
                
    if( false === $elementValid 
                {
                    
    // set return parameter
                    
    $isValid false;
                    
                    
    // get error messages
                    
    $this->errors[$element->getName()] = $element->getErrors();
                }
            }
            
            return 
    $isValid;
        }

        
    /**
        * getErrors() - Returns the errors accured in a form
        *
        * @access public
        * @return Array
        */
        
    public function getErrors()
        {
            return 
    $this->errors;
        }
        
        
    /**
        * __toString() - Returns the html-code of the form
        *
        * @access public
        * @return NONE
        */
        
    public function __toString()
        {    
            
    // initiate code-variable
            
    $html "\n\n<!-- start PHP created form -->\n";
            
            
    // start form
            
    $html .= '<form action="" method="">';
            
            
    // get all form fields
            
    foreach($this->elements as $element)
            {            
                
    // element is not valid
                
    if( $element->isValid() === false 
                {
                    foreach(
    $element->getErrors() as $error)
                    {
                        
    $html .= "\n" $error "<br />";
                    }
                }
                
                
    // check if element is valid
                
    $html .= sprintf("\n%s: %s"$element->getName(), $element);
            }
            
            
    // end form
            
    $html .= "\n</form>\n";
            
    $html .= "<!-- end PHP created form -->\n\n";
            
            return 
    $html;
        }
    }

    /***
    * Abstract Class Form_Element 
    *
    * The Form_Element class supports 
    * the handling of different input fields.
    * You are able to assign validators,
    * names and values to each input element.
    *  
    * @package Form_Element
    * @version 0.1
    **/  
    Abstract Class Form_Element
    {
        
    // protected class variables
        
    protected $name '';
        protected 
    $value '';
        protected 
    $attributs = array();
        protected 
    $validators = array();
        protected 
    $errors = array();

        
    /**
        * Constructor - Is called when the class is instanced
        *
        * @access public
        * @param Str $name
        * @return NONE
        */
        
    public function __construct($name)
        {
            
    $this->name $name;
        }

        
    /**
        * setValue - Assigns value to an element
        *
        * @access public
        * @param Mix $value
        * @return NONE
        */
        
    public function setValue($value)
        {
            
    $this->value $value;
        }
        
        
    /**
        * addValidator() - Adds an validator to an element
        *
        * @access public
        * @param Obj $validator
        * @return NONE
        */
        
    public function addValidator($validator)
        {
            
    // create hash
            
    $hash md5(serialize(get_object_vars($validator)));
            
            
    // check if entry exists
            
    if( !isset($this->validators[$hash]) )
            {
                
    $this->validators[$hash] = $validator;
            }
        }
        
        
    /**
        * addAttr() - Adds an attribut to an element
        *
        * @access public
        * @param Str $key
        * @param Mix $val
        * @return NONE
        */
        
    public function addAttr($key$val)
        {        
            
    // check if entry exists
            
    if( !isset($this->attributs[$key]) )
            {
                
    $this->attributs[$key] = $val;
            }
        }
        
        
    /**
        * getName() - Returns the name of an element
        *
        * @access public
        * @return NONE
        */
        
    public function getName()
        {
            return 
    $this->name;
        }

        
    /**
        * getName() - Returns the value of an element
        *
        * @access public
        * @return NONE
        */
        
    public function getValue()
        {
            return 
    $this->value;
        }
        
        
    /**
        * isValid() - Checks if any errrors accured in this element
        *
        * @access public
        * @return Boolean
        */
        
    public function isValid()
        {
            
    // initiate return parameter
            
    $isValid true;
            
            
    // check value with the assigned validators
            
    foreach( $this->validators as $validator 
            {
                
    // invalid value
                
    if( !$validator->isValid($this->value) )
                {
                    
    // set return parameter
                    
    $isValid false;
                    
                    
    // get error messages
                    
    $errors $validator->getErrors();
                    
                    
    // save errors
                    
    foreach($errors as $error
                    {
                        
    $this->errors[] = $error;
                    }
                }
            }
            
            return 
    $isValid;
        }

        
    /**
        * getErrors() - Returns the errors accured in an element
        *
        * @access public
        * @return Array
        */
        
    public function getErrors()
        {
            return 
    $this->errors;
        }
    }

    /***
    * Class Form_Element_Text 
    *
    * The Form_Element class 
    * represents a text-input filed.
    * You are able to assign a name, a value
    * and different validators to each input element.
    *  
    * @package Form_Element
    * @subpackage Form_Element_Text
    * @version 0.1
    **/  
    Class Form_Element_Text extends Form_Element
    {
        
    /**
        * __toString() - Returns the html-code of the input field
        *
        * @access public
        * @return NONE
        */
        
    public function __toString()
        {
            
    // initiate code-variable
            
    $html '<input type="text"';
            
            
    // add name
            
    $html .= ' name="' $this->name '"';
            
            
    // add value
            
    $html .= ' value="' $this->value '"';
            
            
    // prepare attributs
            
    foreach($this->attributs as $key => $val)
            {
                
    $html .= ' ' $key '="' $val '"';
            }
            
            
    // close tag
            
    $html .= ' />';
            
            return 
    $html;
        }
    }
    ?>

    Kommentar


    • #32
      Betreibst du irgendeine Art von tests ? Oder schreibst du den Code einfach so runter ohne irgendwie zu testen ?
      Gerade bei größeren Komponenten ist das sinnvoll!

      PHP-Code:
          public function addElement($element)
          {
              
      // create hash
              
      $hash md5(get_class($element));
              
              
      // check if entry exists
              
      if( !isset($this->validators[$hash]) )
              {
                  
      $this->elements[$hash] = $element;
              }
          } 
      da wird elemente + validatoren durcheinandergeschmissen.

      und md5(get_class( ... ));
      damit würdest du wenn das ernst gemeint ist deiner Form genau 1 Element jeder Klasse hinzufügen können, keine 2 Text-Felder oder was auch immer.

      Bevor du hier so eine riesen Klasse oder sogar mehrere postest, schreib doch einfach mal ein paar tests ob sie das macht was sie soll ? -> phpunit oder auch simpletest wären da vielleicht nützlich.
      [URL="http://www.robo47.net"]robo47.net[/URL] - Blog, Codeschnipsel und mehr
      | :arrow: [URL="http://www.robo47.net/blog/192-Caching-Libraries-and-Opcode-Caches-in-php-An-Overview"]Caching-Klassen und Opcode Caches in php[/URL] | :arrow: [URL="http://www.robo47.net/components"]Robo47 Components - PHP Library extending Zend Framework[/URL]

      Kommentar


      • #33
        Hallo!

        Danke für deine Hilfe. Es erscheint nun auch das erste Formularfeld.

        Natürlich versuche ich die Klassen zu testen jedoch weiß ich nicht, wie ich solche Klassen anders testen sollte als kleine Beispiel-Aufrufe zu schreiben. Werde mir mal PHPUnit ansehen.

        Leider bleibt mein altes problem, dass die fehlermeldungen bereits ausgegeben werden, obwohl ich das Formular noch garnicht abgesendet habe. Wie kann ich das geschickt verhindern?

        Des weiteren wird die Fehlermeldung, dass die Eingabe zu kurz ist 3 mal für jedes Feld angezeigt. Woran kann das liegen?

        Zudem erhalte ich für
        PHP-Code:
        ereg("[[:alnum:]]{".strlen($value)."}"$value
        das Warning
        Code:
        Warning:  ereg() [function.ereg]: REG_EMPTY in /home/www/web274/html/admin/classes/Validator_Alnum.php on line 31
        Wie kann ich diesen Fehler verhindern? Oder gibt es eine andere bessere Funktion mittels der ich auf alphanumerische Eingaben zu prüfen kann?

        MfG, Andy

        Kommentar


        • #34
          Zitat von #Avedo Beitrag anzeigen
          Leider bleibt mein altes problem, dass die fehlermeldungen bereits ausgegeben werden, obwohl ich das Formular noch garnicht abgesendet habe. Wie kann ich das geschickt verhindern?
          Versuch mal das Formular zu prüfen nach dem es gesendet wurde und nicht davor

          PHP-Code:
          [...]
              
          $form->addElement($text2);
                 
              if(
          $_POST) {    
                  
          // set form data
                  
          $form->setData($_POST);
                  
                  
          // check for errors
                  
          if( $form->isValid() )
                      echo 
          "<b>Succesfull.</b><br />";
                  else
                      echo 
          "<b>Error accured.</b><br />";
              }
              
              
          // print out form
              
          echo $form

          Kommentar


          • #35
            Danke für deine Antwort. Hat mir bei der Lösung des Problems sehr geholfen. Dieser Fehler ist also behoben.

            Mich würde nun aber noch interessieren, wie ich eine Unterscheidung in optionale und Pflichtfelder hinbekomme. Das muss ja über einen optionalen Parameter binding lösbar sein. Würde es reichen, die abstrakte Klasse um eine Methode zu erweitern, die überprüft ob eine Eingabe gemacht wurde oder nicht und dann wenn dies nicht der Fall ist und binding auf false gesetzt ist einfach immer true für isValid() zurückgebe? So könnte ich auch verhindern, dass für solche Felder, wenn sie leer sind Fehler ausgegeben würden. Zudem kann ich dann eine Zusätzliche Fehlermeldung ausgeben, wenn ein Pflichtfeld nicht ausgefüllt wurde. Habe ich etwas übersehen?

            Sitze nun noch an einer geeigneten Lösung um Formatierungen für das Formular festlegen zu können. Eine Methode addAttr(), die Attribute für das <form>-Tag festlegt ist sicher hilfreich jedoch könnte es ja sein, dass vor einem Formularfeld eine Beschreibung stehen soll, oder dass das Formular in eine Tabelle gepackt wreden soll. Wie kann ich das ermöglichen? Kurz, wie schaffe ich es, dass das Formular zum Beispiel wie hier anpassbar ist?
            MfG, Andy

            Kommentar


            • #36
              ich hab mir auch eine Validierungsklasse geschrieben.

              Allerdings eine reine Validierung und kein Mischmasch von
              Formularerzeugung und Vailiderung.

              So hab ich die maximale Freiheit bei der Darstellung des Formulars
              (die Dinge die Du angesprochen hast: Tabellenlayout, Beschreibungstexte etc.)

              Pflichtfelder erkennt die klasse anhand der Namen der input-Felder
              (vorangestelltes "r_").

              Die Methode displayErrors() liefert einen String mit den Fehlern zurück.

              Zusätzlich gibt es die Methoden getJSErrors() um JS-Alerts anzuzeigen und getCSSErrors(), mit der dynamisch CSS erzeugt wird, damit die unausgefüllten Pflichtfelder rot umrandet werden.

              Wenn Du willst such ich Dir die Klasse raus und poste sie hier.

              ereg ist übrigens veraltet ...
              Eine if-else-Abfrage nimmt, ordentlich geschrieben eine Menge Platz weg. Platzsparend geht es mit einem ternären Operator.

              Kommentar


              • #37
                HAst du dir die Posts im Thread mal durchgelesen? Es gibt keinen Mischmasch von Formularausgabe und Validierung. Wir reden hier nicht von einer Klasse, sondern von über 20 Klassen. Eine Klasse Form, eine Form_Element, eine Klasse für jedes Formular-Element(Text, Hidden, etc.), eine Klasse Validator und eine Klasse für jeden spezifischen Validator. Flexibler kann es nicht gehen. Die Validatoren sind so auch in anderen Klassen einsetzbar. Zum Beispiel bei der Validierung von per URL übergebenen Parametern oder der Verarbeitung von Stream-Daten. Eine Klasse wäre viel zu statisch. Das habe ich nun auch begriffen. Habe ja am Anfang dieses Threads es auch in einer Klasse gelöst.
                MfG, Andy

                Kommentar


                • #38
                  Es gibt keinen Mischmasch von Formularausgabe und Validierung.
                  oh - sorry.

                  Dann versteh ich aber das hier nicht:
                  Sitze nun noch an einer geeigneten Lösung um Formatierungen für das Formular festlegen zu können. Eine Methode addAttr(), die Attribute für das <form>-Tag festlegt ist sicher hilfreich jedoch könnte es ja sein, dass vor einem Formularfeld eine Beschreibung stehen soll, oder dass das Formular in eine Tabelle gepackt wreden soll. Wie kann ich das ermöglichen? Kurz, wie schaffe ich es, dass das Formular zum Beispiel wie hier anpassbar ist?
                  Eine Klasse Form, eine Form_Element, eine Klasse für jedes Formular-Element(Text, Hidden, etc.), eine Klasse Validator und eine Klasse für jeden spezifischen Validator. Flexibler kann es nicht gehen.
                  flexibler geht es natürlich ohne form- und form-element-Klassen, indem Du das Formular in der view/action definerst. so hast Du maximale Freiheit bei der Gestaltung.
                  Wenn Du alle Eventualitäten abdecken willst bei der Gestaltung von Formularen,
                  dann hast Du gigantisch viel zu Programmieren.

                  Und zu der Sache mit den Pflichtfeldern hatt ich ja geschrieben wie Du es machen kannst.
                  Eine if-else-Abfrage nimmt, ordentlich geschrieben eine Menge Platz weg. Platzsparend geht es mit einem ternären Operator.

                  Kommentar


                  • #39
                    Eine Möglichkeit wäre es, Fieldset-Objekte zwischen das Formularobjekt und die Eingabefelder zu schieben. Dann musst du allerdings vermutlich die Kommunikation zwischen Formular und Eingabefeldern anpassen. Ausserdem würde ich mir noch eine Möglichkeit lassen, mehrere Eingabefelder als Gruppe vorzuverarbeiten, so dass nur noch ein Wert zurückkommt. Beispiele hierfür wären eine Datumseingabe mittels 3 Select-Listen (Tag/Monat/Jahr) oder eine Auswahlliste mit einem "andere"-Textfeld. Die könntest du auch als Klassen definieren, die ihrerseits Eingabefelder enthalten und deren Werte zu einem oder mehreren eigenen Rückgabewerten verrechnen.

                    Die Hierarchie wäre dann etwa folgende:

                    Formular ---> Fieldset ---> Gruppe ---> Eingabefelder

                    Validiert wird dann 3 mal, nämlich zuerst auf der Eingabefelder-Stufe, dann wird der Rückgabewert der Gruppe berechnet und validiert und zu guter Letzt können auf Formularebene noch Beziehungen zwischen den Werten gecheckt werden.

                    Nicht dass ich das schonmal so gemacht hätte, aber ich plane ja auch gerade eine Formularklasse und ich hab halt manchmal etwas zuviel Fantasie.

                    Was den View angeht: das finde ich auch ziemlich schwierig, das wirklich zu trennen. Die Verarbeitung der Formularwerte gehört ganz klar nicht zum View, auch die definition der geforderten Eingabefelder nicht. Die Darstellung ist jedoch ziemlich stark von der Definition abhängig. Aber das Formular im View zu definieren... da hab ich irgendwie das Gefühl, dass es bessere Lösungen geben muss.

                    Kommentar


                    • #40
                      auch die definition der geforderten Eingabefelder nicht.
                      stimmt - gehört wohl eher in den Controller.

                      Aber das Formular im View zu definieren... da hab ich irgendwie das Gefühl, dass es bessere Lösungen geben muss.
                      mag sein, aber Du hast eben die größtmögliche Freiheit.

                      Deine fieldset-Objekte machen sich in einem Tabellenlayout z.B. nicht gut.
                      Eine if-else-Abfrage nimmt, ordentlich geschrieben eine Menge Platz weg. Platzsparend geht es mit einem ternären Operator.

                      Kommentar


                      • #41
                        Naja unter Mischmasch zwischen Formularausgabe und Validierung verstehe ich, dass dies in einer Klasse gebündelt ist. Das ist ja aber nicht der Fall. Die Klasse, die die Validatoren aufruft und die das Formular ausgeben soll, ist nur teilweise die selbe. Die Validatoren sind allerdings alles eigenständige Klassen.

                        Zudem wird es noch zwei drei Filter-Klassen geben, die es erlauben zum Beispiel einen String in Kleinbuchstaben umzuwandeln.

                        Die Ausgabe des Formulars über diese Klasse ermögliche ich, da ich kein großer Freund von HTML-Formularen bin. Macht mir einfach keinen Spaß. Da brüte ich doch lieber an einer neuen Klasse in PHP. Natürlich müssen Anpassungen via CSS möglich sein. Deshalb lege ich ein Standard-Layout fest und weise automatisch css-Klassen und IDs zu. Zudem gibt es noch die Möglichkeit HTML-Attribute, wie zum Beispiel size hinzuzufügen. So ist das Formular gut Anpassbar und ich hab keinen Stress. Vielleicht ermögliche ich es noch anstatt Deinition Lists Tabellen zu nutzen.

                        MfG, Andy

                        Kommentar


                        • #42
                          Es besteht ja immernoch die Möglichkeit im View sich die Elemente einzeln aus dem Formular zu holen element zu ziehen oder auch das formular händisch zu machen, wenn man es denn unbedingt braucht.

                          Ansonsten mit ein paar Standard-Dekoratoren kann man im üblichen das meiste erreichen.
                          [URL="http://www.robo47.net"]robo47.net[/URL] - Blog, Codeschnipsel und mehr
                          | :arrow: [URL="http://www.robo47.net/blog/192-Caching-Libraries-and-Opcode-Caches-in-php-An-Overview"]Caching-Klassen und Opcode Caches in php[/URL] | :arrow: [URL="http://www.robo47.net/components"]Robo47 Components - PHP Library extending Zend Framework[/URL]

                          Kommentar


                          • #43
                            Danke. Das ist eine gute Idee. Denke auch, dass die standard Dekoratoren ausreichen. Und du hast recht. Mann kann das Layout immernoch per Hand machen. Werde mich also nun noch an die letzten Form_Element_* - Klassen setzen und noch die Möglichkeit Filter zu nutzen implementieren. An dieser Stelle würde mich noch interessieren, welche Filter ihr für Sinnvoll haltet.
                            • Filter_ToLower
                            • Filter_ToUpper
                            • Filter_UcFirst

                            Das waren die, die mir vorerst eingefallen sind. Habt ihr noch eine Idee? Freue mich auf eure Anregungen.
                            MfG, Andy

                            Kommentar


                            • #44
                              mir fällt spontan ein:

                              Filter_Trim
                              Filter_StripTags
                              [URL="http://www.robo47.net"]robo47.net[/URL] - Blog, Codeschnipsel und mehr
                              | :arrow: [URL="http://www.robo47.net/blog/192-Caching-Libraries-and-Opcode-Caches-in-php-An-Overview"]Caching-Klassen und Opcode Caches in php[/URL] | :arrow: [URL="http://www.robo47.net/components"]Robo47 Components - PHP Library extending Zend Framework[/URL]

                              Kommentar


                              • #45
                                String kürzen (abschneiden)
                                str_replace
                                preg_replace
                                bestimmte zeichen entfernen/austauschen

                                Kommentar

                                Lädt...
                                X