dedlfix: Umstellung auf UTF-8

Beitrag lesen

Tach!

Unter PMA wird derzeit alles korrekt dargestellt. Ich gehe also davon aus, dass die Daten in meiner MySQL zusammen mit dem richtigen Zeichensatz gespeichert worden sind. Woher aber kannte MySQL den korrekten Zeichensatz?

Zufall. Was auch immer die Default-Einstellung der Verbindungskodierung war, das Programm, das die Daten an MySQL übertragen hat, hat sie verwendet.

Bzw. was ist ausschlaggebend gewesen? Es gibt scheinbar den "Zeichensatz der Verbindung" zwischen MySQL und den Zeichensatz von MySQL-Tabellen bzw. sogar einzelner Felder?

Die Kodierungsangabe der einzelnen Felder ist ausschlaggebend. Jedes Feld kann seine eigene unterschiedliche Kodierung haben. Die Tabellen- und auch die Datenbank-Kodierung sind nur Default-Einstellungen, die beim Anlagen untergeordneter Elemente verwendet wird, wenn du keine explizite Angabe machst.

Und wie schon gesagt, zwischen der Verbindungskodierung und der Feldkodierung wird gegebenenfalls umkodiert. (Nebenbei, man kann sogar einzelnen Stringliteralen eine eigene Kodierungsangabe mitgeben, so dass auch innerhalb des SQL-Statements unterschiedliche Kodierungen stehen können.)

Ich verstehe das so:

MySQL(-Tabellen bzw. Felder) enthalten eine Kodierungsangabe (was wohl das ist, was man beim Anlegen der Tabellenstruktur festlegt). Hole ich mir die Daten in einem PHP-Skript per SQL-Statement dort ab, speichere sie dann in einer php-Variable, steht in dieser Variablen mein Content auf diese Weise kodiert.

Was für die Felder eingestellt ist, legt lediglich fest, was alles darin abgelegt werden kann. Für die Kommunikation mit den Clients ist ausschließlich die Verbindungskodierung relevant. (Ich sage vereinfacht "Verbindungskodierung", in Wirklichkeit sind es drei verschiedene Werte, zwei für den Weg zu MySQL und einer für das Resultset.) In deinen PHP-Variablen stehen nach dem Fetchen die Werte in der Verbindungskodierung (und nicht in der Feldkodierung, wenn diese eine andere war).

Will ich a) diese Daten dann im Browser ausgeben, muss für die Ausgabe die selbe Kodierung eingestellt sein.

Ja, oder du musst umkodieren. Üblicherweise will man das nicht, weil dadurch Zeichen verloren gehen können oder durch eine längere Ersatzschreibweise ausgetauscht werden müssen (NCR, Entitys).

Sprich: Daten aus einer MySQL-Tabelle mit der Zeichenkodierung Latin1 werden in meiner PHP-Variablen gespeichert. Wird der Inhalt dieser Variablen beim Aufruf meiner index.php im Browser ausgegeben und steht im Header, bzw. Metatag die selbe Zeichenkodierungsangebe, in dem Fall also ISO-8859-1 wird der Inhalt der Variablen korrekt angezeigt und zwar unabhängig davon, mit welcher Zeichenkodierung index.php gespeichert wurde.

Ja. Die Kodierung der PHP-Dateien (nebst Template-Dateien und dergleichen) hat nur Einfluss auf die Stringliterale, die in ihnen stehen.

Was verbirgt sich aber wohl hinter der Kodierung der Verbindung?
Ist damit die Umkodierung gemeint? Sprich, nur wenn php die Daten aus der Latin1-Tabelle als UTF-8 kodiert zur Verfügung gestellt bekommen soll, muss php der DB mit mysql_set_charset() mitteilen, dass sie die Daten als UTF-8 liefern (also umwandeln) soll.

MySQL sollte immer über die tatsächlich auf der Verbindung verwendete Kodierung informiert werden, weil es sonst die ankommenden Bytes selbst falsch interpretiert und im weiteren Verlauf Stringfunktionen (vor allem Vergleichen und Sortieren) nicht richtig arbeiten können. Zudem bekommen dann Programme, die selbst eine korrekte Verbindungskodierung aushandeln, nicht richtig interpretierbare Daten geliefert. Wenn diese Programme dann selbst Daten schreiben, kommt es zu einen Mischmasch. Der PMA ist eines der korrekt arbeitenden Programme, so dass mit diesem die korrekte Speicherung der Daten kontrolliert werden kann.

Interessant wäre dann auch, wie die Anweisung in umgekehrter Richtung (also Daten in der MySQL-DB speichern) funktioniert.

Etwas komplexer, weil dafür zwei Werte zuständig sind. Bei Interesse bitte selbst nachlesen: (MySQL-Handbuch Connection Character Sets and Collations)

Ich meinte, dass a) 'ä','ü' und 'ö' im HTML-Quelltext bei einheitlich richtiger Zeichenkodierung weder in UTF-8 noch ISO-8859-1 maskiert werden müssen, damit sie richtig dargestellt werden die Zeichen '"' und '<' hingegen unabhängig von der Zeichenkodierung im HTML-Quelltext immer zu Problemen führen.

Stimmt.

Und dass während htmlentities(), was 'ä','ü' und 'ö' genauso wie '"' und '<' maskieren würde zwar mit den ISO-kodierten Daten umgehen kann, mit UTF-8-kodierten Daten aber nicht, für htmlspecialchars() die unterschiedliche Kodierung keine Rolle spielt. Ist also multibyte-sicher?

Stimmt nicht mehr. Sowohl htmlentities() als auch htmlspecialchars() verfügen über einen Parameter ($encoding) zur Angabe der Zeichenkodierung. Damit können beide ihre Aufgabe ordnungsgemäß erledigen. Es hat nur den Anschein, dass htmlspecialchars() auch ohne den Parameter multibytefest ist, wenn du lediglich die auf ASCII aufbauenden Kodierungen betrachtest. Es gibt mindestens eine asiatische Kodierung, die die "ASCII-Bytes" (00-7f) mehrfach verwendet.

Dasselbe gilt für mysql(i)_real_escape_string(), das nicht bei allen Kodierungen richtig arbeiten kann, wenn nicht vorher mysql(i)_set_charset() verwendet wurde. SET NAMES geht direkt in das DBMS und hat keine Auswirkungen auf die Funktionen der MySQL-Client-API. mysql(i)_set_charset() informiert sowohl den Server als auch die MySQL-Client-API-Funktionen. Das ist der Grund, warum SET NAMES nur die zweite Wahl ist, aber keine negativen Auswirkung auf das Arbeiten mit ISO-8859-x und UTF-8 hat.

dedlfix.