PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [PHP] Problem mit UTF-8-kodierten Zeichen in PHP 5.3


ezzemm
2011-12-29, 17:56:37
Hallo zusammen!

Für mein Webtool (http://www.forum-3dcenter.org/vbulletin/showthread.php?t=514827) speichere ich alle Texte UTF-8-kodiert in der SQL-Tabelle, um einfach verschiedene Sprachen zu unterstützen.

Nun habe ich ein verrücktes Problem: In meiner einen Testumgebung mit PHP 5.2.9 funktionieren alle Sprachen fehlerfrei. In der anderen Testumgebung mit PHP 5.3.8 machen Koreanisch und Französisch Probleme: Während manche Sonderzeichen korrekt angezeigt werden, werden andere Zeichen falsch dargestellt. Und ich habe keine Ahnung, womit dieses Verhalten zusammenhängen könnte. Kann mir jemand helfen?

http://gfx.ezstats.org/utf-8-problem.jpg

Berni
2011-12-29, 18:12:12
Hast du dir mal den Seitenquelltext angesehen? Wird da vom HTTP-Header vielleicht ein falsches Seitenencoding ausgegeben und/oder der Browser nimmt ein falsches an?
Datenbank ist dieselbe und das Encoding bei der Verwendung zur Mysql auch? Sind die PHP-Quelldateien identisch in UTF-8 codiert.

sei laut
2011-12-29, 19:10:09
Manchmal hilft, das Encoding im Webserver zu setzen (wahrscheinlich Apache oder?).

ezzemm
2011-12-30, 11:55:15
Meine Ausgabe im PHP-Code ist wie folgt:
header('Content-Type:text/html; charset=UTF-8');
echo $html;

Der Browser nimmt auch den korrekten Charset an. Was ich wirklich nicht verstehe ist, wieso ein Teil der koreanischen Zeichen richtig angezeigt werde, und andere nicht.

Und wieso in dem einen Testsystem mit PHP 5.2 alles funktioniert, und PHP 5.3 nicht. :confused:

Coda
2011-12-30, 12:44:16
Gib uns mal die beiden HTML-Ausgaben als Text und die ausgelieferten Header dazu (siehst du in Firebug o.ä.).

Ansonsten kann man nur Mutmaßen.

ravage
2011-12-30, 12:52:05
Was für ein default_charset steht in der php.ini? Und kommen die Werte aus einer mysql Datenbank?


# für PHP.ini:
ini_set('default_charset', "UTF-8");

# für MySQL:
mysql_query("SET NAMES 'utf8'");
mysql_query("SET CHARACTER SET 'utf8'");

ezzemm
2011-12-30, 13:47:01
Ich habe es mal auf meinem Server installiert; da seht ihr auch daß manche koreanische Zeichen angezeigt werden, und manche nicht. Ausserdem wird dort php_info eingeblendet:
http://test.ezstats.org/admin/

Der "default_charset" ist nicht gesetzt; das ist er aber in meiner funktionierenden Testumgebung auch nicht.
Die ganzen koreanischen Zeichen stehen in der selben SQL-Tabelle; und manche gehen, manche nicht. In den französischen Sprachdateien habe ich das Problem mit bestimmten Buchstaben auch.

Könnte es mit der Bitlänge zusammenhängen, daß manche Zeichen gehen und manche nicht? Und daß mein altes Testsystem wo alles geht, diesbezüglich anders eingestellt ist?

Coda
2011-12-30, 15:05:53
Nochmal: Wir brauchen *beide* Ausgaben nicht nur eine und die Header,. Das kann doch nicht so schwer sein.

Berni
2011-12-30, 15:28:26
Also ich tippe stark auf die MySQL-Verbindung. Es haben sich da in der neuen Version die Defaultwerte für die Charsets teils geändert. Zudem war es auch in den früheren Versionen oft falsch eingestellt weshalb in der Datenbank schon Müll steht (nur es kommt eben zufällig wieder dasselbe richtige raus wenn man den Müll mit der gleichen falschen Einstellung wieder abholt). In den Fällen kann ein Export der Daten mit der alten Version und anschließender Neuimport helfen.

Es sollte darauf geachtet werden, dass alle MySQL-Tabellen und auch die einzelnen Attribute auf utf8_general_ci laufen. Zudem sollten auch die globalen MySQL-Variablen bzgl. Character set und collation komplett überprüft und ggf. geändert werden. Bei mir siehts bsp. so aus und damit gibts gar keine Probleme:
character set client utf8
character set connection utf8
character set database utf8
character set filesystem binary
character set results utf8
character set server utf8
character set system utf8
character sets dir /usr/share/mysql/charsets/
collation connection utf8_unicode_ci
collation database utf8_unicode_ci
collation server utf8_unicode_ci
Wobei die character set client, character set results und character set connection an der aktuellen Verbindung hängen und über "SET NAMES UTF8;" geändert werden kann (bzw. über mysql_set_charset/mysqli_set_charset). Siehe dazu auch http://dev.mysql.com/doc/refman/5.1/de/charset-connection.html

ezzemm
2011-12-31, 14:27:57
Hallo!

Berni, du hast mir sehr geholfen!

Mit deinen Hinweisen im Hinterkopf bin ich nochmals alle Arbeitsschritte durchgegangen. Die Übersetzung findet in einem von mir programmierten Online-Tool statt, und um die verschiedenen Lokalisierungen zusammenzuführen, exportiere ich die SQL-Tabelle vom Webserver, und importiere sie in meinem lokalen Server.

Beim Exportieren habe ich bisher immer ohne Komprimierung ausgewählt, und dann per Copy&Paste in das SQL-Eingabefeld meiner lokalen MySQLAdmin-Installation überführt. Dabei ist der Fehler entstanden.

Nun habe ich es ausprobiert, in eine Zip-Datei zu exportieren und wieder zu importieren. Nun sind alle Zeichen fehlerfrei übernommen worden.

Dies ist wirklich ein sehr verrückter Fehler!

mittelding
2011-12-31, 15:46:52
Nachdem das Anliegen geklärt wurde noch eine Unklarheit meinerseits: Für mich war eine Datenbank bisher immer nur ein Speicher für "Datenströme", welche so aus der DB heraus kommen wie man sie hinein gesteckt hat... Für was genau braucht man nun diese Collation, ich dachte immer diese nützt nur um die Sortierreihenfolge festzulegen?
Ich hätte jetzt vermutet, dass das mit utf8 selbst dann noch funktioniert, wenn man eine rein asiatische Collation wählt, den Bytestrom interpretiert man evt. außerhalb der DB als utf8.

Berni
2011-12-31, 21:15:24
Das mit dem Zusammenhang Collation und Sortierreihenfolge ist schon richtig, die Collation selbst sollte eigtl. niemals Probleme in Hinsicht von Sonderzeichen verursachen. Allerdings gehört eine korrekt eingestellte Collation eben auch dazu damit die Datenbank wirklich korrekt arbeitet. Die Collation spielt nämlich z.B. auch bei Stringvergleichen eine Rolle (manche sehen z.B. OE = Ö, es gibt auch welche die Groß-/Kleinschreibung missachten welche man an dem "_ci" hinten erkennt).

Eine Anmerkung noch bzgl. Charsets (also nicht Collationbezogen): Als reinen binären Datenspeicher ansehen sollte man die Datenbank niemals: Wenn du Unicodezeichen binär in der Datenbank in einem ASCII-Feld (also z.B. latin1_general_ci) abspeicherst, dann belegt ein Zeichen 1-4 Byte bzw. "Zeichen". Wenn dann also tatsächlich mehr als 1 Byte benötigt wird, dann kann es durchaus bei Abfragen unterschiedliche Ergebnisse geben (LIKE-Abfragen, Substring, etc.). Es sogar dazu kommen, dass Zeichen nur "halb" abgespeichert werden wenn das Varchar-Feld zu klein ist. Mal ganz abgesehen davon, dass die richtige Einstellung überlebenswichtig ist eben weil auch Konvertierungen auftreten können, z.B. im SQL-Treiber.