Arno: In Datenbank wird nichts geschrieben

Hallo ihr fleißigen Helfer!
Ich lerne seit Kurzem PHP. Dazu arbeite ich mich von Kapitel zu Kapitel nach einem Tutorial. Bisher hat alles ganz gut geklappt, nun komme ich aber echt nicht weiter. Ich erstelle ein Loginskript.
Folgendes Problem: Wenn ich mich registrieren will, wird nichts in die Datenbank geschrieben! Kennt ihr dieses Problem?
Das sind meine Dateien:
index.php

  
<?php  
error_reporting(E_ALL);  
ini_set('display_errors', 1);  
  
$dateien = array();  
$dateien['news'] = 'news.php';  
$dateien['register'] = 'register.php';  
  
include 'constants.php';  
include 'functions.php';  
  
  
$db = @new MySQLi('localhost', 'root', 'test', 'test');  
$ret = 1; // speichert den rückgabewert von include, standardwert 1  
if (mysqli_connect_errno()) {  
    $ret = 'Konnte keine Verbindung zu Datenbank aufbauen, MySQL meldete: '.mysqli_connect_error();  
} else if (is_string($error = getUserID($db))) { // String, also ein MySQL Fehler  
    $ret = $error; // die Fehlermeldung in $ret speichern, damit sie angezeigt wird.  
} else {  
  
  
// Laden der Include-Datei  
/*  
 * Die Include-Datei muss eine return Anweisung enthalten mit folgenden  
 * Werten:  
 * - Bei normaler Ausführung  
 *   Array('filename' => string, -- Dateiname vom Template  
 *         'data' => Array())    -- Array mit Daten für das Template  
 * - Bei einem Fehler  
 *   string  -- Die Fehlermeldung die angezeigt werden soll.  
 */  
if (isset($_GET['section'], $dateien[$_GET['section']])) {  
    if (file_exists('includes/'.$dateien[$_GET['section']])) {  
        $ret = include 'includes/'.$dateien[$_GET['section']];  
    } else {  
        $ret = "Include-Datei konnte nicht geladen werden: 'includes/".$dateien[$_GET['section']]."'";  
    }  
} else {  
    // default bereich laden, news  
    $ret = include $dateien['news'];  
}  
  
}  
  
// Laden des HTML-Kopfs  
include 'header.html';   // Doctype, <html>, <head>, <meta> kram  
  
// Laden der Template-Datei  
if (is_array($ret) and isset($ret['filename'], $ret['data']) and  
        is_string($ret['filename']) and  
        is_array($ret['data'])) {  
    // Gültige Include-Datei  
    if (file_exists($file = $ret['filename'])) {  
        $data = $ret['data']; // speicher die Arraydaten in eine Variable $data  
                              // die dann im Template verwendet werden kann.  
        include $file;  
    } else {  
        $data['msg'] = 'Templatedatei "'.$file.'" ist nicht vorhanden.';  
        include 'templates/error.tpl';  
    }  
} else if (is_string($ret)) {  
    // Fehlermeldung  
    $data['msg'] = $ret;  
    include 'templates/error.tpl';  
} else if (1 === $ret) {  
    // return wurde vergessen  
    $data['msg'] = 'In der Include-Datei wurde die return Anweisung vergessen.';  
    include 'templates/error.tpl';  
} else {  
    // ein Ungültiger Return wert  
    $data['msg'] = 'Die Include-Datei hat einen ungültigen Wert zurückgeliefert.';  
    include 'templates/error.tpl';  
}  
  
  
// HTML footer laden  
include 'footer.html';  // Zeug wie </body> und </html>  
?>  

sql

  
CREATE TABLE User (  
    ID INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,  
    Username VARCHAR(30) NOT NULL,  
    Password CHAR(32) NOT NULL,  
    Email VARCHAR(100) NOT NULL  
);  

