Sebastian Schrader: Ausgabeprobleme bei UTF-8 in Verbindung mit MySQL

Hallo Leute,

ich habe folgendes Problem im Zusammenhang mit UTF-8:
Ich lese mit meinem PHP-Skript Strings aus meiner MySQL-Datenbank aus (Die Datenbank ist überall auf UTF-8 eingestellt, d. h. von globalen Variablen wie "character set client" bis in zu den Einstellungen für jede Spalte). Mein Editor (Zend Studio Client) speichert die Skripte, Templates, etc auch alle als UTF-8. Apache gibt UTF-8 aus, php ebenso, im Header wird UTF-8 angegeben und als meta-Tag zusätzlich auch noch einmal.
Dennoch werden die Sonderzeichen wie Umlaute aus der Datenbank nicht als UTF-8 dargestellt, stattdessen sieht man Fragezeichen, statische Strings mit Umlauten (die zum Beispiel in einem Template stehen oder per echo/print ausgegeben werden) aber schon. Zum Test habe ich die Strings aus der Datenbank die Umlaute enthalten per mb_detect_encoding() auf ihre Zeichsatz getestet: das Ergebnis war UTF-8. Danach habe ich die Strings zum Teste per mb_convert_encoding() obwohl sie eigentlich schon UTF-8 sein müssten nochmal zu UTF-8 konvertieren lassen und dann geht alles. Um zu Testen obs an MySQL liegt habe ich mit dem MySQL Query Browser und phpMyAdmin mir die Datenbank angeschaut und hier werden die Umlaute korrekt ausgegeben.

Weiß vielleicht jemand den Grund für dieses Verhalten?

PS: Über Alternativlösungen wie zum Beispiel alle Strings vorher zu konvertieren bin ich mir klaren, ich stelle diese Frage um dem Problem auf den Grund zu gehen, sonst hätte ich anstatt UTF-8 auch bei HTML-Entities bleiben können und mir die Umkonfiguration auf UTF-8 sparen können.

mfG
Sebsatian Schrader

  1. Moin!

    Zum Test habe ich die Strings aus der Datenbank die Umlaute enthalten per mb_detect_encoding() auf ihre Zeichsatz getestet: das Ergebnis war UTF-8.

    Es gibt keine Funktion, die dir 100% korrekt und zweifelsfrei sagen kann, welche Codierung ein beliebiger String hat.

    Der String "Hallo Welt" ist beispielsweise gültiges UTF-8 - und ebenso gültiges ISO-8859-1, ISO-8859-15, Windows-1252, und vermutlich ebenso in allen anderen Codierungen, die kompatibel zu US-ASCII sind. Die PHP-Funktion gibt diese Codierungen ja aber keinesfalls alle aus.

    Die Funktion kann aber nicht prüfen, ob ein Zeichen, welches sich im String befindet, in diesem Kontext bei einer Zeichencodierung sinnvoll ist. Das, was man sieht, wenn man UTF-8 nimmt, aber als ISO-8859-1 ausgibt, enthält beispielsweise sehr häufig das Zeichen Ã, gefolgt z.B. von ¼ o.ä. Ein "A-tilde" ist sicher kein böses Zeichen, ein "ein Viertel" ebenfalls nicht - nur in Kombination ergeben Sie für Menschen normalerweise keinen Sinn - das weiß die Funktion ja aber nicht.

    Deshalb muß irgendwo in deiner Verarbeitungskette eine Lücke sein, welche die Konvertierung noch nicht korrekt durchreicht. Die mußt du finden und eliminieren.

    Btw: Welche DB-Version? Welche Kollation (wenn MySQL > 4.1) hast du gewählt?

    - Sven Rautenberg

    --
    My sssignature, my preciousssss!
  2. Hallo Sebastian,

    (Die Datenbank ist überall auf UTF-8 eingestellt, d. h. von globalen Variablen wie "character set client" bis in zu den Einstellungen für jede Spalte).

    Das ist Overkill. Es reicht, wenn für die Datenbank eine Kodierung/ collation eingestellt ist.

    Mein Editor (Zend Studio Client) speichert die Skripte, Templates, etc auch alle als UTF-8.

    Das ist gut, sollte aber nicht zwingend erforderlich sein. Ich mache das auch so, habe aber schon überlegt, ob es nicht richtiger wäre, die PHP-Skripte in ISO-8859-1 zu speichern. Ja, ich weiß, ich hab Probleme...

    Apache gibt UTF-8 aus, php ebenso, im Header wird UTF-8 angegeben und als meta-Tag zusätzlich auch noch einmal.

    Hast Du das mal überprüft, z.B. mit der web developer extension für den Firefox? Information -> View Response Headers.

    Dennoch werden die Sonderzeichen wie Umlaute aus der Datenbank nicht als UTF-8 dargestellt, stattdessen sieht man Fragezeichen, statische Strings mit Umlauten (die zum Beispiel in einem Template stehen oder per echo/print ausgegeben werden) aber schon.

    Was passiert denn, wenn Du Deine Website vom Browser in anderen Kodierungen anzeigen lässt? Wann ist es richtig? (Z.B. im Firefox: Ansicht -> Zeichencodierung).

    Danach habe ich die Strings zum Teste per mb_convert_encoding() obwohl sie eigentlich schon UTF-8 sein müssten nochmal zu UTF-8 konvertieren lassen und dann geht alles.

    Von welcher Kodierung hast Du sie zu UTF-8 konvertieren lassen? Konkret: Mit was als dritten Parameter hast Du mb_convert_encoding() aufgerufen, bzw. setzt Du vorher eine interne Kodierung mit mb_convert_encoding()?

    Weiß vielleicht jemand den Grund für dieses Verhalten?

    Ich vermute, dass es an der Datenbankverbindung liegt. Welche SQL-Befehle führst Du aus, bevor du Datansätze abrufst?
    Du solltest die Verbindungskodierung mit
    SET NAMES='utf8';

    oder alternativ mit

    SET character_set_client='utf8';  
    SET character_set_connection='utf8';  
    SET character_set_results='utf8';
    

    explizit festlegen.