php-Zugriff auf mysql funktioniert nicht?
Ich habe folgende Funktion in PHP geschrieben:
function getName($id) {
global $conn;
$sql = "SELECT Vorname, Nachname FROM mitglieder WHERE ID = `$id`";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
$row = $result->fetch_assoc();
return $row['Vorname'] . " " . $row['Nachname'];
} else {
return "";
}
}
Aber aus irgendeinem Grund kommt immer folgende Fehlermeldung:
Warning: Attempt to read property "num_rows" on bool in C:\xampp\htdocs\***********.php on line 35
Diese Variable $conn funktioniert aber an anderer Stelle im globalen Code außerhalb dieser Funktion einwandfrei wie gewünscht und ich sehe vom Code her keinen nennenswerten Unterschied.
Was ich bereits versucht habe:
- $conn als Parameter an die Funktion zu übergeben
- $conn in der Funktion selber zu definieren
- $conn in der Funktion selber definieren und dass $conn im globalen Code entfernen
- ChatGPT nach dem Fehler fragen
- Folgende Fehlerabfrage einzubauen (dabei war $conn auch in der Funktion selber und NUR in der Funktion selber definiert):
if ($conn->connect_error) {
die("Serverfehler: " . $conn->connect_error);
}
Das führte aber nur zu folgender Fehlermeldung:
Warning: Attempt to read property "connect_error" on null in C:\xampp\htdocs\*********.php on line 26
Hat alles nichts geholfen. Wisst ihr wo der Fehler liegt?
3 Antworten
Hallo,
ich bin mir nicht ganz sicher, wo der Fehler genau liegt aber ich würde an Deiner Stelle mal folgendes versuchen:
1. In der getName-Funktion sollte bei der Definition der $sql-Variable um die $id-Variable herum keine `-Zeichen verwenden werden. Ich gehe davon aus, dass es sich bei der Id um einen numerischen Wert handelt, weshalb Du auf die `-Zeichen verzichten kannst. Du solltest in der Funktion allerdings vorab sicherstellen, dass der $id-Parameter als numerischer Wert übergeben wurde.
2. Die Meldung, die bei der $conn->connect_error-Abfrage ausgegeben wird, deutet daraufhin, dass die Verbindung zur Datenbank nicht erfolgreich hergestellt wurde. Ich würde hierzu, wie Du bereits geschrieben hast, einfach versuchen, die ganze Sache in der Funktion mit $conn = new mysqli($servername, $username, $password, $dbname); zu definieren.
3. Abschließend noch ein allgemeiner Hinweis. Um Probleme mit SQL-Injection zu vermeiden, würde ich Dir empfehlen Prepared-Statements zu verwenden. Der Code dazu ist zwar etwas aufwändiger, wird aber dadurch auch deutlich sicherer. Ich habe hierzu auch mal Chat-GPT befragt und habe diesbezüglich das folgende Code-Beispiel erhalten:
function getName($id) {
global $conn;
$sql = "SELECT Vorname, Nachname FROM mitglieder WHERE ID = ?";
$stmt = $conn->prepare($sql);
if ($stmt === false) {
die("Prepare failed: " . $conn->error);
}
$stmt->bind_param("i", $id); // 'i' for integer, use 's' for string
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
$row = $result->fetch_assoc();
return $row['Vorname'] . " " . $row['Nachname'];
} else {
return "";
}
}
Vielleicht kannst Du diese Funktion ja einfach mal ausprobieren. Es würde mich interessieren, ob die ganze Sache so funktioniert.
Perfekt. Freut mich, dass die Lösung funktioniert. Warum der neue Code funktioniert aber der alte nicht, weiß ich leider auch nicht genau.
Zu Deiner Frage zu dem Unterschied zwischen real_escape_string und Prepared-Statements:
real_escape_string
- Die Funktion wird verwendet, um spezielle Zeichen in einem String, die in SQL-Befehlen eine besondere Bedeutung haben könnten, zu "escapen". Dadurch wird vermieden, dass diese Zeichen die Struktur der SQL-Anfrage verändern können. Zeichen wie Anführungszeichen, Backslashes und andere werden so modifiziert, dass sie sicher in einem SQL-Statement eingefügt werden können.
Prepared Statements
- Prepared Statements sind eine robustere Methode zur Verhinderung von SQL-Injection. Bei dieser Methode wird die SQL-Anfrage vom Datenbankserver vorab kompiliert und gespeichert. Die Daten (Parameter) werden dann von den eigentlichen SQL-Befehlen getrennt behandelt. Die Hauptvorteile von Prepared Statements sind erhöhte Sicherheit und manchmal verbesserte Performance bei wiederholten Ausführungen desselben Statements. Da die SQL-Struktur bereits festgelegt ist, können Parameter die Logik der Anfrage nicht verändern, selbst wenn sie schädlichen Code enthalten.
Ich habe meine Seiten vor einer ganzen Weile schon zu Prepared-Statements umgestellt und habe bisher nur gute Erfahrungen damit gemacht. Ich würde Dir auf jeden Fall empfehlen, Dich mal in das Thema einzuarbeiten. Notfalls kann Dir Chat-GPT da sicher bei helfen und Dir gute Code-Beispiele zu geben. Ich wünsche Dir auf jeden Fall weiterhin viel Erfolg.
Womöglich wird "false" zurückgegeben, da ein Fehler vorliegt?
Aber erstens: Warum? Klappt doch an anderer Stelle im Programm auch.
Und zweitens: Warum kommt dann diese komische Fehlermeldung bei der "connect_error" Abfrage?
Was für ein Fehler vorliegt müsstest du mittels passender Funktion testen.
Der Fehler bei "connect_error" ist wohl, dass das Attribut nicht existiert. Warum, das musst du selbst prüfen. Womöglich ist "$conn" noch nicht erstellt oder in einem anderem Scope. Oder aber es ist invalide.
Referenz siehe hier:
https://www.php.net/manual/en/book.mysqli.php
Da wird auch beschrieben, welche weiteren Fehler-Funktionen es gibt.
Der Code von HANSPAUL... funktioniert, weil die prepare- und execute-Anweisungen vorhanden sind und mysqli richtig benutzt wird. Welcher Grund liegt für $global conn; vor?
ES FUNKTIONIERT!!! Mir ist zwar noch immer schleierhaft warum (an den Backticks sollte es nicht liegen, weil ich hatte es auch die ganze Zeit ohne sie probiert) aber es funktioniert.
Aber eine Frage noch: Ich hatte bisher zum verhindern von SQL-Injection immer real_escape_string verwendet. Was ist der Unterschied zu den Prepared-Statements?