register.php

  
<?php  
if (getuserID($db)) {  
    return 'Sie sind eingeloggt und können sich nicht registieren.';  
}  
$ret = array();  
$ret['filename'] = 'register.tpl';  
$ret['data'] = array();  
if ('POST' == $_SERVER['REQUEST_METHOD']) {  
    if (!isset($_POST['Username'], $_POST['Password'], $_POST['Email'],  
               $_POST['Antwort'], $_POST['formaction'])) {  
        return INVALID_FORM;  
    }  
    if (!is_array($_POST['Password']) OR count($_POST['Password']) != 2) {  
        return INVALID_FORM;  
    }  
    if ($_POST['Password'][0] != $_POST['Password'][1]) {  
        return 'Bitte geben sie das gleiche Password ein.';  
    }  
    if (($Username = trim($_POST['Username'])) == '' OR  
            ($Password = trim($_POST['Password'][0])) == '' OR  
            ($Email = trim($_POST['Email'])) == '' OR  
            ($Antwort = trim($_POST['Antwort'])) == '') {  
        return EMPTY_FORM;  
    }  
    if ('Antwort' != $Antwort) { // entsprechend anpassen  
        return 'Bitte geben sie die richtige Antwort an.';  
    }  
    if (!preg_match('~\A\S{3,30}\z~', $Username)) {  
        return 'Der Benutzername darf nur aus 3 bis 30 Zeichen bestehen und '.  
               'keine Leerzeichen enthalten.';  
    }  
  
    $sql = 'SELECT  
                ID  
            FROM  
                user  
            WHERE  
                Username = ?  
            LIMIT  
                1';  
    $stmt = $db->prepare($sql);  
    if (!$stmt) {  
        return $db->error;  
    }  
    $stmt->bind_param('s', $Username);  
    $stmt->execute();  
    $stmt->store_result();  
    if ($stmt->num_rows) {  
        return 'Der Username wird bereits verwendet.';  
    }  
    $stmt->close();  
  
    $sql = 'INSERT INTO  
                user(Username, Email)  
            VALUES  
                (?, ?)';  
    $stmt = $db->prepare($sql);  
    if (!$stmt) {  
        return $db->error;  
    }  
  
    $stmt->bind_param('ss', $Username, $Email);  
    if (!$stmt->execute()) {  
        return $stmt->error;  
    }  
    $userID = $stmt->insert_id;  
    $sql = 'UPDATE  
                user  
            SET  
                Password = ?  
            WHERE  
                ID = ?';  
    $stmt = $db->prepare($sql);  
    if (!$stmt) {  
        return $db->error;  
    }  
    $Hash = md5(md5($userID).$Password);  
    $stmt->bind_param('si', $Hash, $userID);  
    if (!$stmt->execute()) {  
        return $stmt->error;  
    }  
    return showInfo('Der Benutzer wurde hinzugefügt. Sie können sich nun anmelden.');  
}  
  
?>  

  1. Hi!

    Folgendes Problem: Wenn ich mich registrieren will, wird nichts in die Datenbank geschrieben! Kennt ihr dieses Problem?

    Nein, nicht direkt. Diese Beschreibung ist zu allgemein, der Ursachen kann es viele haben. Denen kann und muss man sich durch Debugging nähern, wenn man die Stelle nicht durch Betrachten des Codes findet. Je länger der Code ist desto geringer wird die Lust, sich da durchzuarbeiten, besonders wenn er viele unrelevante Teile enthält. Tu also bitte dir und uns den Gefallen und grenze den Fehler weiter ein. Dazu kannst du mit Kontrollausgaben von Variableninhalten und Rückgabewerten der Funktionen ermitteln, wo Wunsch und Wirklichkeit auseinanderlaufen. Für Kontrollausgaben liefert var_dump() die genauesten Werte. Eine weitere Strategie ist, das Problem durch Streichen von unrelevanten Code einzukreisen. Je weniger Code übrigbleibt, desto einfacher lässt sich dieser untersuchen und Tests an ihm vornehmen.

    error_reporting(E_ALL);
    ini_set('display_errors', 1);

    Das ist schonmal sehr gut. Allerdings fügen sich die MySQL-Funktionen nicht so richtig in das Fehlermeldungskonzept PHPs ein. Sie hängen in der Datenbank aufgetretene Fehler nicht an die große Glocke sondern signalisieren sie leise über ihren Rückgabewert. Frag also bitte immer die Rückgabewerte auf einen Fehlerzustand ab.

    $db = @new MySQLi('localhost', 'root', 'test', 'test');
    if (mysqli_connect_errno()) {
        $ret = 'Konnte keine Verbindung zu Datenbank aufbauen, MySQL meldete: '.mysqli_connect_error();
    } else if (is_string($error = getUserID($db))) { // String, also ein MySQL Fehler
        $ret = $error; // die Fehlermeldung in $ret speichern, damit sie angezeigt wird.
    } else {

    Dein Code ist ja schon einigermaßen gut strukturiert und reagiert auch auf viele Fehlerstände, wie dieses Beispiel zeigt. Allerdings macht er das nicht überall.

    $stmt = $db->prepare($sql);
        if (!$stmt) {
            return $db->error;
        }
        $stmt->bind_param('s', $Username);
        $stmt->execute();
        $stmt->store_result();

    Das Prepare prüfst du noch. Bind schon nicht mehr. Wichtiger ist jedoch das Execute, denn da passiert die eigentliche Abfrage und potentiell die meisten Fehler.

    $stmt = $db->prepare($sql);
        if (!$stmt) {
            return $db->error;
        }
        $stmt->bind_param('ss', $Username, $Email);
        if (!$stmt->execute()) {
            return $stmt->error;
        }

    Kurz danach bist du wieder fast vorbildlich. Zumindest das Execute ist "gesichert".

    Wie auch immer, versuch den Fehler weiter einzugrenzen. Wenn du die Möglichkeit hast, kannst du auch ein Query-Log im MySQL-Server einrichten, dann siehst du, welche Statements in welcher Reihenfolge abgearbeitet werden (und demzufolge auch, welche nicht).

    Lo!