PHP MySQLi
PHP MySQLi-Erweiterung: Datenbankverbindung, sichere Abfragen mit Prepared Statements, Fehlerbehandlung und Vergleich mit PDO.
MySQLi („MySQL Improved") ist die PHP-Erweiterung, mit der Sie sich mit einer MySQL- oder MariaDB-Datenbank verbinden, Abfragen ausführen und Ergebnisse lesen. Dieser Artikel erklärt, was die Erweiterung ist, wie man eine Verbindung herstellt, wie man SELECT/INSERT/UPDATE-Abfragen sicher ausführt und wann MySQLi gegenüber PDO zu bevorzugen ist.
Was ist die MySQLi-Erweiterung?
Die MySQLi-Erweiterung ist der Nachfolger der alten (und inzwischen entfernten) mysql_*-Funktionen. Sie bietet Funktionen, die die ursprüngliche Erweiterung nie hatte: Prepared Statements, Transaktionen, mehrere Anweisungen und ordentliche Unterstützung für MySQL-4.1+-Authentifizierung. Sie ist in PHP enthalten und auf den meisten Installationen standardmäßig aktiviert.
MySQLi stellt dieselbe Funktionalität über zwei Schnittstellen bereit:
- Objektorientiert — Sie arbeiten mit einem
mysqli-Objekt und rufen Methoden wie$mysqli->query()auf. Dies ist der Stil, den moderner Code überwiegend verwendet, und dem dieser Artikel folgt. - Prozedural — Sie rufen Funktionen wie
mysqli_connect()undmysqli_query()auf und übergeben die Verbindung als erstes Argument.
Beide tun exakt dasselbe; wählen Sie einen Stil und bleiben Sie dabei. Die objektorientierte Form ist kürzer und lässt sich natürlicher lesen.
Mit einer Datenbank verbinden
Eine Verbindung wird durch ein mysqli-Objekt dargestellt. Sie erstellen eines, indem Sie Host, Benutzername, Passwort und Datenbankname an den Konstruktor übergeben, und prüfen anschließend, ob die Verbindung erfolgreich war, bevor Sie irgendetwas anderes tun:
<?php
$mysqli = new mysqli("localhost", "username", "password", "my_database");
// Always check the connection before using it.
if ($mysqli->connect_error) {
die("Failed to connect to MySQL: " . $mysqli->connect_error);
}
// Recommended: use UTF-8 so accented characters and emoji are stored correctly.
$mysqli->set_charset("utf8mb4");
echo "Connected successfully";
?>Die Eigenschaft connect_error enthält eine lesbare Fehlermeldung, wenn die Verbindung fehlschlägt (oder null bei Erfolg). Der Aufruf von set_charset() direkt nach dem Verbinden vermeidet spätere subtile Kodierungsfehler. Einen ausführlicheren Blick auf das Öffnen einer Verbindung bieten PHP mysqli_connect() und die connect()-Referenz.
Eine SELECT-Abfrage ausführen
Nach dem Verbinden führt query() SQL aus und gibt ein Ergebnisobjekt zurück, über das Sie iterieren können. fetch_assoc() gibt jeweils eine Zeile als assoziatives Array zurück oder null, wenn keine weiteren Zeilen vorhanden sind:
<?php
$result = $mysqli->query("SELECT name, email FROM users");
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
echo "Name: " . $row["name"] . " - Email: " . $row["email"] . "<br>";
}
} else {
echo "No users found.";
}
$result->free(); // release the result set
$mysqli->close(); // close the connection when you are done
?>num_rows gibt an, wie viele Zeilen zurückgekommen sind, sodass Sie eine freundliche Meldung anzeigen können, wenn eine Abfrage nichts liefert. Weitere Abfragemuster finden Sie unter PHP MySQL Select Data.
Prepared Statements (der sichere Umgang mit Benutzereingaben)
Fügen Sie niemals Benutzereingaben direkt in einen Abfrage-String ein — so entsteht SQL-Injection. Ein Prepared Statement sendet SQL und Daten getrennt, sodass die Datenbank die Eingabe ausschließlich als Wert und nie als ausführbares SQL behandelt.
Sie schreiben ?-Platzhalter, prepare() die Anweisung und übergeben dann mit bind_param() die eigentlichen Werte:
<?php
$age = 18;
$stmt = $mysqli->prepare("SELECT name, email FROM users WHERE age > ?");
$stmt->bind_param("i", $age); // "i" = integer (s = string, d = double, b = blob)
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo "Name: " . $row["name"] . " - Email: " . $row["email"] . "<br>";
}
$stmt->close();
?>Das erste Argument von bind_param() ist ein Typ-String: ein Zeichen pro Platzhalter — i (integer), s (string), d (double/float) oder b (blob). Die weiteren Argumente sind die Werte in der richtigen Reihenfolge.
Hinweis:
get_result()erfordert denmysqlnd-Treiber, der in modernem PHP der Standard ist. Wenn Ihre Version ihn nicht enthält, verwenden Sie stattdessenbind_result(), um Spalten an Variablen zu binden.
Eine ausführliche Anleitung finden Sie unter PHP MySQL Prepared Statements.
Daten einfügen und aktualisieren
Dasselbe Prepared-Statement-Muster funktioniert auch für Schreiboperationen. Nach einem INSERT ist die Auto-Increment-ID der neuen Zeile über $mysqli->insert_id verfügbar; nach einem INSERT/UPDATE/DELETE zeigt $mysqli->affected_rows, wie viele Zeilen geändert wurden:
<?php
$name = "Ada Lovelace";
$email = "[email protected]";
$stmt = $mysqli->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
$stmt->bind_param("ss", $name, $email); // two strings
$stmt->execute();
echo "Inserted user #" . $mysqli->insert_id;
$stmt->close();
?>Das vollständige CRUD-Bild finden Sie unter PHP MySQL Insert Data und PHP MySQL Update Data.
Fehlerbehandlung
Schlägt eine Abfrage fehl, gibt query() false zurück und die Details befinden sich am Verbindungsobjekt. Das Lesen von $mysqli->error nach einem fehlgeschlagenen Aufruf zeigt, was schiefgelaufen ist:
<?php
if (!$mysqli->query("SELECT * FROM no_such_table")) {
echo "Query failed (" . $mysqli->errno . "): " . $mysqli->error;
}
?>In der Entwicklung können Sie MySQLi dazu bringen, mit mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT) automatisch Ausnahmen auszulösen, was seit PHP 8.1 das Standardverhalten ist. Weiterführende Lektüre: PHP connect_error und PHP connect_errno.
MySQLi vs. PDO — was soll ich verwenden?
Beide sind sichere, moderne Wege, mit einer Datenbank zu kommunizieren. Kurz zusammengefasst:
- MySQLi funktioniert nur mit MySQL/MariaDB. Es bietet einige MySQL-spezifische Funktionen (wie asynchrone Abfragen), die PDO nicht hat.
- PDO (PHP Data Objects) unterstützt über eine einzige API ein Dutzend Datenbanken, sodass ein Wechsel von MySQL zu PostgreSQL nur eine geänderte Verbindungszeichenfolge erfordert, nicht Ihre Abfragen. Es unterstützt außerdem benannte Platzhalter (
:name), die leichter zu lesen sind.
Wenn Sie wissen, dass Sie ausschließlich MySQL verwenden werden, ist MySQLi vollkommen in Ordnung. Wenn Portabilität wichtig ist, bevorzugen Sie PDO. In jedem Fall: Verwenden Sie immer Prepared Statements.
Zusammenfassung
- MySQLi ist die Standard-Erweiterung für die Arbeit mit MySQL/MariaDB in PHP und steht in objektorientiertem und prozeduralem Stil zur Verfügung.
- Erstellen Sie eine Verbindung mit
new mysqli(...), prüfen Sieconnect_errorund legen Sie den Zeichensatz fest. - Verwenden Sie
query()+fetch_assoc(), um Daten zu lesen und über Ergebnisse zu iterieren. - Verwenden Sie Prepared Statements (
prepare()→bind_param()→execute()) für alles, was Benutzereingaben enthält, um SQL-Injection zu vermeiden. - Prüfen Sie
$mysqli->error/$mysqli->errno, wenn eine Abfrage fehlschlägt, und bevorzugen Sie PDO, wenn Sie Datenbankportabilität benötigen.