MySQLDumper und Legacy-PHP unter PHP 7/8 zum Laufen bringen

Migration von PHP 7 auf PHP 8 — Datenbank-Kompatibilität sicherstellen

Du hast deinen Server auf PHP 7 oder PHP 8 aktualisiert, und plötzlich wirft MySQLDumper nur noch Fehlermeldungen? Das liegt daran, dass die alte mysql_*-Erweiterung seit PHP 7.0 komplett entfernt wurde. Keine Deprecation-Warnung mehr, kein Fallback — einfach weg. Das betrifft nicht nur MySQLDumper, sondern jedes Legacy-PHP-Tool, das noch die klassischen mysql_*-Funktionen verwendet.

Das Problem: mysql_* vs. mysqli_*

Die alte MySQL-Erweiterung (mysql_*) war über ein Jahrzehnt der Standard für PHP-Datenbankzugriffe. Ab PHP 5.5 wurde sie als deprecated markiert, ab PHP 7.0 ist sie entfernt. Die Nachfolgerin heißt mysqli_* (MySQL Improved) und bietet mehr Funktionen, bessere Sicherheit und Support für Prepared Statements.

Typische Fehlermeldungen nach dem PHP-Upgrade:

Fatal error: Uncaught Error: Call to undefined function mysql_connect()
Fatal error: Uncaught Error: Call to undefined function mysql_query()
Fatal error: Uncaught Error: Call to undefined function mysql_real_escape_string()

Die Lösung: Alle mysql_*-Aufrufe durch ihre mysqli_*-Pendants ersetzen. Klingt einfach — hat aber ein paar Fallstricke.

Die wichtigsten Funktions-Umbenennungen

Hier die häufigsten Funktionen und ihre modernen Entsprechungen:

Alt (mysql_*) Neu (mysqli_*) Hinweis
mysql_connect() mysqli_connect() Parameter-Reihenfolge gleich
mysql_select_db($db) mysqli_select_db($link, $db) Connection-Parameter kommt zuerst
mysql_query($sql) mysqli_query($link, $sql) Connection-Parameter erforderlich
mysql_fetch_array($result) mysqli_fetch_array($result) Kompatibel
mysql_fetch_assoc($result) mysqli_fetch_assoc($result) Kompatibel
mysql_fetch_row($result) mysqli_fetch_row($result) Kompatibel
mysql_num_rows($result) mysqli_num_rows($result) Kompatibel
mysql_affected_rows() mysqli_affected_rows($link) Connection-Parameter erforderlich
mysql_real_escape_string($str) mysqli_real_escape_string($link, $str) Connection-Parameter erforderlich
mysql_error() mysqli_error($link) Connection-Parameter erforderlich
mysql_close() mysqli_close($link) Connection-Parameter erforderlich
mysql_insert_id() mysqli_insert_id($link) Connection-Parameter erforderlich

Der größte Unterschied: Bei mysqli_* musst du fast überall die Datenbankverbindung als ersten Parameter mitgeben. Bei den alten mysql_*-Funktionen war das optional — PHP hat einfach die zuletzt geöffnete Verbindung genommen.

Code-Beispiel: Vorher und Nachher

Alter Code (PHP 5.x, funktioniert nicht mehr):

// Verbindung herstellen
$conn = mysql_connect('localhost', 'root', 'passwort');
mysql_select_db('meine_datenbank');

// Abfrage
$result = mysql_query("SELECT * FROM users WHERE active = 1");

while ($row = mysql_fetch_assoc($result)) {
    echo $row['username'] . "\n";
}

// Escaping
$name = mysql_real_escape_string($_POST['name']);
$sql = "INSERT INTO users (name) VALUES ('$name')";
mysql_query($sql);

mysql_close($conn);

Neuer Code (PHP 7/8, mysqli):

// Verbindung herstellen
$conn = mysqli_connect('localhost', 'root', 'passwort', 'meine_datenbank');

if (!$conn) {
    die('Verbindung fehlgeschlagen: ' . mysqli_connect_error());
}

// Abfrage
$result = mysqli_query($conn, "SELECT * FROM users WHERE active = 1");

while ($row = mysqli_fetch_assoc($result)) {
    echo $row['username'] . "\n";
}

// Escaping (besser: Prepared Statements verwenden!)
$name = mysqli_real_escape_string($conn, $_POST['name']);
$sql = "INSERT INTO users (name) VALUES ('$name')";
mysqli_query($conn, $sql);

mysqli_close($conn);

Das MySQLConverterTool

Oracle hat auf GitHub das MySQLConverterTool bereitgestellt, das die Konvertierung automatisch durchführt. Es ist ein PHP-Skript, das deinen Quellcode scannt und mysql_*-Aufrufe durch mysqli_* ersetzt.

# Repository klonen
git clone https://github.com/niclasleonbock/MySQLConverterTool.git

# Oder das Original von Oracle (falls verfügbar)
git clone https://github.com/mysql/mysql-converter-tool.git

Das Tool macht einen guten ersten Durchlauf, aber du musst danach manuell nacharbeiten. Es gibt Fälle, die das Tool nicht korrekt konvertiert.

Manuelle Fixes: Die häufigsten Stolpersteine

1. Die db_escape-Funktion

