heinetz: ... und da war es wieder, das Problem mit den Zeichensätzen ;(

Hallo Forum,

ich habe auf meiner Windows-Entwicklungsumgebung eine XHTML-Website
mit einem Backend gebaut. Mit diesem Backend werden über Forms Inhalte
(Texte) die als sollches in einer MySQL-DB liegen editiert. Auf der
Website ist als Charcode UTF) definiert. Die Zeichensatzunterstützung
von MySQL raff ich nicht richtig und verwende sie auch nicht. Die
DB meiner Entwicklungsumgebung habe ih gstern dedumpt und mit phpMyAdmin
in die Live-DB eingespielt. Wenn ich jetzt dort unter phpMyAdmin einen
Text editiere und die geänderten Datensatz abspeichere ist alles gut
(ein dort eingegebenes 'ä' wird unter phpMyAdmin und auf der Website  richtig dargestellt). Wenn ich dazu das selbstgebaute CMS verwende,
ist die Darstellung des 'ä' unter phpMyAdmin und auf der Website
kaputt. Sprich:

Der Fehler scheint beim Update des Datensatzes aufzutreten.

Wahrscheinlich habe ich etwas Grundsätzliches vergessen (das maskieren
des Wertes aus $_POST ?).

Kann mir jemad einen Tipp geben ?

