Die Regeln für das Hinzufügen einer PHP-Variable innerhalb einer MySQL-Anweisung sind schlicht und einfach:
- Jede Variable, die ein SQL-Datenliteral darstellt , (oder einfach ausgedrückt - ein SQL-String oder eine Zahl) MUSS durch eine vorbereitete Anweisung hinzugefügt werden. Keine Ausnahmen.
- Jeder andere Abfrageteil, wie ein SQL-Schlüsselwort, ein Tabellen- oder Feldname oder ein Operator, muss durch eine weiße Liste gefiltert werden .
Da es sich bei Ihrem Beispiel also nur um Datenliterale handelt, müssen alle Variablen durch Platzhalter (auch Parameter genannt) hinzugefügt werden. Dazu:
- Ersetzen Sie in Ihrer SQL-Anweisung alle Variablen durch Platzhalter
- vorbereiten die resultierende Abfrage
- binden Variablen zu Platzhaltern
- ausführen die Abfrage
Und so machen Sie es mit allen gängigen PHP-Datenbanktreibern:
Hinzufügen von Datenliteralen mit mysql ext
Ein solcher Treiber existiert nicht .
Hinzufügen von Datenliteralen mit mysqli
$type = 'testing';
$reporter = "John O'Hara";
$query = "INSERT INTO contents (type, reporter, description)
VALUES(?, ?, 'whatever')";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("ss", $type, $reporter);
$stmt->execute();
Der Code ist etwas kompliziert, aber die detaillierte Erklärung all dieser Operatoren finden Sie in meinem Artikel How to run an INSERT-Abfrage mit Mysqli , sowie eine Lösung, die den Prozess erheblich vereinfacht.
Für eine SELECT-Abfrage müssen Sie nur einen Aufruf von get_result()
hinzufügen Methode, um ein bekanntes mysqli_result
zu erhalten aus der Sie die Daten wie gewohnt abrufen können:
$reporter = "John O'Hara";
$stmt = $mysqli->prepare("SELECT * FROM users WHERE name=?");
$stmt->bind_param("s", $reporter);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc(); // or while (...)
Hinzufügen von Datenliteralen mit PDO
$type = 'testing';
$reporter = "John O'Hara";
$query = "INSERT INTO contents (type, reporter, description)
VALUES(?, ?, 'whatever')";
$stmt = $pdo->prepare($query);
$stmt->execute([$type, $reporter]);
In PDO können wir die Bind- und Execute-Teile kombinieren, was sehr praktisch ist. PDO unterstützt auch benannte Platzhalter, die manche als äußerst praktisch empfinden.
Hinzufügen von Schlüsselwörtern oder Identifikatoren
Manchmal müssen wir eine Variable hinzufügen, die einen anderen Teil einer Abfrage darstellt, z. B. ein Schlüsselwort oder eine Kennung (eine Datenbank, eine Tabelle oder ein Feldname). Es ist ein seltener Fall, aber es ist besser, vorbereitet zu sein.
In diesem Fall muss Ihre Variable explizit gegen eine Werteliste geprüft werden in Ihrem Skript geschrieben. Dies wird in meinem anderen Artikel erklärt, Hinzufügen eines Feldnamens in der ORDER BY-Klausel basierend auf der Wahl des Benutzers :
Leider hat PDO keinen Platzhalter für Bezeichner (Tabellen- und Feldnamen), daher muss ein Entwickler sie manuell herausfiltern. Ein solcher Filter wird oft als „weiße Liste“ bezeichnet (wo wir nur zulässige Werte auflisten) im Gegensatz zu einer „schwarzen Liste“, auf der wir unzulässige Werte auflisten.
Wir müssen also explizit alle möglichen Varianten im PHP-Code auflisten und dann aus ihnen auswählen.
Hier ist ein Beispiel:
$orderby = $_GET['orderby'] ?: "name"; // set the default value
$allowed = ["name","price","qty"]; // the white list of allowed field names
$key = array_search($orderby, $allowed, true); // see if we have such a name
if ($key === false) {
throw new InvalidArgumentException("Invalid field name");
}
Genauso sollte für die Richtung vorgegangen werden,
$direction = $_GET['direction'] ?: "ASC";
$allowed = ["ASC","DESC"];
$key = array_search($direction, $allowed, true);
if ($key === false) {
throw new InvalidArgumentException("Invalid ORDER BY direction");
}
Nach einem solchen Code werden sowohl $direction
und $orderby
Variablen können sicher in die SQL-Abfrage eingefügt werden, da sie entweder gleich einer der erlaubten Varianten sind oder ein Fehler ausgegeben wird.
Zu guter Letzt müssen Identifikatoren noch entsprechend der jeweiligen Datenbanksyntax formatiert werden. Für MySQL sollte es backtick
sein Zeichen um die Kennung. Die abschließende Abfragezeichenfolge für unser Bestellbeispiel wäre also
$query = "SELECT * FROM `table` ORDER BY `$orderby` $direction";