Viele Legacy-Projekte — darunter auch MySQLDumper — haben eigene Wrapper-Funktionen für das Escaping. Die müssen ebenfalls angepasst werden:

// Alt:
function db_escape($string) {
    return mysql_real_escape_string($string);
}

// Neu — braucht die Connection:
function db_escape($string, $conn) {
    return mysqli_real_escape_string($conn, $string);
}

// Oder als globale Variable:
function db_escape($string) {
    global $dbconn;
    return mysqli_real_escape_string($dbconn, $string);
}

2. Implizite Verbindung entfernen

Der alte Code verlässt sich oft darauf, dass PHP die letzte Verbindung automatisch verwendet. Bei mysqli_* musst du die Verbindung explizit übergeben. Suche im Code nach allen Stellen, die mysql_query() ohne Verbindungsparameter aufrufen, und ergänze den $conn-Parameter.

3. mysql_result() gibt es nicht mehr

Die Funktion mysql_result() hat kein direktes mysqli_*-Pendant. Du musst sie umschreiben:

// Alt:
$value = mysql_result($result, 0, 'name');

// Neu:
$row = mysqli_fetch_assoc($result);
$value = $row['name'];

PHP-Migration Checkliste: Weitere Fallstricke ab PHP 7/8

Neben mysql_* gibt es weitere Änderungen, die bei der Migration von altem PHP-Code zu Problemen führen:

PHP 7.0+

  • ereg() und eregi() entfernt — ersetzen durch preg_match()
  • split() entfernt — ersetzen durch explode() oder preg_split()
  • Konstruktor-Methoden mit Klassennamen (function ClassName()) deprecated — verwende __construct()
  • Strikte Typprüfung: == verhält sich bei String-Vergleichen anders

PHP 8.0+

  • each() entfernt — ersetzen durch foreach
  • create_function() entfernt — ersetzen durch anonyme Funktionen
  • Named Arguments und Union Types — kein Problem bei altem Code, aber gut zu wissen
  • Match-Expressions als Alternative zu Switch
  • Wichtig: Viele Funktionen geben bei Fehlern jetzt TypeError statt false zurück

PHP 8.1+

  • FILTER_SANITIZE_STRING deprecated
  • Implizite Konvertierungen von Float zu Int werfen Deprecation-Notices
  • $GLOBALS ist nicht mehr beschreibbar als Variable

MySQLDumper konkret auf PHP 8 bringen

Für MySQLDumper selbst sieht der Prozess so aus:

  1. Alle PHP-Dateien durchsuchen: grep -rn "mysql_" *.php
  2. Ersetze mysql_connect durch mysqli_connect mit dem vierten Parameter (Datenbankname)
  3. Ersetze alle mysql_query($sql) durch mysqli_query($conn, $sql)
  4. Ersetze mysql_real_escape_string durch mysqli_real_escape_string mit Connection
  5. Ersetze mysql_result durch mysqli_fetch_*-Konstrukte
  6. Teste jede Funktion einzeln: Backup erstellen, Backup wiederherstellen, Tabellenliste, Datenbank-Info
# Alle betroffenen Dateien finden
grep -rln "mysql_connect\|mysql_query\|mysql_fetch\|mysql_real_escape" /pfad/zu/mysqldumper/

# Schnelle Ersetzung mit sed (vorher Backup machen!)
sed -i 's/mysql_query(/mysqli_query($GLOBALS["dbconn"], /g' datei.php
sed -i 's/mysql_fetch_assoc(/mysqli_fetch_assoc(/g' datei.php

Achtung: Die sed-Methode ist nur der erste Schritt. Du musst danach alle Dateien manuell prüfen, besonders Stellen mit mysql_real_escape_string und mysql_select_db.

Alternative: Polyfill-Lösung (Notlösung)

Falls du keine Zeit für die vollständige Migration hast, gibt es eine Notlösung: einen Polyfill, der die alten mysql_*-Funktionen als Wrapper um mysqli_* nachbildet. Das ist keine dauerhafte Lösung, kann aber kurzfristig helfen:

// mysql_polyfill.php — am Anfang deiner Anwendung einbinden
if (!function_exists('mysql_connect')) {
    function mysql_connect($server, $user, $password) {
        global $__mysql_polyfill_conn;
        $__mysql_polyfill_conn = mysqli_connect($server, $user, $password);
        return $__mysql_polyfill_conn;
    }

    function mysql_select_db($database) {
        global $__mysql_polyfill_conn;
        return mysqli_select_db($__mysql_polyfill_conn, $database);
    }

    function mysql_query($query) {
        global $__mysql_polyfill_conn;
        return mysqli_query($__mysql_polyfill_conn, $query);
    }

    // ... weitere Funktionen analog
}

Fazit

Die Migration von mysql_* auf mysqli_* ist keine Raketenwissenschaft, aber sie erfordert Sorgfalt. Besonders bei gewachsenen Projekten wie MySQLDumper, wo die Datenbankverbindung implizit überall genutzt wird, musst du jede Datei einzeln prüfen. Das MySQLConverterTool nimmt dir die Fleißarbeit ab, aber die manuellen Fixes — vor allem bei Wrapper-Funktionen und mysql_result() — musst du selbst machen.

Falls du dabei auf Timeout-Probleme stößt, hilft dir der Artikel PHP-Timeout bei großen Datenbanken weiter.