danke,
guesse,
heinetz

  1. Moin!

    Ich denke, dein elementarer Fehler liegt hier:

    Die Zeichensatzunterstützung von MySQL raff ich nicht richtig und verwende sie auch nicht.

    Aber vermutlich läuft bei deinem Live-System noch einiges mehr unabsichtlich schief, weil du dich bisher nicht um die korrekte Auszeichnung des Encodings bemüht hast.

    Grundsätzlich wichtig ist: Das ausgelieferte HTML muß korrekt als UTF-8 gekennzeichnet sein, sowohl im HTTP-Header als auch im HTML-Head per Meta-Tag.

    Das führt dann dazu, dass auch eingesetzte Formulare wieder UTF-8 zurück an den Server schicken. Dieser muß seinerseits natürlich UTF-8 auch korrekt behandeln können (die normalen Stringfunktionen von PHP können das beispielsweise nicht, bzw. man muß bedenken, dass man dort die für UTF-8 typischen, abweichenden Ergebnisse erhält). Das gilt insbesondere für die Datenverbindung zur Datenbank, die ebenfalls auf UTF-8 eingestellt werden muß. Und zu guter letzt benötigen natürlich auch die DB-Datenfelder die korrekte Auszeichnung mit UTF-8, wobei die Kollation auch noch dafür sorgt, wie das Sortierverhalten ist.

    Wenn du diese drei Punkte beachtest, solltest du keinerlei Probleme mit dem Encoding haben. Wenn du sie ignorierst, hast du nur durch Zufall keine Probleme (wie auf deinem Entwicklungssystem zu sehen), zu unpassenden Ereignissen dann aber doch wieder (wie auf dem Livesystem).

    - Sven Rautenberg

    --
    "Love your nation - respect the others."
    1. Hallo Sven,

      Ich denke, dein elementarer Fehler liegt hier:

      Die Zeichensatzunterstützung von MySQL raff ich nicht richtig und verwende sie auch nicht.

      Damit hast Du natürlich vollkommen recht - was mir klar ist - Dass ic#
      mich damit eingängiger auseinandersetzen muss, um sollche Probleme
      zukünfit keine mehr sind, ist mir insofern auch klar.

      Ich hab's nun in den relativ einfach Griff gekriegt:

      im metatag steht utf8 und vorm Schreiben in die DB führe ich ein
      'SET NAMES utf8' aus ... was erstmal den Fehler behebt.

      danke,
      gruesse,
      heinetz

      1. Hallo heinetz!

        Warum gehst du nicht der Reihe nach die Hinweise von Sven durch?

        1. Welche Kodierung verwendet der Server?
           (unterstützt der kein UTF-8, solltest du vllt. eine andere Kodierung in Betracht ziehn)
        2. Wurde der korrekte Zeichensatz im HTML-Header und als Meta-Tag angegeben?
        3. Ist deine Tabelle mit UTF-8 kodiert? (lässt sich z.B. über PHPMyAdmin leicht heraus finden)
        4. Verwende die Multibyte Funktionen von PHP

        im metatag steht utf8

        Siehe oben! Was sagt denn der Header?

        'SET NAMES utf8' aus ... was erstmal den Fehler behebt.

        Ob das die beste Lösung ist...

        Grüße, Matze

        1. Hallo

          'SET NAMES utf8' aus ... was erstmal den Fehler behebt.
          Ob das die beste Lösung ist...

          nunja, es ist eine Möglichkeit, dem MySQL-Server mitzuteilen, dass UTF-8 als Charset in der aktuellen Verbindung genutzt werden soll. mysql_set_charset() wie auch das mysqli-Pendant mysqli::set_charset() sind moderne Alternativen, die es noch nicht lange gibt und die daher bei entsprechender Suche erst selten zu finden sind (Beiträge von dedlfix [1] im hiesigen Forum mal ausgenommen :-)).

          Das Charset nicht festzulegen und die dadurch resultierende Verwendung eines falschen Charsets ist ein beliebter Fehler in der Verarbeitungskette.

          Freundliche Grüße

          Vinzenz

          [1] Ein willkürlich herausgegriffenes Suchergebnis.

        2. echo $begrüßung;

          1. Ist deine Tabelle mit UTF-8 kodiert? (lässt sich z.B. über PHPMyAdmin leicht heraus finden)

          Die Tabellen-Angabe ist nur dann von Interesse, wenn neue Felder ohne explizite Kodierungs-/Kollationsangabe hinzugefügt werden. Jedes Feld kann seine eigenen Kodierung haben. Beim Umschreiben der Tabellenkodierungsangabe ändert sich für die bereits bestehenden Felder nichts. Für diese muss die Kodierung einzeln angepasst werden. (Dabei versucht MySQL den Inhalt umzukodieren. Wenn der bisherige Inhalt nicht zur alten Kodierungsangabe gepasst hat, gibt es Datensalat.)

          'SET NAMES utf8' aus ... was erstmal den Fehler behebt.
          Ob das die beste Lösung ist...

          Es ist für die hierzulande üblichen Kodierungen ISO-8859-Familie und UTF-8 gleichwertig zur ansonsten besten Lösung mysql_set_character_set() bzw. deren Pendants in anderen programmiersprachenspezifischen Funktionssammlungen.
          Was konkret lässt dich den zweifeln?

          echo "$verabschiedung $name";

          1. Hallo dedlfix!

            Es ist für die hierzulande üblichen Kodierungen ISO-8859-Familie und UTF-8 gleichwertig zur ansonsten besten Lösung mysql_set_character_set() bzw. deren Pendants in anderen programmiersprachenspezifischen Funktionssammlungen.

            Es ist mir durchaus nicht neu, den Eindruck wollte ich nicht erwecken.

            Was konkret lässt dich den zweifeln?

            Dass ich es nicht verwende, weil ich das Umfeld in der Regel so anpasse, dass die Kodierung überall gleich ist.
            Somit ist die Angabe dann überflüssig.

            Das sollte auch bei Dritt-Anbietern möglich sein weil ich nicht glaube, dass irgendwer Webspace mit PHP und DB anbietet und dabei 2 oder gar 3 verschiedene Kodierungen einstellt. Ich kann auch guten Gewissens auf UTF8 verzichten wenn der Server auf ISO-8859... eingestellt ist.

            Oder denke ich grad in die falsche Richtung?

            Grüße, Matze

            1. echo $begrüßung;

              Was konkret lässt dich [an SET NAMES] zweifeln?
              Dass ich es nicht verwende, weil ich das Umfeld in der Regel so anpasse, dass die Kodierung überall gleich ist.
              Somit ist die Angabe dann überflüssig.

              Dann musst du dir auch die Einstellung character-set-server auf dem MySQL-Server selbst setzen können.

              Das sollte auch bei Dritt-Anbietern möglich sein weil ich nicht glaube, dass irgendwer Webspace mit PHP und DB anbietet und dabei 2 oder gar 3 verschiedene Kodierungen einstellt.

              Webspace-Anbieter haben in der Regel nicht für jeden Kunden einen eigenen MySQL-Server, den sich dieser selbst verwalten könnte sondern einen für viele, der meist unter dem Default-Wert Latin1 läuft.

              Ich kann auch guten Gewissens auf UTF8 verzichten wenn der Server auf ISO-8859... eingestellt ist.
              Oder denke ich grad in die falsche Richtung?

              Es ist möglich, einem MySQL-Server, der auf der Client-Verbindung von Latin1-kodierten Daten ausgeht, UTF-8-kodierte Daten zu senden. Man bekommt sich auch so wieder zurück. Nur kann man dann keine Funktionalität nutzen, die auf korrekte Zeichen angewiesen ist. Das fängt bei der Sortierung an, betrifft Längenermittlungen und Stringfunktionen und hört bei der Größenangabe der Felder nicht auf. VARCHAR(10) speichert beispielsweise nur 9 Zeichen, wenn eins davon ein UTF-8-Umlaut ist. Außerdem bekommt man dann genau die Probleme des Ausgangspostings, wenn man mit korrekt arbeitenden Tools wie dem allseits beliebten phpMyAdmin auf seinen Datenbestand zugreifen möchte.

              echo "$verabschiedung $name";

    2. [...] Das gilt insbesondere für die Datenverbindung zur Datenbank, die ebenfalls auf UTF-8 eingestellt werden muß. Und zu guter letzt benötigen natürlich auch die DB-Datenfelder die korrekte Auszeichnung mit UTF-8, wobei die Kollation auch noch dafür sorgt, wie das Sortierverhalten ist.

      Hi,
      dazu hätt ich auch mal eine hier relevante Frage...
      MySQL verwendet ja afaik standardmäßig ISO-5589-1. Wenn es aber nur darum geht, Daten in die Datenbank zu speichern und wieder auszulesen, welche UTF-8 codiert sind, ist es dann nicht trotzdem egal mit welchem Charset MySQL arbeitet?
      Klar, wenn ich z.B. Fulltext-Indizes verwendet, wird MySQL z.B. Umlaute nicht als solche erkennen, Indizes wären also nur beschränkt nutzbar, aber die gespeicherten Daten dürften sich doch eigentlich nicht verändern, oder?
      Wenn ich also UTF-8 Zeichen in die DB speichere, wobei die DB mit ISO-8859-1 arbeitet, und dann wieder auslese und ausgebe, dürften sie doch immernoch korrekte UTF-8 Zeichen sein, oder?

      Soll jetzt nicht heißen, dass man generell darauf verzichten kann, MySQL über den Zeichensatz aufzuklären - ich frag mich nur, für den Fall dass man es vergisst, ob es dadurch trotzdem zu Problemen bei der reinen Ausgabe der Daten kommen kann.

      Gruß,
      Andreas

      1. Hallo Andreas,

        Klar, wenn ich z.B. Fulltext-Indizes verwendet, wird MySQL z.B. Umlaute nicht als solche erkennen, Indizes wären also nur beschränkt nutzbar, aber die gespeicherten Daten dürften sich doch eigentlich nicht verändern, oder?
        Wenn ich also UTF-8 Zeichen in die DB speichere, wobei die DB mit ISO-8859-1 arbeitet, und dann wieder auslese und ausgebe, dürften sie doch immernoch korrekte UTF-8 Zeichen sein, oder?

        Prinzipiell schon, ja. Allerdings musst Du dann höllisch darauf aufpassen, dass MySQL wirklich überall nur Latin1 verwendet - und Deine Programme müssten das dann immer uminterpretieren. Tools wie phpMyAdmin werden Dir die Sachen "doppelt kodiert" anzeigen. Da ist es viel besser, gleich aufzupassen, dass alles UTF-8 ist, dann spart man sich eine MENGE Probleme, die durch Situationen wie "Was soll der Code, den ich vor 6 Monaten geschrieben habe, eigentlich nochmal machen? Warum ist hier ISO-8859-1, ich arbeite doch mit UTF-8?" entstehen...

        Viele Grüße,
        Christian