Petersen: Never ending story Sonderzeichen

Hi,
gebe in ein Formularfeld (vorname) auf einer Seite bspw. ein ü ein.
Ich sehe im Browser das gerade eingegebene ü in dem Feld.
Die Eingabe wird von einem externen php-script mit einem rgex kontrolliert und  anschließend in einer Datenbank gespeichert.
Lese ich den Wert nach dem Eintragen aus, sehe ich anstelle von ü das hier:"ü"
Öffne ich phpMyadmin sehe ich anstelle von ü das hier:"ü"

Die Zeichendeklaration im HTML Header:
<meta http-equiv="content-type" content="text/html; charset=utf-8">

Überprüfung mit regex des Vornamens:

// Prüft, ob der Vorname unerlaubte Zeichen enthält  
// ...  
elseif(!preg_match('/^[a-züÜöÖäÄéÉèÈ\s]+$/i', trim($_POST['vorname'])))  
$errors[]= "Ihre Eingabe: ".$_POST['vorname'].": - Im Vornamen sind keine Zahlen und keine Umlaute erlaubt außer üöäéè";

Der Eintrag in die Datenbank erfolgt so:

$_POST['vorname']=utf8_encode($_POST['vorname']);  
$update="UPDATE nutzer SET vorname='".mysql_real_escape_string(trim($_POST['vorname']))."' WHERE ...";  
mysql_query($update) OR die("<pre>\n".$update."</pre>\n".mysql_error());

Das Datenbankfeld hat als Kollation:utf8_unicode_ci

Der Nutzer soll also diese Sonderzeichen eingeben können und dann natürlich auch beim Auslesen des Feldinhalts genauso angezeigt bekommen.

