You are not logged in.

  • Login

1

Saturday, January 30th 2010, 9:35pm

Ü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:

PHP Quellcode

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


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

PHP Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public function set_entry_name($entry_name)
    {
        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...)
        {
            $this->entry_name = $entry_name;
        }
        else
        {
            $anonym_entries_allowed = $db->getData("SELECT 'setting_value' FROM ".TABLE_PREFIX."settings WHERE 'setting_name' = 'anonym_entries_allowed");
            if($anonym_entries_allowed[0] == 1)
            {
                $this->entry_name = $language['ENTRY_NAME_ANONYM'];
            }
            else
            {
                return false;
            }
        }
    }


Hoffe es ist verständlich :D

MFG

Illidan

2

Sunday, January 31st 2010, 9:20am

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: Objektorientierung mit Models

3

Sunday, January 31st 2010, 3:21pm

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:

PHP Quellcode

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


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-> ?

4

Sunday, January 31st 2010, 4:25pm

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

PHP Quellcode

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


Neuen Benutzer anlegen

PHP Quellcode

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


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.

5

Sunday, January 31st 2010, 5:34pm

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?

PHP Quellcode

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.

This post has been edited 3 times, last edit by "Illidan" (Jan 31st 2010, 7:23pm)


6

Friday, February 5th 2010, 9:20pm

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

PHP Quellcode

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


Teil meiner validate()

PHP Quellcode

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


$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....

7

Friday, February 5th 2010, 9:37pm

Naja, du vergleichst ein Objekt mit einem String.

Nach deinem Schema solltest du die Abfragen so bauen:

PHP Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
try {
	throw new ValidateException('X');
} catch(Exception $e) {
	switch($e->getMessage()) {
		case 'X':
			echo 'fehler x';
		break;
		case 'Y':
			echo 'fehler y';
		break;
		default;
			echo 'fehler default';
		break;
	}
}

8

Friday, February 5th 2010, 10:03pm

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.

9

Friday, February 5th 2010, 11:25pm

Hm.. für meinen Geschmack nutzt damit zu viele Exceptions.
Ich setze Exceptions nur an ganz wenigen Stellen ein und behandle sie an noch weniger (zentralen) Stellen.

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

10

Saturday, February 6th 2010, 9:01am

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...

11

Saturday, February 6th 2010, 10:30am

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

12

Saturday, February 6th 2010, 11:04am

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

13

Saturday, February 6th 2010, 11:44am

Ich habe mal einen neuen Wiki Eintrag zu dem Thema erstellt: Objektorientierung mit Exceptions

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:

PHP Quellcode

1
2
3
4
5
6
7
8
9
10
11
class User extends Model {
	public function save($override = null) {
		if($override !== null) {
			$this->data = array_merge($this->data, $override);
		}
		if(empty($this->email)) {
			$this->email = 'unknown';
		}
		parent::save();
	}
}

14

Saturday, February 6th 2010, 10:11pm

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.

15

Saturday, February 6th 2010, 11:41pm

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.

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.

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.

16

Sunday, May 30th 2010, 12:20pm

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 ?

17

Sunday, May 30th 2010, 3:59pm

Entry und User sind Model Klassen. Die machen aber von sich aus nichts.
Dazu gibts den Controller, der mit dem Model kommuniziert und die Daten dann in der View (dem Template) darstellt.
Eine Guestbook Klasse mit Pagination etc, müsstest du also als Controller implementieren.
Lg

18

Sunday, May 30th 2010, 4:12pm

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.

This post has been edited 1 times, last edit by "Illidan" (May 30th 2010, 4:17pm)


19

Sunday, May 30th 2010, 7:51pm

ja, wenn du eine Administrationsoberfläche machst, dann sind add/del/edit typische Methoden im Controller.
Aber du brauchst dann nicht für jedes Model einen Controller.. Meist ist es ja die selbe Funktionalität für alle Models.
Also behalte deine GästebuchController Klasse ruhig :)

Similar threads

Social bookmarks