PHP Programmfehler - warum?
- mysqli
- php
MySQL-Vers.=[MySQL 8.0] PHP-Vers.=[8.4.27] (seit wenigen Monaten, vorher jahrelang PHP 5)
Moin,
in der php-error.log gibt es viele Meldungen, die ich abstellen möchte.
Fehlertyp 1:
[24-Oct-2026 13:19:28 Europe/Berlin] PHP Deprecated: htmlentities(): Passing null to parameter #1 ($string) of type string is deprecated in /homepages/u79644/200/p203.php on line 427
Vorher hatte ich htmlspecialchars (veraltet), in https://www.php.net/manual/en/function.htmlspecialchars.php wird auf htmlenteties verwiesen, wird aber auch als veraltet bezeichnet.
Die Meldung kommt bei leeren Feldern. Es muss doch möglich sein, leere Werte ohne vorheriges if wandeln zu lassen, dann kommt was Leeres raus ohne Warnung.
Wie macht ihr das?
Fehlertyp 2:
Webseite meldet (aber gibt bewusst verursachten Fehler nicht aus):
In der php-error.log lese ich:
[24-Oct-2026 14:36:19 Europe/Berlin] PHP Fatal error: Uncaught mysqli_sql_exception: Undeclared variable: A in /homepages/u79644/200/p203.php:295
Stack trace:
#0 /homepages/u79644/200/p203.php(295): mysqli->query('\n# ~~~~~~~~~~~~...')
#1 /homepages/u79644/index.php(70): include('/homepages/u796...')
#2 {main}
thrown in /homepages/u79644/200/p203.php on line 295
Und der PHP-Code zur Fehlerausgabe (LIMIT A) funktioniert nicht:
Gruß, Linuchs
Bitte keinen Code als Bildschirmfoto. Wer antwortet muss das abtippen und das kann sehr schwierig sein, weil man dann scrollen muss oder sogar einen zweiten Browser-Tab braucht. Du bekommst also mehr und ggf. richtige Anworten, wenn Du es dem Anwortendem leichter machst.
Fehlertyp 1:
[24-Oct-2026 13:19:28 Europe/Berlin] PHP Deprecated: htmlentities(): Passing null to parameter #1 ($string) of type string is deprecated in /homepages/u79644/200/p203.php on line 427
Wie macht ihr das?
Mit der geforderten Typumwandlung:
… htmlentities( (string)$row['bewertung'],ENT_QUOTES ) …
Fehlertyp 2:
Und der PHP-Code zur Fehlerausgabe (LIMIT A) funktioniert nicht:
(1)
Nein, Dein Code heisst nicht … LIMIT A … sondern … LIMIT A,1 … - und wir sehen nichts, wo du A mit einem Integer-Wert belegt hast.
(2) Du startest eine Abfrage, willst wissen, ob die durchging - fragst dann aber nach dem Verbindungsfehler:
mysqli-> connect_errno
Was Du willst, sieht so aus:
if ( !$mysqli->query( $query ) ) {
printf( "Fehlermeldung: %s\n", $mysqli->error );
}
oder eben
if ( false === $res_we2 ) {
printf( "Fehlermeldung: %s\n", $mysqli->error );
}
Hallo Raketenwilli,
Die Typumwandlung könnte scheitern, wenn wirklich NULL im Datenfeld steht. Da er modernes PHP einsetzt, würde ich den null coalescing Operator ?? empfehlen:
htmlentities($row['bewertung'] ?? '', ENT_QUOTES)
Steht hier, weiter unten: PHP Vergleichsoperatoren
Rolf
Die Typumwandlung könnte scheitern, wenn wirklich NULL im Datenfeld steht. Da er modernes PHP einsetzt,
Hm. Ich wohl auch. Ich hatte das wie folgt getestet:
<?php
error_reporting( E_ALL );
print phpversion() . "\n";
$row['bewertung'] = null;
print "„" . htmlentities( (string)$row['bewertung'], ENT_QUOTES ) .'“' . PHP_EOL;
print "Meldung erwartet: „" . htmlentities( $row['bewertung'], ENT_QUOTES ) .'“' . PHP_EOL;
Ausgaben:
$ php /tmp/test.php
8.4.27
„“
PHP Deprecated: htmlentities(): Passing null to parameter #1 ($string) of type string is deprecated in /tmp/test.php on line 7
Meldung erwartet: „“
auf der anderen Maschine:
$ php /tmp/test.php
8.5.12
„“
PHP Deprecated: htmlentities(): Passing null to parameter #1 ($string) of type string is deprecated in /tmp/test.php on line 7
Meldung erwartet: „“
Die erzwungene Typumwandlung funktioniert also. An der von Dir erwähnten Stelle steht:
The expression (expr1) ?? (expr2) evaluates to expr2 if expr1 is null, and expr1 otherwise.
„In particular, this operator does not emit a notice or warning if the left-hand side value does not exist, just like isset(). This is especially useful on array keys.“
Das würde also dann eine Fehlermeldung unterdrücken, wenn $row['bewertung'] nicht besetzt (false === isset( $row['bewertung'] ) ) wäre - was vorliegend nicht der Fall und gerade nicht gefordert ist: Deine Lösung tut also zu viel.
Hallo Raketenwilli,
Bitte keinen Code als Bildschirmfoto.
Okay, aber nur so bekomme ich die Zeilen-Nr. aufs Bild (Editor Geany)
if ( !$mysqli->query( $query ) ) {
printf( "Fehlermeldung: %s\n", $mysqli->error );
}
Der Firefox gibt die Fehlermeldung nicht aus, auch nicht mit echo. Offenbar bekommt er nur den Status 500 gemeldet und keinerlei HTML. [Strg][U] ist leer, ich lese:
Anscheinend gibt es ein Problem mit dieser Website
Der Server auf remso.eu sendete einen Fehler: 500 Internal Server Error
Was können Sie dagegen tun?
Vergewissern Sie sich, dass Sie die Adresse der Website richtig eingegeben haben.
Die Website könnte vorübergehend nicht erreichbar sein, versuchen Sie es bitte später nochmals.
Wie kann ich eine Fehlermeldung ausgeben, ist da was an der php.ini zu schrauben?
Gruß, Linuchs
Das wird wohl eine andere Ursachen haben, denn Du gibts ja etwas zum Webserver aus. Ich vermute den Fehler also „viel früher“.
Probiere mal temporär an der Stelle:
$res_we2 = mysqli->query( $q ); # Das ist Dein Code
if ( false === $res_we2 ) { # Teste also Dein Resultset
printf( "Fehlermeldung: <pre>%s</pre>\n", $mysqli->error );
exit;
} else { # Nach Test löschen
print ("Hat geklappt: <pre>$query</pre>\n"); # Nach Test löschen
}
$res_we2 = mysqli->query( $q ); # Das ist Dein Code
if ( false === $res_we2 ) { # Teste also Dein Resultset
# Übernehme die Fehlermeldung in Variable $errmsg
$errmsg=sprintf( "MySQL-Error: " . $mysqli->error );
# Erzeuge einen „User Error“
trigger_error( $errmsg, E_USER_ERROR )
exit;
}
Um den Fehler nicht nur im Logfile sondern auch in der Webseite anzuzeigen tätige einen dieser Schritte:
https://forum.selfhtml.org/self/2026/oct/24/php-programmfehler-warum/1826046#m1826046
WARNUNG: Denke aber daran, dass das auf einer öffentlichen Webseite ggf. einem Angreifer sehr hilft.
Wie kann ich eine Fehlermeldung ausgeben, ist da was an der php.ini zu schrauben?
Ja. Am Anfang des Skriptes:
<?php
ini_set( "display_errors", 1 );
error_reporting( E_ALL );
Du kannt auch alternativ eine lokale php.ini ins Verzeichnis setzen. Beachte, dass Einstellungen in der php.ini im Skript überschrieben werden können. Einige Dich mit Dir selbst, wo Du das machst.
display_errors = On
html_errors = On
error_reporting = E_ALL
Denke daran, dass diese für jeden (den Webserver) lesbar sein muss. Und dass Du das wieder abschalten musst.
Moin Linuchs,
Fehlertyp 1:
[24-Oct-2026 13:19:28 Europe/Berlin] PHP Deprecated: htmlentities(): Passing null to parameter #1 ($string) of type string is deprecated in /homepages/u79644/200/p203.php on line 427Vorher hatte ich htmlspecialchars (veraltet), in https://www.php.net/manual/en/function.htmlspecialchars.php wird auf htmlenteties verwiesen, wird aber auch als veraltet bezeichnet.
Beide Funktionen sind nicht veraltet, nur das Übergeben von null anstelle eines Strings ist veraltet.
Die Meldung kommt bei leeren Feldern. Es muss doch möglich sein, leere Werte ohne vorheriges
ifwandeln zu lassen, dann kommt was Leeres raus ohne Warnung.Wie macht ihr das?
Das hat @Rolf B schon skizziert.
Fehlertyp 2:
[24-Oct-2026 14:36:19 Europe/Berlin] PHP Fatal error: Uncaught mysqli_sql_exception: Undeclared variable: A in /homepages/u79644/200/p203.php:295 Stack trace: #0 /homepages/u79644/200/p203.php(295): mysqli->query('\n# ~~~~~~~~~~~~...') #1 /homepages/u79644/index.php(70): include('/homepages/u796...') #2 {main} thrown in /homepages/u79644/200/p203.php on line 295
Die SQL-Syntax von MySQL/MariaDB kennt LIMIT nur mit numerischen Werten, A ist keiner.
Und der PHP-Code zur Fehlerausgabe (LIMIT A) funktioniert nicht:
Das liegt auf der Hand, denn connect_errno gibt den letzten Verbindungsfehler zurück, aber nicht den Fehler des letzten mysqli-Aufrufs. Unabhängig davon ist der bessere Weg direkt den Rückgabewert von query zu prüfen:
$res_we2 = $mysqli->query($q);
if (! $res_we2) {
echo 'DB-Fehler: ', $mysqli->error, "\n";
}
Viele Grüße
Robert
Hallo Robert,
Die SQL-Syntax von MySQL/MariaDB kennt LIMIT nur mit numerischen Werten, A ist keiner.
Ja, habe ich testweise eingegeben, um einen Fehler zu provozieren.
$res_we2 = $mysqli->query($q);
if (! $res_we2) {
echo 'DB-Fehler: ', $mysqli->error, "\n";
}
Wenn $mysqli einen Fehler erzeugt, wird kein weiteres Kommando ausgeführt, der if bringt also keine Klarheit.
Gruß, Linuchs
Moin Linuchs,
$res_we2 = $mysqli->query($q); if (! $res_we2) { echo 'DB-Fehler: ', $mysqli->error, "\n"; }Wenn $mysqli einen Fehler erzeugt, wird kein weiteres Kommando ausgeführt, der if bringt also keine Klarheit.
Aber $mysqli->error bringt hoffentlich Klarheit – oder dann wenigstens die von Rolf genannten Punkte.
Viele Grüße
Robert
Hallo Linuchs,
PHP-Vers.=[8.4.27] (seit wenigen Monaten, vorher jahrelang PHP 5)
Wenn $mysqli einen Fehler erzeugt, wird kein weiteres Kommando ausgeführt
Diese Info-Kombi brachte Klarheit. Sogar ohne KI 😉. Und Dir hätte was dämmern können, wenn Du anständiges Error-Logging durchführen würdest und in die Log-Datei geschaut hättest. Da müsste eine ungefangene SQL-Exception drinstehen.
Guck mal bei report_mode des mysqli Drivers. Da hat sich mit PHP 8.1 ein Default geändert. Es gibt durchaus Gründe, warum man sich die PHP Release Notes anschauen muss - da verbergen sich regelmäßig Tretminen.
Kurz gesagt: der report_mode war vor PHP 8.1 MYSQLI_REPORT_OFF und ist seitdem MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT. Das bedeutet, dass bei SQL-Fehlern eine Exception fliegt und das Script abbricht, wenn kein try/catch um die Query liegt. Das erklärt dann auch den HTTP 500.
Die aufwändige Lösung ist, jede SQL-Query in try/catch einzupacken und die mysqli_sql_exception sauber zu behandeln.
Die einfache Lösung wäre
mysqli_report(MYSQLI_REPORT_OFF);
damit hast Du das Verhalten vor PHP 8.1 und bekommst von mysqli_query ein FALSE zurück.
Statt OFF könntest Du aber auch
mysqli_report(MYSQLI_REPORT_INDEX | MYSQLI_REPORT_ERROR);
setzen, also nicht STRICT. Je nach Einstellungen im Error-Reporting bekommst Du dann Hinweise auf SQL-Fehler oder unpassende oder fehlende Indexe im Output oder in Error-Log zu sehen.
Diese Änderung in PHP 8.1 ist mal wieder typisch PHP: Seit PHP 8.0 steht in PDO das Attribut PDO::ATTR_ERRMODE auf PDO::ERRMODE_EXCEPTION, vorher war es PDO::ERRMODE_SILENT. Ein professionell aufgestelltes Team hätte diese Änderung in mysqli zeitgleich ausgerollt. Aber nein, sie haben es offenbar vergessen und schieben es eine Unterversion später nach. Das ist die Sprache, mit der ein Großteil des nichtstatichen Internets läuft 😢.
Rolf