Überprüfung von Werten in $_POST Feldern

This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

  • Überprüfung von Werten in $_POST Feldern

    Hallo,

    Ich habe ein Formular welches beim Absenden einen Eintrag in die Datenbank macht. Ich habe bis jetzt immerm vor dem Aufrufen der Funktion für das Eintragen, die Felder überprüft ob sie leer sind.
    Da mir die OOP immer mehr Sinn macht bin ich jetzt darauf gestoßen das ich die Werte für ein Objekt auch in der Klasse und der zuständigen Methode überprüfen könnte.

    Jetzt ist die Frage:
    Was ist besser? Wenn ich die Werte vorher überprüfe kommt das Skript gar nicht erst zur Möglichkeit das Objekt zu erstellen und in die Datenbank hinzuzufügen. Außerdem wird das Anzeigen der Fehlermeldung einfacher.
    Welchen Vorteil es bringt das ich die Werte in der Funktion zu überprüfen kommt mir nicht so wirklich in den Sinn. Ich denke aber das es irgendwie sicherer ist falls man das Formular umgehen kann oder sonst was...

    Hier ist erstmal der momentane Code:

    Source Code

    1. if(isset($_POST['add_entry_submit']))
    2. {
    3. $entry_data = array(
    4. 'entry_name' => $_POST['entry_name'],
    5. 'entry_text' => $_POST['entry_text'],
    6. 'entry_mail' => $_POST['entry_mail'],
    7. 'entry_website' => $_POST['entry_website'],
    8. 'entry_IP' => $_SERVER['REMOTE_ADDR']
    9. );
    10. if(empty($_POST['entry_name']))
    11. {
    12. $information = true;
    13. $information_text = $language['ADD_ENTRY_EMPTY_ENTRY_NAME'];
    14. $information_type = 'error';
    15. }
    16. elseif(empty($_POST['entry_text']))
    17. {
    18. $information = true;
    19. $information_text = $language['ADD_ENTRY_EMPTY_ENTRY_TEXT'];
    20. $information_type = 'error';
    21. }
    22. else
    23. {
    24. $entry = new entry($entry_data['entry_name'], $entry_data['entry_text'], $entry_data['entry_mail'], $entry_data['entry_website'], $entry_data['entry_IP']);
    25. $addEntry = $entry->addEntry();
    26. if($addEntry == true)
    27. {
    28. $information = true;
    29. $information_text = $language['ADD_ENTRY_SUCCESSFULL'];
    30. $information_type = 'accept';
    31. $entry_added = true;
    32. }
    33. else
    34. {
    35. $information = true;
    36. $information_text = $language['ADD_ENTRY_ERROR'];
    37. $information_type = 'error';
    38. }
    39. }
    40. $smarty->assign($entry_data);
    41. }
    Display All


    Ich denke so würde ich das dann ungefähr machen:

    Source Code

    1. public function set_entry_name($entry_name)
    2. {
    3. if($entry_name != "") // evtl. kann man dann auch hier weitere Überprüfungen reinbringen ob der Wert Wörter enthält die nicht drinstehen dürfen (Badlist oder sowas in der Richtung...)
    4. {
    5. $this->entry_name = $entry_name;
    6. }
    7. else
    8. {
    9. $anonym_entries_allowed = $db->getData("SELECT 'setting_value' FROM ".TABLE_PREFIX."settings WHERE 'setting_name' = 'anonym_entries_allowed");
    10. if($anonym_entries_allowed[0] == 1)
    11. {
    12. $this->entry_name = $language['ENTRY_NAME_ANONYM'];
    13. }
    14. else
    15. {
    16. return false;
    17. }
    18. }
    19. }
    Display All


    Hoffe es ist verständlich :D

    MFG

    Illidan
  • Hi,
    du sprichst es selbst an. "Man könnte das Formular übergehen"

    Ein Grund für Objektorientierung ist, dass man Code wiederverwenden kann und wenn dein Objekt nun von zwei verschiedenen Stellen erzeugt werden kann, dann musst du die Validierung entweder an zwei Stellen einbauen, oder eben direkt in die Klasse.

    Ziel ist also die Validierung im Model zu machen (wenn das Model eine public Methode "validate" hat - kannst du natürlich für eine vorzeitige Validierung darauf zugreifen)
    Ich habe mal einen Mini Wiki Artikel mit Beispielcode dazu erstellt: [wiki]Objektorientierung mit Models[/wiki]
  • Vielen Dank für den Artikel! Ich hab jetzt mal versucht das so in etwa (hoff ich mal) in die Tat umzusetzen und es funktioniert auch:

    Source Code

    1. public function __construct($entry_name, $entry_text, $entry_mail, $entry_website, $entry_IP)
    2. {
    3. $this->set_entry_name($entry_name);
    4. $this->set_entry_mail($entry_mail);
    5. $this->set_entry_website($entry_website);
    6. $this->set_entry_text($entry_text);
    7. $this->set_entry_IP($entry_IP);
    8. }
    9. public function getResult()
    10. {
    11. return $this->result;
    12. }
    13. public function checkValue($select, $from, $where, $wheredata)
    14. {
    15. global $sql;
    16. return $sql->getData("SELECT ".$select." FROM ".TABLE_PREFIX."".$from." WHERE ".$where." = '".$wheredata."'");
    17. }
    18. public function validation($attribut, $value, $select, $from, $where, $wheredata, $replace_value)
    19. {
    20. if($value != "")
    21. {
    22. $this->$attribut = $value;
    23. }
    24. elseif($select == '' && $from == '' && $where == '' && $wheredata == '')
    25. {
    26. $this->result = false;
    27. }
    28. else{
    29. $this->validation_value = $this->checkValue($select, $from, $where, $wheredata);
    30. if($this->validation_value[0] == 1)
    31. {
    32. $this->$attribut = $replace_value;
    33. $this->result = true;
    34. }
    35. else
    36. {
    37. $this->result = false;
    38. }
    39. }
    40. }
    41. public function set_entry_name($entry_name)
    42. {
    43. global $language;
    44. $this->validation('entry_name', $entry_name, 'setting_value', 'settings', 'setting_name', 'anonym_entry_allowed', $language['ENTRY_NAME_ANONYM']);
    45. }
    Display All


    Würd das so ungefähr stimmen? Ich ruf dann in meinem Skript ab ob $entry->result = true ist und je nach dem rufe ich die Methode addData() wo der Eintrag hinzugefügt wird.

    Noch kurz die Frage: Was ist besser in einer Klasse zu verwenden? self:: oder $this-> ?
  • Warum hast du nicht meinen Code übernommen. So kann ich dir nur sagen: Ich hätte es anders gemacht :(
    Ich behaupte nicht, dass mein Weg der beste ist, aber bei einen Sachen bestehe ich darauf ;)

    Zum einen finde ich dass es Sinn macht eine Basisklasse zu verwenden. Von der solltes du erben.

    Die validation Methode verwende ich um das Objekt an sich zu prüfen - nicht fremde Parameter. Daher sollte sie parameterlos sein. Eine Validation Methode darf das Objekt selbst nicht verändern.
    Die Validierung sollte außerdem zentralisiert sein - und nicht beim setzen jedes Attributes aufgerufen werden. Einzeln kannst du nicht vernünftig Abhängigkeiten zwischen Werten prüfen.

    "global" ist so ein Wort, dass man komplett vermeiden sollte. Um globale Variablen zu vermeiden gibt es Singletons.

    Ich habe im Wiki Beitrag nochmal Beispiele ergänzt wie mein Model zu verwenden ist:


    Neuen Benutzer anlegen

    Source Code

    1. <form method="post">
    2. email: <input type="text" name="email" /><br/>
    3. password: <input type="password" name="password" /><br/>
    4. <input type="submit">
    5. </form>
    6. <?php
    7. if(count($_POST)) {
    8. $user = new User($_POST);
    9. $user->save();
    10. }
    11. ?>
    Display All


    Neuen Benutzer anlegen

    Source Code

    1. <form method="post">
    2. email: <input type="text" name="email" /><br/>
    3. password: <input type="password" name="password" /><br/>
    4. <input type="submit">
    5. </form>
    6. <?php
    7. if(count($_POST)) {
    8. $user = new User($_POST);
    9. $user->save();
    10. }
    11. ?>
    Display All


    self und $this sind übrigens Grundverschieden.
    $this gehört zur Instanz eines Benutzers. self gehört zur Klasse User - damit haben alle instantiierten Benutzer hier den selben Wert.
  • Tut mir Leid aber ich will das jetzt nicht so direkt übernehmen wenn ich es nicht richtig verstehe =/.

    Wenn die Validation nur das Objekt selbst überprüft, was genau überprüft er und wie gibt er dementsprechend Fehlermeldung aus?
    Das mit Exceptions ist mir halt auch ziemlich neu...

    Würde jetzt hier z.B. "message" ausgegeben?

    Source Code

    1. throw new ValidateException('message');


    Und die Model Klasse ist sozusagen das Oberhaupt aller anderen Klassen da sie die Basis Funktionen wie Hinzufügen, Updaten, Löschen usw besitzt?

    Schade, ich dachte ich hätte es jetzt richtig gemacht und dann ist es eigentlich komplett falsch :D :D

    Ich versuch mich mal durchzuarbeiten...vielen Dank erstmal!

    EDIT: Wenn $primarykey = "id" ist dann müsste in der Datenbank das Primarykey Attribut doch auch id heißen?
    EDIT2: Okay, ich könnte $primarykey = $this->getTablename()."_ID"; machen und dann hab ich es so eig...
    EDIT3: Irgendwie will das nicht so wirklich...ich krieg die Meldung unexpected T_VARIABLE und ist für mich irgendwie unklar Oo.

    The post was edited 3 times, last by Illidan ().

  • Bin gerade bei der Validigierung aber es haut nicht so hin. Ich werfe ne Exception und frage mit if ab ob die Exception der Wert ist was definitiv der Wert sein muss dennoch geht die if-Anweisugn in den else Bereich.

    entry.php

    Source Code

    1. try
    2. {
    3. $entry->save();
    4. }
    5. catch(ValidateException $e)
    6. {
    7. if($e == 'NO_ENTRY_TEXT')
    8. {
    9. $information = true;
    10. $information_text = 'Kein Text';
    11. $information_type = 'error';
    12. }
    13. elseif($e == 'NO_WEBSITE_NOT_ALLOWED')
    14. {
    15. $information = true;
    16. $information_text = 'Ohne Website nicht erlaubt!';
    17. $information_type = 'error';
    18. }
    19. elseif($e == 'NO_MAIL_NOT_ALLOWED')
    20. {
    21. $information = true;
    22. $information_text = 'Ohne Mail nicht erlaubt';
    23. $information_type = 'error';
    24. }
    25. elseif($e == 'ANONYM_ENTRY_NOT_ALLOWED')
    26. {
    27. $information = true;
    28. $information_text = 'Keine Anonymen Einträge erlaubt!';
    29. $information_type = 'error';
    30. }
    31. elseif($e == 'ANONYM_ENTRY_ALLOWED')
    32. {
    33. $entry_data['entry_name'] = 'Anonym';
    34. try
    35. {
    36. $entry->save($entry_data);
    37. }
    38. catch(Exception $e)
    39. {
    40. echo $e;
    41. echo "exception";
    42. }
    43. }
    44. else{
    45. echo "exception something else";
    46. echo $e;
    47. }
    48. }
    49. catch(Exception $e)
    50. {
    51. echo $e;
    52. echo "exception something else 2";
    53. }
    Display All


    Teil meiner validate()

    Source Code

    1. if($this->data['entry_name'] == '')
    2. {
    3. if($check_anonym_name != 1)
    4. {
    5. throw new ValidateException('ANONYM_ENTRY_NOT_ALLOWED');
    6. }
    7. else
    8. {
    9. throw new ValidateException('ANONYM_ENTRY_ALLOWED');
    10. }
    11. }
    Display All


    $check_anonym_name ist 1, habe das über eine Datenbankabfrage rausgeholt und auch geguckt ob es wirklich 1 ist....

    Mache ich da irgendwie etwas falsch mit dem try und catch =/?

    Habe noch weitere if-Anweisungen in der validate() für die anderen Exceptions aber ich denek die eine reicht ja aus....
  • Oh man, wieso hab ich das nicht bemerkt :|

    Wie kommt es aber das mein Programm die Funktion getMessage() nicht anzeiget wenn ich $e-> schreibe?

    Ich dachte die ganze Zeit in $e steht nur was ich in die Klammern beim Exception reinschreibe aber dazu gehört wohl auch die Meldung wo und in welcher Zeile und worum es bei der Exception geht...

    naja, danke vielmals.

    Noch eine Frage: Kann man irgendwie Exceptions wieder zurück werfen? Wenn ich throw $e mache dann geht es ja weiter zum nächsten catch{}?

    Sozusagen in einem case ist noch ein weiteres try-catch und in dem catch sollte dann das $e wieder zurück zum oberen catch geleitet werden damit die switch Anweisung nochmal durchgeführt wird.

    Ich habe das jetzt so gemacht das so gemacht das zuerst abgefragt wird ob in $e->getMessage() der eine Wert steht und dementsprechend wird ein Wert umgeändert und mit try-catch der Speichervorgang erneut aufgerufen. Im catch Bereich steht dann switch Anweisung drin.
  • Naja, ich hab ja allerdings 6 Ausnahmen. Wenn kein Benutzername angegeben ist und es ohne Name nicht erlaubt ist, wenn es erlaubt ist dann wird etwas anderes reingeschrieben, wenn keine Email angegeben ist, wenn keine Website angegeben ist und wenn kein Text angegeben ist.

    Ich dachte das ist ja der Sinn der Sache das ich sozusagen Ausnahmen behandele...
  • Objektorientierung ist ein spiel mit verantwortlichkeiten.
    Ist es aufgabe des formulars fehleingaben automatisch zu korrigieren, oder ist es aufgabe des user modells optionaleangaben durch defaults zu ersetzen.
    häufig beantwortet man sich die frage, wenn man sich überlegt an welchen stellen man die funktion noch benötigt.
    von wo legt man benutzer an?
    registrierung und armin tool. Lasst sich das registrierungsformular im admin tool wiederverwenden oder ist es einfacher die funktion stattdessen im usermodel zu hinterlegen?
    exceptions sind für mich ausnahmen die man nicht automatisch lösen kann. Die exception habe ich konkret eingebaut damit du dem benutzer ein dialog zeigen kannst, wie er seine eingaben korrigiert. Falls du dich gar nichteinigung einem formular befindest, die ausnahme also nicht gefangen wird dann würde die ausnahme zum abbruch des programms fuhren.
    lg
  • Naja, du hast ja gemeint das zb die Validierung das Objekt selbst nicht ändern darf. Deswegen werfe ich bei leeren Einträgen Exceptions und fange die dann auf der Seite auf und gebe dann eine Meldung aus das manche Einträge leer sind.
    Ich hab es jetzt hinbekommen und es läuft so weit ;)

    Ich denke aber du meinst das ich ne Funktion bei meiner Entry Klasse erstelle und dann aufrufe und dort fange ich halt evtl Exceptions und gebe das Ergebnis wieder zurück? Somit könnte ich es bei ner anderen Seite weiter verwenden
  • Ich habe mal einen neuen Wiki Eintrag zu dem Thema erstellt: [wiki]Objektorientierung mit Exceptions[/wiki]

    Du hast schon Recht mit dem was ich gesagt habe und ich bin begeistert, dass du es wirklich verinnerlicht hast :) Vielen kann man erzählen und erzählen und sie machen es nicht.
    Allerdings würde ich die Default Werte wohl auch nicht in der validate Methode setzen, sondern eine Ebene früher.
    Entweder mit Default Werten in der Datenbank, oder direkt im Formular, falls die Defaultwerte spezifisch für das Formular sind oder in der Model Save Methode, falls es global erfolgen soll.

    Konkret würde das so aussehen:

    Source Code

    1. class User extends Model {
    2. public function save($override = null) {
    3. if($override !== null) {
    4. $this->data = array_merge($this->data, $override);
    5. }
    6. if(empty($this->email)) {
    7. $this->email = 'unknown';
    8. }
    9. parent::save();
    10. }
    11. }
    Display All
  • Yeah, vielen Dank für den Wiki Eintrag. Hat mir schon geholfen wie ich das jetzt löse!

    Ich hab das jetzt so gemacht wie du es vorgegeben hast. Überprüfung war ja auch schon in der Validierung (ist ja eig klar^^), default Werte sind in der save Methode und das Auffangen und ausgeben der Fehlermeldung natürlich auf der Hauptseite (Controller oder?)

    Ich hab übrigens bei dem Model zwei Methoden für Insert Into und Update gemacht. Mir ist nicht klar was das mit $override und die Überprüfung ob es nicht Null ist sagen soll :S.
  • Das Thema Exceptions finde ich äußerst interessant, da ich mich momentan viel mit Python beschäftige und da ja im Grunde nichts anderes gemacht wird.

    d0nut wrote:

    Hm.. für meinen Geschmack nutzt damit zu viele Exceptions.

    Wie kann man zu viele Exceptions werfen, solange sie angebracht sind? Ich meine, ist es nicht schön, ausführliche Fehlermeldungen zu werfen und immer die Möglichkeit zu haben, alternative Lösungswege im Programm zu implementieren? Das ist sicherlich geschmackssache, aber ich habe im Laufe meiner Arbeit mit Python und PHP-Frameworks gelernt, wie umgänglich diese Exceptions sein können.

    d0nut wrote:

    Vor allem klingt das für mich nicht schlüssig, dass eine Exception im Bedarfsfall noch weitere Exceptions schmeißt...

    Das ist allerdings ab von der Definition einer Exception. Keine Ahnung, wie sie genau definiert ist, aber ein komisches Gefühl krieg ich dabei ebenfalls.
  • Hallo,

    ich bins mal wieder! Hehe - habe in der letzten Zeit nicht mehr viel gemacht und bin auch etwas verwirrt von dem ganzen Code :rolleyes: . Naja, und zwar ist mir jetzt noch eine Frage eingefallen bei der ich nicht unbedingt weis ob ich es so lassen soll oder nicht.

    Ich schreib ja ein kleines Gästebuch und nun weis ich nicht ob ich eine Klasse "gbook.php" benutzen soll der entweder das Gästebuch verwaltet oder das Gästebuch erzeugt.

    Die Verwaltung macht ja eigentlich schon Entry.php welche von Model.php erbt wobei hier ja nur ein Eintrag selbst verwaltet wird. Ich habe jetzt z.B. noch zwei Methoden wie getEntries oder getSites welche alle Einträge als Array zurück gibt oder die die Seitenanzahl. Das sind halt so Sachen die ich eigentlich auch in meine index.php reinbringen könnte wo die Einträge angezeigt werden. Allerdings, wie du schon gemeint hast d0nut, vllt will ich ja auf einer anderen Seite wieder auf diese Methoden zugreifen und dann müsste ich sie nochmal schreiben, somit wäre eine einheitliche Methode in einer Klasse besser.

    Nun ja, wie gesagt, seh ich den Sinn in so einer Verwaltungsklasse für das Skript falsch oder wird das überhaupt nicht benötigt ?
  • Um noch mal sicher zu gehen: die index.php wo jetzt die Einträge aufgelistet werden wäre sozusagen schon ein Controller? Denn er steuert ja was angezeigt wird und welche Daten geladen werden sollen. Die Anzeige also das View wäre dann sozusagen Smarty?

    Kann mich nicht ganz entscheiden ob ich diese Gästebuch Klasse entferne oder doch benutze. Wenn ich so eine Klasse benutzen würde, wäre es ja auch versätndlicher dann so Methoden wie "addEntry", "delEntry", "editEntry" reinzufügen oder nicht? Die Methoden würden dann halt auf das Entry Model zugreifen.

    The post was edited 1 time, last by Illidan ().