utf-8 Umstellung in einer Lamp Umgebung
Bei der Umstellung von PHP-Scripten oder ganzen PHP-Anwendungen inklusive Datenbank-Anbindung und deren Ausgaben, von Latin1(iso-8859-*) auf utf-8 (Abk. für 8-bit Unicode Transformation Format), gibt es vieles zu beachten.
Weil iso-8859-1 bzw -15(mit €) in den meisten Fällen ausreicht, sollte dieser Zeichensatz für deutsch bzw englischsprachigen Seiten auch Verwendung finden. Wenn aber kyrillisch oder gar chinesisch auf der Seite angezeigt werden muss, liegt ein Multibyte Zeichensatz wie utf-8 nahe, da er all diese Zeichen anzeigen kann. Das W3C empfiehlt übrigens generell die Benutzung von utf-8 auf HTML-Seiten. XHTML ist grundsätzlich utf-8, wenn man nichts anderes vorgibt.
Da man den utf-8 Zeichensatz bei allen möglichen Gelegenheiten(in PHP, in mySQL, in XHTML, in CSS und im Browser) um- und einstellen kann, ist bei der Umstellung also einiges an Aufmerksamkeit gefragt, denn eine vergessene Einstellung kann schon das Scheitern des Vorhabens bedeuten.
Viele der folgenden Einstellungen mögen doppelt vorkommen, meine Erfahrung bei der Umstellung ist jedoch, dass man hier sehr gewissenhaft vorgehen muss um Fehler und Folgefehler zu vermeiden.
Der wohl wichtigste Part beschäftigt sich mit der Konfiguration von mySQL, da gerade beim Daten speichern sehr viele Fehler auftauchen können.
Schritt 1 - Das Dokument an sich
Die Kodierung des verwendeten Editors(z.B. Dreamweaver) auf UTF-8 umstellen. Alle Dokumente sollten direkt als utf-8 erstellt werden. Hier ist zu bemerken, dass es eine sog. "BOM" gibt, eine Markierung für die Byte-Reihenfolge bei UTF-* Dokumenten, die es dem Client ermöglicht auszulesen ob das Dokument ein UTF-* Dokument ist. Diese Option im Editor also aktivieren. Die Funktion sollte bitte nur mit Vorsicht aktiviert werden, denn nicht jede Applikation kommt damit klar. Gutes Beispiel ist, dass durch die BOM anscheinend schon ein Header gesendet wird. Somit wird durch eine nachfolgende header()-Anweisung unter PHP ein "headers already sent" Warning ausgelöst. Ich bin momentan dabei dieses Problem zu lösen.
Schritt 2 - Das HTML
(X)HTML Header anpassen. Damit der Browser weiß dass er das Dokument in utf-8 anzeigen soll, muss er dies gesagt bekommen .
Schritt 3 - CSS
Das CSS wird mit dieser kleinen Anweisung zu utf-8. Wichtig: Wenn man in Stylesheets eine BOM verwendet, dann kann man nicht zugleich die @charset-Regel benutzen, denn die muss immer die allererste Zeichenkette im Dokument sein.
-
@charset "utf-8";
Schritt 4 - php.ini
Damit php die Scripte als utf-8 ausliefert, sollte man auch die php.ini entsprechend anpassen.
-
default_mimetype = "text/html"
-
default_charset = "utf-8"
Schritt 5 - Apache-Webserver
Damit der Webserver Dokumente als utf-8 ausliefert, muss er entsprechend konfiguriert werden. Entweder man tut dies direkt in der http.conf oder in einer htacces Datei. alternativ kann diese Direktive auch nur in speziellen vhosts vorgenommen werden.
-
AddCharset utf-8 .css .html .xhtml .php .php4 .php5
Schritt 6 - mySQL
Um Daten in einer mySQL Datenbank als utf-8 zu speichern ist grundsätzlich eine Version >4.1 erforderlich. In Versionen darunter ist eine Unicode-Unterstützung nicht implementiert. Will man Daten als utf-8 abspeichern muss die Datenbank und die Tabelle in dieser Kollation angelegt sein. "Jeder String in MySQL ist mit einem Encoding und einer Kollation markiert. Für Datenbankobjekte geschieht dies auf der Spaltenebene: Eine Spalte mit CHAR, VARCHAR oder einem TEXT-Typ ist immer auch mit einem CHARSET und einer COLLATION versehen.(JK)"
Dies macht man z.B. so:
-
CREATE TABLE `test` (
-
`id` TINYINT( 64 ) NOT NULL ,
-
`TEXT` VARCHAR( 128 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL
-
) TYPE = MYISAM CHARACTER SET utf8 COLLATE utf8_unicode_ci;
Mit CHARACTER SET utf8 COLLATE utf8_unicode_ci wird der Spalte der Typ Unicode zugewiesen. Gibt man nicht explizit an welche Kollation verwendet werden soll, wird die in der Datenbank angebende weiter nach unten vererbt. Standard Encoding und Kollation lassen sich in der my.cnf angeben:
-
[mysqld]
-
default-character-set=utf-8
-
default-collation=utf8_unicode_ci
Der Query
Auch wenn alles auf utf-8 umgestellt ist, wird man schnell feststellen, dass ein utf-8 String, der über ein HTML-Formular eingeben wird bei dem Weg zur Datenbank encodiert wird. Z.B. wird aus
فارسی in der Datenbank wieder العربية. Woran kann das liegen? Auf dem Weg von HTML über http zu PHP zu mySQL wird der ursprünglich als utf-8 kodierte String also wieder encodiert. Dies geschieht, sofern man alles andere richtig eingestellt hat, bei der Verbindung von PHP und mySQL. Man umgeht das Problem indem man die Verbindung in utf-8 aufbaut:
http://www.columbia.edu/kermit/utf8.html
http://www.bueltge.de/wk-utf-8-konvertierung/130/
http://blog.koehntopp.de/archives/1424-MySQL-Zeichensatz-Grundlagen.html
http://blog.antikoerperchen.de/beitrag/42/utf-8-und-die-entity.html