MfG
Petersen

  1. Moin Petersen,

    $errors[]= "Ihre Eingabe: ".$_POST['vorname'].": - Im Vornamen sind keine Zahlen und keine Umlaute erlaubt außer üöäéè";

    Ich finde diese Einschränkung nicht sinnvoll.

    $_POST['vorname']=utf8_encode($_POST['vorname']);

    Hier liegt ein Denkfehler vor. Die Daten werden durch deinen <meta>-Header (und vermutlich keinem widersprechenden Content-Type-Header) schon UTF-8 kodiert verschickt, das heisst, du interpretierst hier einen UTF-8-String als ISO-8859-1 und kodierst ihn erneut nach UTF-8. Lass den Schritt einfach weg. :)

    LG,
     CK

    1. Ich finde diese Einschränkung nicht sinnvoll.

      Ok, was schlägst Du als erlaubte Zeichen für den Vornamen vor?

      $_POST['vorname']=utf8_encode($_POST['vorname']);

      Hier liegt ein Denkfehler vor. Die Daten werden durch deinen <meta>-Header (und vermutlich keinem widersprechenden Content-Type-Header) schon UTF-8 kodiert verschickt, das heisst, du interpretierst hier einen UTF-8-String als ISO-8859-1 und kodierst ihn erneut nach UTF-8. Lass den Schritt einfach weg. :)

      Der vollständige Kopf meiner Seite sieht so aus:

        
      <?xml version="1.0" encoding="utf-8"?>  
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
        
      <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">  
        
      <head>  
        
      <meta http-equiv="content-type" content="text/html; charset=utf-8">  
        
      <title>Seitentitel</title>  
        
      <link href="styles/styles.css" rel="stylesheet" type="text/css" />  
        
      </head>  
      <body>  
      
      

      Habe das encode weggelassen. Jetzt zeigt mir meine Seite ü etc. richtig an.
      Öffne ich den PHPmyadmin sehe ich da immer noch diese Verschlüsselung.
      Eigentlich kann es mir doch egal sein, was mein phpMyadmin anzeigt, solange es beim Nutzer im Browser richtig angezeigt wird order?

      VG
      Pertersen

      1. Hallo,

        Ich finde diese Einschränkung nicht sinnvoll.
        Ok, was schlägst Du als erlaubte Zeichen für den Vornamen vor?

        alle, die man bei großzügiger Auslegung als "Buchstaben" auffassen kann. Dazu gehören Umlaute und diakritische Zeichen ebenso dazu wie das kyrillische und griechische Alphabet, wenn man noch weiter gehen möchte. natürlich auch die Zeichen der arabischen, hebräischen, chinesischen oder japanischen Schrift - von der Vielfalt weiterer asiatischer Schriften ganz zu schweigen.

        Der vollständige Kopf meiner Seite sieht so aus:

        <?xml version="1.0" encoding="utf-8"?>

        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

        <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">

        <head>

        <meta http-equiv="content-type" content="text/html; charset=utf-8">

        <title>Seitentitel</title>

        <link href="styles/styles.css" rel="stylesheet" type="text/css" />

        </head>
        <body>

          
        Drei Dinge sind dazu noch interessant:  
         a) Welche Codierung gibt der Server im HTTP-Header an? Die hat nämlich Vorrang vor dem meta-Element.  
         b) In welcher Codierung ist das Dokument \*wirklich\* gespeichert?  
         c) Welche Codierung wird für die Kommunikation zwischen PHP und der DB verwendet?  
          
        
        > Habe das encode weggelassen. Jetzt zeigt mir meine Seite ü etc. richtig an.  
          
        Dann hast du entweder alles richtig gemacht, oder es passt nun "zufällig". ;-)  
          
        
        > Öffne ich den PHPmyadmin sehe ich da immer noch diese Verschlüsselung.  
          
        Das heißt, die Daten werden tatsächlich in UTF-8 in der Datenbank gespeichert, aber der PMA "meint", es sei ISO-8859-1.  
          
        
        > Eigentlich kann es mir doch egal sein, was mein phpMyadmin anzeigt, solange es beim Nutzer im Browser richtig angezeigt wird order?  
          
        Eigentlich schon. An deiner Stelle würde es mich aber trotzdem noch interessieren, warum es jetzt richtig läuft.  
          
        Ciao,  
         Martin  
        
        -- 
        Auf jeden Menschen auf der ganzen Welt entfallen statistisch gesehen etwa 3000 Spinnen, wie Wissenschaftler jetzt festgestellt haben.  
        Wer will meine haben? Denn ich will sie bstimmt nicht.  
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        
        1. Tach!

          Öffne ich den PHPmyadmin sehe ich da immer noch diese Verschlüsselung.
          Das heißt, die Daten werden tatsächlich in UTF-8 in der Datenbank gespeichert, aber der PMA "meint", es sei ISO-8859-1.

          Selten. Wenn der PMA was falsch anzeigt, ist in der Regel immer etwas mit den Daten in MySQL falsch.

          dedlfix.

        2. Drei Dinge sind dazu noch interessant:
          a) Welche Codierung gibt der Server im HTTP-Header an? Die hat nämlich Vorrang vor dem meta-Element.
          b) In welcher Codierung ist das Dokument *wirklich* gespeichert?
          c) Welche Codierung wird für die Kommunikation zwischen PHP und der DB verwendet?

          Hi,
          ich muss gestehen, dass ich nicht weiß, wie ich auf a) oder b) antworten kann.
          zu c) habe gerade das hier beim Verbindungsaufbau zur DB probiert:

          // Verbindung zur Datenbank aufbauen  
          	$connid = @mysql_connect($MYSQL_HOST, $MYSQL_USER, $MYSQL_PASS) OR die("Error: ".mysql_error());  
          	mysql_select_db($MYSQL_DATA) OR die("Error: ".mysql_error());  
          	mysql_query("SET NAMES 'utf8'"); 
          

          dann klappt es wieder nicht. für ü erhalte ich jetzt im Browser nach dem auslesen quadrate mit Fragezeichen drin. dafür sehe ich im phpmyadmin das ü
          Das ist doch zum Mäusemelken!

          1. Ich habs!..glaube ich :-)

            Habe jetzt sowohl im Eingabe-Script als auch im Ausgabe-Skript
            den Verbindungsaufbau zur Datenbank um folgenden Ausdruck erweitert:
            mysql_set_charset('utf8');
            Jetzt zeigt der Browser schöne ü ä ö usw. an und auch der phpMyadmin stellt sich nicht quer sondern zeigt die Zeichen an.

            Vielen Dank Euch allen!

          2. Tach!

            Drei Dinge sind dazu noch interessant:
            a) Welche Codierung gibt der Server im HTTP-Header an? Die hat nämlich Vorrang vor dem meta-Element.
            b) In welcher Codierung ist das Dokument *wirklich* gespeichert?
            c) Welche Codierung wird für die Kommunikation zwischen PHP und der DB verwendet?
            ich muss gestehen, dass ich nicht weiß, wie ich auf a) oder b) antworten kann.

            a) Nimm dir ein Tool wie die livehttpheaders-Extension für den Firefox und schau dir die vom Server gesendeten Header an.

            Ich empfehle nochmal http://wiki.selfhtml.org/wiki/Themen:Zeichencodierung und dort die Abschnitte Webdokumente und Webserver. Da findest du auch beschrieben, wonach du schauen musst.

            b) kannst nur du selbst beantworten und dabei deinen Editor genauer anschauen, was du beim Speichern angegeben hast oder was konfiguriert ist.

            c) hast du ja schon gefunden: nach jedem Verbindungsaufbau einzustellen.

            dedlfix.

      2. Tach!

        Ich finde diese Einschränkung nicht sinnvoll.
        Ok, was schlägst Du als erlaubte Zeichen für den Vornamen vor?

        Alle. Mit jeder Einschränkung kann man Mist machen. Technisch ist kein Zeichen problematisch, wenn du die Kontextwechsel berücksichtigst.

        Habe das encode weggelassen. Jetzt zeigt mir meine Seite ü etc. richtig an.
        Öffne ich den PHPmyadmin sehe ich da immer noch diese Verschlüsselung.

        Verbindungskodierung aushandeln!

        Eigentlich kann es mir doch egal sein, was mein phpMyadmin anzeigt, solange es beim Nutzer im Browser richtig angezeigt wird order?

        Nein, es sei denn, du willst auf alle Stringfunktionen MySQLs verzichten (inklusive Sortierung).

        dedlfix.

        1. Hello,

          Ich finde diese Einschränkung nicht sinnvoll.
          Ok, was schlägst Du als erlaubte Zeichen für den Vornamen vor?

          Alle. Mit jeder Einschränkung kann man Mist machen. Technisch ist kein Zeichen problematisch, wenn

          Das ist schlichtweg Unsinn.
          Benenne mir bitte den Codepoint für Hethitisch in UTF

          Auch UTF ist nur eine Untermenge des Möglichen. Wer trifft denn da die Auswahl?

          Ich bin immer noch der Meinung, dass eine Reduzierung auf ASCII uns weitergebracht hätte, als die bisher vorliegende Erweiterung auf UTF und sonstwelchen Unsinn. Selbst die Chinesen waren nahezu Bereit dazu, sich von ihrer Bildersprache zu verabschieden, und ihre Begriffe in Lautformung und ASCII darzustellen. Dass wir diesen Zeitpunkt verpasst haben, ist im Sinne einer WEltverständigung einfach unverzeihlich!

          Liebe Grüße aus dem schönen Oberharz

          Tom vom Berg

          --
           ☻_
          /▌
          / \ Nur selber lernen macht schlau
          http://bergpost.annerschbarrich.de
          1. Tach!

            Ok, was schlägst Du als erlaubte Zeichen für den Vornamen vor?
            Alle. Mit jeder Einschränkung kann man Mist machen. Technisch ist kein Zeichen problematisch, wenn
            Das ist schlichtweg Unsinn.
            Benenne mir bitte den Codepoint für Hethitisch in UTF

            Es geht mir mit der Aussage nicht um sämtliche Zeichen dieses Universums, sondern nur um die in Unicode bereits enthaltenen. Für die anderen würde der Nachsatz mit dem Kontextwechsel schlicht keinen Sinn ergeben. Aber es ist insofern richtig und technisch problematisch, dass man im Falle MySQLs Abstriche machen muss, denn das unterstützt (meines Wissens immer noch) nur die BMP (die ersten 65536 Zeichen).

            dedlfix.

      3. Hello,

        Ich finde diese Einschränkung nicht sinnvoll.
        Ok, was schlägst Du als erlaubte Zeichen für den Vornamen vor?

        Das kommt doch immer darauf an, was man nachher damit machen will oder muss.

        Man muss sich nicht alle Codierungsprobleme dieser Welt zueigen machen, wenn man z.B. später einen Verzeichnisnamen damit erzeugen will...

        Ich halte UTF-Codierung noch lange nicht für sinnvoll, nur weil ganz viele "schlaue Leute" das befürworten. Oft liegt die Lösung in der Reduzierung auf das Wesentliche.

        @Petersen:

        Mach Dir bitte klar, welche Codierung wo gilt:

        Browser bei der Erfassung
        Browser bei der Übermittlung an den Server
        Server beim Empfang der Daten und der nachfolgenden Auswertung im Script
        Server im Script beim Aufbau nder Datenbankverbindung
        Server im Script bei Vorbereitung der Daten dür den Datenbankkontext
        Server im Script bei der Übermittlung der Daten an die Datenbank
        Datenbank bei der Speicherung der Datgen in der betroffenen Tabelle und Spalte

        usw. (Rückweg)

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
  2. Tach!

    Der Eintrag in die Datenbank erfolgt so:
    [code lang=php]$_POST['vorname']=utf8_encode($_POST['vorname']);
    Öffne ich phpMyadmin sehe ich anstelle von ü das hier:"ü"

    Nicht nur, dass du keine UTF-8-Kodierung benötigst, weil die Daten bereits so vorliegen, scheinst du auch nicht mit MySQL die auf der Verbindung zwischen deinem Client und ihm zu verwendende Kodierung auszuhandeln. Meine Vermutung ist, dass dein MySQL-Server davon ausgeht, Latin1-Daten geschickt zu bekommen.

    Der Browser sendet ein UT_8-ü, bestehend aus 2 Byte. Das utf8_encode() macht UTF-8 aus ISO-8859-1, also werden die zwei Byte als zwei Zeichen angesehen und 4 Byte draus gemacht.

    Das Datenbankfeld hat als Kollation:utf8_unicode_ci

    Diese angeblichen Latin1-Daten kodiert MySQL nun für das Feld nach UTF-8 um. Das ist die zweite Kodierung, die dir dann aus den 4 Byte (entspricht 4 Latin1-Zeichen) 8 Byte. Eine Kontrollausgabe LENGTH() auf das Feld wird also nun 8 ergeben und CHARACTER_LENGTH() das Ergebnis 4.

    Der Nutzer soll also diese Sonderzeichen eingeben können und dann natürlich auch beim Auslesen des Feldinhalts genauso angezeigt bekommen.

    Schau mal da: SELFHTML-Wiki: Zeichencodierung

    dedlfix.

  3. Hallo,

    Der Eintrag in die Datenbank erfolgt so:

    $_POST['vorname']=utf8_encode($_POST['vorname']);

    [pref:t=210284;m=1432947@title=dass Du utf8_encode nicht verwenden sollst], [pref:t=210284;m=1432954@title=weißt Du ja schon],

    Du solltest aber MySQL auch mitteilen, dass die Daten in UTF-8 codiert

    vorliegen, der bevorzugte Weg dazu ist in Deinem Fall

    link:http://de2.php.net/manual/de/function.mysql-set-charset.php@title=mysql_set_charset;

    Dies gilt übrigens auch für das Auslesen der Daten

    So wie es aussieht, spricht Deine Clientbibliothek standardmäßig Latin-1

    $update="UPDATE nutzer SET vorname='".mysql_real_escape_string(trim($_POST['vorname']))."' WHERE ...";
    mysql_query($update) OR die("<pre>\n".$update."</pre>\n".mysql_error());

      
      
    Freundliche Grüße  
      
    Vinzenz