Hallo zusammen,
ich weiß, das ist ein ziemlich alter Forenbeitrag, aber mein Bugreport scheint genau hier zu passen.
Vor etwa sechs Jahren wurde in
operations.php offenbar folgender Code eingefügt:
Code: Alles auswählen
if (strlen($signtxt) > 120) {
$signtxt = substr($signtxt, 0, 117) . "...";
}
Dadurch wird der String auf 120 Zeichen gekürzt. Das Problem ist allerdings, dass
strlen() und
substr() auf
Bytes arbeiten.
Enthält ein Artikelname Sonderzeichen (bei uns war es z. B. „Radler-Süß“), kann es (scheinbar völlig zufällig und sehr sporadisch) passieren, dass
substr() genau mitten in einem UTF-8-Multibyte-Zeichen abschneidet. Beim Speichern des ungültigen UTF-8-String in der Datenbank führte das anschließend zu folgendem PHP-Fehler:
Code: Alles auswählen
[Sun Jun 28 17:41:02.349905 2026] [php:error] [pid 23899] [client 192.168.0.208:50322] PHP Fatal error: Uncaught PDOException: SQLSTATE[22007]: Invalid datetime format: 1366 Incorrect string value: '\\xC3...' for column `ordersprinter`.`os_operations`.`signtxt` at row 1 in /var/www/html/php/commonutils.php:510\nStack trace:\n#0 /var/www/html/php/commonutils.php(510): PDOStatement->execute()\n#1 /var/www/html/php/utilities/operations.php(51): CommonUtils::execSql()\n#2 /var/www/html/php/queuecontent.php(1977): Operations::createOperation()\n#3 /var/www/html/php/queuecontent.php(1908): QueueContent::signAtTSE()\n#4 /var/www/html/php/queuecontent.php(1533): QueueContent->addProductListToQueueCore()\n#5 /var/www/html/php/queuecontent.php(125): QueueContent->addProductListToQueue()\n#6 /var/www/html/php/contenthandler.php(75): QueueContent->handleCommand()\n#7 {main}\n thrown in /var/www/html/php/commonutils.php on line 510, referer: http://192.168.0.100/waiter.html
Erst wenn die komplette Bestellung verworfen und anschließend neu erfasst wurde, funktionierte alles wieder. Dabei wurde die Reihenfolge der Bestellung (zufällig) geändert, sodass der Schnittpunkt nicht mehr mitten in einem Multibyte-Zeichen lag.
Die Lösung besteht darin, UTF-8-fähige Funktionen zu verwenden, z. B.
mb_strlen() und
mb_substr(), damit immer an einer gültigen Zeichenposition abgeschnitten wird (wobei mit diesen Funktionen längere Strings als 120 Byte entstehen können).
Ich habe es jetzt so gelöst:
Code: Alles auswählen
if (strlen($signtxt) > 120) {
$signtxt = mb_strcut($signtxt, 0, 117, 'UTF-8') . "...";
}
Folgende Zeile ist ebenso anfällig für Multi-Byte-Zeichen, hat aber wohl keine Funktion mehr
Code: Alles auswählen
$signtxt_ascii = preg_replace('/[[:^print:]]/', '', $signtxt);
Gruß Frank