Signatur
Beschreibung
mysqli_prepare() sendet eine SQL-Anweisung an den MySQL-Server, der sie kompiliert und einen Ausführungsplan erstellt, ohne sie sofort auszuführen. Parameter werden als Fragezeichen (?) angegeben und später mit mysqli_stmt_bind_param() gebunden. Dadurch werden Benutzerdaten niemals direkt in den SQL-String interpoliert, was SQL-Injection-Angriffe strukturell ausschließt.
Das Prepared-Statement-Modell ist besonders sinnvoll, wenn dieselbe Abfrage mehrfach mit unterschiedlichen Parameterwerten ausgeführt werden soll, da der Server den Ausführungsplan nur einmal erstellt. Außerdem entfällt manuelles Escaping vollständig – der Treiber übernimmt die korrekte Übertragung der Parameterwerte im binären Protokoll.
Die prozedurale Variante mysqli_prepare() verhält sich identisch zur objektorientierten Methode mysqli::prepare(). Das zurückgegebene mysqli_stmt-Objekt wird mit mysqli_stmt_bind_param(), mysqli_stmt_execute() und mysqli_stmt_bind_result() bzw. mysqli_stmt_get_result() weiterverarbeitet.
Nach der Nutzung sollte das Statement mit mysqli_stmt_close() freigegeben werden, um Ressourcen zurückzugeben.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $mysql Pflicht | mysqli | Eine aktive MySQLi-Verbindungsressource, wie sie von mysqli_connect() oder mysqli_init() zurückgegeben wird. |
|
| $query Pflicht | string | Die SQL-Anweisung mit ?-Platzhaltern für Parameter. Mehrere Anweisungen in einem String (durch Semikolon getrennt) sind nicht erlaubt. |
Rückgabewert
mysqli_stmt-Objekt, das das vorbereitete Statement repräsentiert. Bei einem Fehler (z. B. Syntaxfehler in der SQL-Anweisung oder fehlende Verbindung) wird false zurückgegeben. Fehlermeldungen können über mysqli_error() abgerufen werden.Beispiele
Einfache SELECT-Abfrage mit einem Parameter
<?php
$mysqli = mysqli_connect('localhost', 'user', 'secret', 'testdb');
if (!$mysqli) {
die('Verbindungsfehler: ' . mysqli_connect_error());
}
$stmt = mysqli_prepare($mysqli, 'SELECT id, name, email FROM users WHERE id = ?');
if ($stmt === false) {
die('Prepare-Fehler: ' . mysqli_error($mysqli));
}
$userId = 42;
mysqli_stmt_bind_param($stmt, 'i', $userId);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
while ($row = mysqli_fetch_assoc($result)) {
echo $row['id'] . ': ' . $row['name'] . ' – ' . $row['email'] . PHP_EOL;
}
mysqli_stmt_close($stmt);
mysqli_close($mysqli);
INSERT mit mehreren Parametern und Fehlerbehandlung
<?php
$mysqli = new mysqli('localhost', 'user', 'secret', 'testdb');
if ($mysqli->connect_errno) {
die('Verbindungsfehler: ' . $mysqli->connect_error);
}
// Prozeduraler Stil mit mysqli_prepare
$stmt = mysqli_prepare(
$mysqli,
'INSERT INTO users (name, email, age) VALUES (?, ?, ?)'
);
if ($stmt === false) {
die('Prepare fehlgeschlagen: ' . mysqli_error($mysqli));
}
$name = 'Erika Musterfrau';
$email = 'erika@example.com';
$age = 30;
mysqli_stmt_bind_param($stmt, 'ssi', $name, $email, $age);
if (mysqli_stmt_execute($stmt)) {
echo 'Eingefügt: ' . mysqli_stmt_affected_rows($stmt) . ' Zeile(n).' . PHP_EOL;
echo 'Neue ID: ' . mysqli_stmt_insert_id($stmt) . PHP_EOL;
} else {
echo 'Fehler: ' . mysqli_stmt_error($stmt) . PHP_EOL;
}
mysqli_stmt_close($stmt);
mysqli_close($mysqli);
// Wichtig · Fallstricke
Sicherheit: Prepared Statements sind der empfohlene Weg, um SQL-Injection zu verhindern. Benutzereingaben werden niemals direkt in den SQL-String eingefügt, sondern über das binäre Protokoll sicher übertragen. Ein manuelles Escaping mit mysqli_real_escape_string() ist daher überflüssig und sollte nicht kombiniert werden.
Tabellen- und Spaltennamen: Platzhalter (?) können ausschließlich für Datenwerte genutzt werden, nicht für Tabellen- oder Spaltennamen. Diese müssen bei dynamischen Abfragen manuell validiert und gegen eine Whitelist geprüft werden.
Mehrere Statements: mysqli_prepare() akzeptiert nur eine einzelne SQL-Anweisung. Der Versuch, mehrere Anweisungen durch ; zu trennen, schlägt fehl.
Fehlerbehandlung: Ab PHP 8.1 wirft MySQLi bei Fehlern standardmäßig Exceptions (mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT) ist der neue Standard). Es empfiehlt sich, dieses Verhalten explizit zu aktivieren, um false-Checks zu vermeiden.