Moin!
Ja. ich habe den Artikel gelesen, sogar mehrmals, weil ich anfangs nicht richtig begriffen habe, worauf der Schreiber hinaus wollte.
Hehe, du diskutierst gerade mit dem Schreiber. ;)
Verstanden habe ich folgendes:
Wenn ich einen String wie diesen hier habe (ist aus dem Artikel kopiert)
"SELECT feldliste FROM tabelle WHERE feld='$variable'";
>
> muss ich den String zwingend mit " beginnen und mit "; beenden. Außerdem muss ich darauf achten, die Werte, die ich in dem String eingebe ( z.B. $variable) in '' zu setzen. Das habe ich bei mir auch soweit berücksichtigt.
Darauf will der Artikel gar nicht hinaus!
In PHP musst du einen String, den du mit doppelten Anführungszeichen " beginnst, auch mit diesen wieder beenden.
Genauso gilt die Vorschrift, wenn du den String mit einfachen Anführungszeichen ' beginnst.
Das Semikolon dahinter hat eine vollkommen andere Aufgabe - es trennt die einzelnen Befehle voneinander, hat mit dem String aber gar nichts zu tun.
Das einbauen von Variablen in den String unterliegt erstmal auch "nur" den Vorschriften von PHP. Variablen werden nur "ausgewertet", d.h. ihr Inhalt in den String integriert, wenn der String von doppelten Anführungszeichen umschlossen ist.
Eine Variable in einem String benötigt aus PHP-Sicht aber keinerlei besonderen Zeichen drumherum. Das ist eine Anforderung, die sich daraus ergibt, dass du in diesem String ein MySQL-Kommando herstellst.
Und genau darum dreht sich der Artikel: Wie kriegt man den Inhalt von Variablen beispielsweise sicher in einen SQL-Befehl integriert?
Und das steht im Abschnitt "Verhindernde Maßnahmen", den du anscheinend noch nicht gelesen hast.
> ~~~php
> $aendern = "UPDATE rustleoaks Set
> bilderraetsel=1 WHERE benutzername LIKE '$benutzername'";
>
Den Wert 1 habe ich nicht mit Hochkommas versehen, da es einen T_String Fehler verursacht. Irgendwo habe ich gelesen, Zahlen dürfen nicht in Hochkommas gesetzt werden.
Der T_STRING-Fehler kommt von PHP. Er zeigt dir, dass du mit PHP einen Fehler gemacht hast. Es stimmt also irgendwas mit der PHP-Syntax nicht.
Das hat aber keine Bedeutung für das SQL, was du hier zusammenbaust. Der SQL-String, den die Datenbank ausführen soll, hat seinerseits eine Syntax, die beim Zusammenbauen natürlich auch zu beachten ist.
Für MySQL gilt: Zahlen KANN man ohne Anführungszeichen in den SQL-String schreiben, man KANN sie aber auch hinzufügen - das stört nicht, macht es aber einfacher, wenn Zahlen aus Variablen kommen und gesichert in den SQL-String geschrieben werden sollen.
Um zu verhindern, dass mir jemand einen Befehl über das Formular unterschiebt, sollte ich jedoch den String nichtso stehen lassen, sondern den Befehl mysql_real_escape_string() mit einfügen. Weiterer Vorteil, ich muss nicht darauf achten, ob ich etwas mit Backslash \ maskieren muss. Dann würde mein Befehl so aussehen:
$aendern = "UPDATE rustleoaks Set bilderraetsel='" . mysql_real_escape_string(1) . "' WHERE benutzername
LIKE '" . mysql_real_escape_string($_POST['benutzername']) . "'";
Aha, den Abschnitt hast du also doch gelesen... :)
Da es sich bei der Zahl 1 um einen von mir vorgegebenen Wert und nicht um einen Wert aus Benutzereingaben handelt, kann ich den Befehl so verwenden (benutze mySQL).
Für alles, was fest im String drinsteht und nicht aus Variablen kommt, brauchst du mysql_real_escape_string() nicht anwenden. Die feste Zahl "1" darf also direkt im SQL auftauchen.
Die Besonderheit bei der LIKE-Angabe habe ich noch nicht ganz kapiert. Darf ich hier den Befehl mysql_real_escape_string() gar nicht verwenden, oder wird es nur wegen der eventuellen Verwendung von sprintf und dem %-Zeichen besonders aufgeführt?
mysql_real_escape_string() sieht die Platzhalterzeichen % und _ nicht als besondere Zeichen an, die man escapen muss. Diese kommen also unverändert im SQL-String an.
Wenn du jetzt eine Benutzereingabe für eine Wildcard-Suche anwendest, wäre die erste Überlegung:
In SQL: Suche alles, was mit XYZ anfängt - und XYZ ist die Benutzereingabe.
[code lang=sql]SELECT ... FROM ... WHERE feld LIKE 'XYZ%'
In PHP: Bastel die Benutzereingabe in den String - aber bitte escapen.
~~~php
$sql = "SELECT ... FROM ... WHERE feld LIKE '".mysql_real_escape_string($searchFor)."%'",
Benutzereingabe lautet: % (der will halt alles suchen, was mit einem Prozentzeichen beginnt.
Resultierendes SQL:
SELECT ... FROM ... WHERE feld LIKE '%%'
Wirkung: Es wird nach allem gesucht, was in der Datenbank steht - LIKE '%%' filtert nichts, sondern findet alle Einträge.
Resultat: Es wird nicht nach dem Prozentzeichen gesucht, sondern alles gefunden. Das ist nicht, was der Benutzer wollte.
Korrekt wäre folgender SQL-String gewesen:
SELECT ... FROM ... WHERE feld LIKE '\%%'
Das würde nach allem suchen, was mit einem Prozentzeichen anfängt.
Da die MySQL-Extensions in PHP für diesen Sonderfall keine eigene Funktion anbieten, um diese Such-Platzhalter zu escapen, muss man sich das halt selbst bauen.
Die Anwendung von sprintf() an der Stelle ist nur eine Erleichterung für das Zusammensetzen des SQL-Strings. Die Vorlage des Strings steht in einem Rutsch für sich allein, und enthält an den entsprechenden Stellen Platzhalter (%s für "String"). Dahinter kommen die weiteren Parameter von sprintf, die von vorne nach hinten für jeden Platzhalter den einzufügenden Wert enthalten.
Das macht die Sache durchaus übersichtlicher, man muss es aber nicht so handhaben.
- Sven Rautenberg