84 Stimmen

Wie man eine PHP-Variable in einer MySQL-Anweisung einbindet

Ich versuche, Werte in die Inhalte-Tabelle einzufügen. Es funktioniert gut, wenn ich keine PHP-Variable innerhalb von VALUES habe. Wenn ich die Variable $type innerhalb von VALUES setze, dann funktioniert dies nicht. Was mache ich falsch?

$type = 'testing';
mysql_query("INSERT INTO contents (type, reporter, description) 
     VALUES($type, 'john', 'whatever')");

15 Stimmen

WICHTIG: Das direkte Einfügen von Variablen in Ihren SQL-Befehl ist eine Hauptursache von SQL Injection Attacken

136voto

Your Common Sense Punkte 154708

Die Regeln zur Hinzufügung einer PHP-Variablen in eine MySQL-Anweisung sind einfach und klar:

1. Verwenden Sie vorbereitete Anweisungen

Diese Regel deckt 99% der Abfragen und Ihre Abfrage im Besonderen ab. Jede Variable, die ein SQL-Datenliteral repräsentiert, (oder einfacher ausgedrückt - eine SQL-Zeichenfolge oder eine Zahl) MUSS über eine vorbereitete Anweisung hinzugefügt werden. Keine Ausnahmen. Ein konstanter Wert kann so eingefügt werden.

Dieser Ansatz beinhaltet vier grundlegende Schritte

  • ersetzen Sie in Ihrer SQL-Anweisung alle Variablen durch Platzhalter
  • vorbereiten Sie die resultierende Abfrage
  • binden Sie Variablen an die Platzhalter
  • führen Sie die Abfrage aus

Und so wird es mit allen populären PHP-Datenbanktreibern gemacht:

Hinzufügen von Datenliteralen mit mysqli

Ab PHP 8.2 können Sie die gesamte Vorbereitungs-/Bindungs-/Ausführungsfolge in einem Aufruf durchführen:

$type = 'testing';
$reporter = "John O'Hara";
$sql = "INSERT INTO contents (type,reporter,description) VALUES ('whatever',?,?)";
$mysqli->execute_query($sql, [$reporter, $description]);

Wenn Ihre PHP-Version alt ist, dann muss Vorbereiten/Binden/Ausführen explizit gemacht werden:

$type = 'testing';
$reporter = "John O'Hara";
$sql = "INSERT INTO contents (type,reporter,description) VALUES ('whatever',?,?)";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("ss", $reporter, $description);
$stmt->execute();

Der Code ist etwas kompliziert, aber eine ausführliche Erklärung aller dieser Operatoren finden Sie in meinem Artikel Wie man eine INSERT-Abfrage mit Mysqli ausführt, sowie eine Lösung, die den Prozess erheblich erleichtert.

Für eine SELECT-Abfrage können Sie dieselbe Methode wie oben verwenden:

$reporter = "John O'Hara";
$result = $mysqli->execute_query("SELECT * FROM users WHERE name=?", [$reporter]);
$row = $result->fetch_assoc(); // oder while (...)

Aber wieder, wenn Ihre PHP-Version alt ist, müssen Sie den Vorbereitungs-/Bindungs-/Ausführungsprozess durchlaufen und auch einen Aufruf der get_result()-Methode hinzufügen, um ein vertrautes mysqli_result zu erhalten, aus dem Sie die Daten auf übliche Weise 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(); // oder while (...)
Hinzufügen von Datenliteralen mit PDO
$type = 'testing';
$reporter = "John O'Hara";
$sql = "INSERT INTO contents (type,reporter,description) VALUES ('whatever',?,?)";
$stmt = $pdo->prepare($sql);
$stmt->execute([$reporter, $description]);

In PDO können Bindungs- und Ausführungsteile kombiniert werden, was sehr praktisch ist. PDO unterstützt auch benannte Platzhalter, die einige als äußerst praktisch empfinden.

2. Verwenden Sie White-Listen-Filterung

Jeder andere Abfrageteil, wie SQL-Schlüsselwort, Tabelle oder Feldname oder Operator, muss durch eine White-Liste gefiltert werden.

Manchmal müssen wir eine Variable hinzufügen, die einen anderen Teil einer Abfrage darstellt, wie ein Schlüsselwort oder einen Bezeichner (einen Datenbank-, Tabellen- oder Feldnamen). Es ist ein seltener Fall, aber es ist besser, vorbereitet zu sein.

In diesem Fall muss Ihre Variable gegen eine Liste von Werten explizit geprüft werden, die in Ihrem Skript festgelegt sind. Dies wird in meinem anderen Artikel erklärt, Hinzufügen eines Feldnamens in die 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 filtern. Ein solcher Filter wird oft als "White-Liste" bezeichnet (wo wir nur erlaubte Werte auflisten) im Gegensatz zu einer "Black-Liste", wo wir nicht erlaubte Werte auflisten.

Also müssen wir alle möglichen Varianten im PHP-Code explizit auflisten und dann daraus auswählen.

Hier ist ein Beispiel:

$orderby = $_GET['orderby'] ?: "name"; // setze den Standardwert
$allowed = ["name","price","qty"]; // die White-Liste erlaubter Feldnamen
$key = array_search($orderby, $allowed, true); // prüfen, ob wir einen solchen Namen haben
if ($key === false) { 
    throw new InvalidArgumentException("Ungültiger Feldname"); 
}

Der gleiche Ansatz sollte auch für die Richtung verwendet werden,

$direction = $_GET['direction'] ?: "ASC";
$allowed = ["ASC","DESC"];
$key = array_search($direction, $allowed, true);
if ($key === false) { 
    throw new InvalidArgumentException("Ungültige ORDER BY-Richtung"); 
}

Nach einem solchen Code können sowohl die Variablen $direction als auch $orderby sicher in die SQL-Abfrage eingefügt werden, da sie entweder einem der erlaubten Varianten entsprechen oder ein Fehler geworfen wird.

Zum Schluss muss noch erwähnt werden, dass Bezeichner auch entsprechend der spezifischen Datenbankensyntax formatiert werden müssen. Für MySQL sollten es backtick-Zeichen um den Bezeichner sein. Die endgültige Abfragezeichenfolge für unser Beispiel des ORDER BY würde also sein

$query = "SELECT * FROM `table` ORDER BY `$orderby` $direction";

10voto

Stefan Punkte 197

Um SQL-Injektionen zu vermeiden, wird die Einfügeanweisung wie folgt sein

$typ = 'testing';
$name = 'john';
$beschreibung = 'was auch immer';

$con = new mysqli($benutzer, $passwort, $ Datenbank);
$stmt = $con->prepare("INSERT INTO inhalte (typ, berichterstatter, beschreibung) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $typ , $name, $beschreibung);
$stmt->execute();

0 Stimmen

Was ist, wenn ich versuche, ein Profil anzuzeigen und in meinem $stmt folgendes habe: 'SELECT * FROM Profile WHERE profile_id LIKE (?)'.. Ich habe nur einen Parameter, den ich in meinem SQL einfügen muss. Wie gehe ich dabei vor?

4voto

Tel Punkte 404

Die beste Option sind vorbereitete Anweisungen. Das Hantieren mit Anführungszeichen und Escapes ist zu Beginn schwerer und schwierig zu pflegen. Früher oder später werden Sie wahrscheinlich vergessen, etwas zu zitieren oder zweimal den gleichen String zu maskieren oder so etwas durcheinander zu bringen. Es könnte Jahre dauern, bis Sie diese Art von Fehlern finden.

http://php.net/manual/de/pdo.prepared-statements.php

2voto

Spencer Rose Punkte 1130

Der Text innerhalb von $type wird direkt in den Einfügestrang eingesetzt, daher erhält MySQL dies:

... VALUES(testing, 'john', 'whatever')

Beachten Sie, dass um testing keine Anführungszeichen stehen. Diese müssen wie folgt hinzugefügt werden:

$type = 'testing';
mysql_query("INSERT INTO contents (type, reporter, description) VALUES('$type', 'john', 'whatever')");

Ich empfehle außerdem, sich über SQL-Injection zu informieren, da diese Art der Parameterübergabe anfällig für Hacking-Versuche ist, wenn die verwendeten Daten nicht gesäubert werden:

2voto

Baloomba Punkte 59

Das ist die einfache Antwort:

$query="SELECT * FROM CountryInfo WHERE Name = '".$name."'";

und du definierst $name wie auch immer du willst.
Und eine andere Möglichkeit, der komplizierte Weg, ist wie folgt:

$query = " SELECT '" . $GLOBALS['Name'] . "' .* " .
         " FROM CountryInfo " .
         " INNER JOIN District " .
         " ON District.CountryInfoId = CountryInfo.CountryInfoId " .
         " INNER JOIN City " .
         " ON City.DistrictId = District.DistrictId " .
         " INNER JOIN '" . $GLOBALS['Name'] . "' " .
         " ON '" . $GLOBALS['Name'] . "'.CityId = City.CityId " .
         " WHERE CountryInfo.Name = '" . $GLOBALS['CountryName'] .
         "'";

2 Stimmen

....aber das ist auch die gefährlichste aller Antworten. Du hast nicht einmal versucht, SQL-Injectionen auf irgendeine Weise zu vermeiden, und ein solcher Code sollte niemals verwendet werden

0 Stimmen

Auch, es gibt einen Fehler. Die Syntax ist falsch. Es sollte so sein: ". $variable . "

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X