simon margulies: Webentwicklung auf UTF-8

Beitrag lesen

Problem:
Umlaute werden auf HTML Seiten nicht richtig dargestellt nach Eingabe in ein Formular.

Technologie:
Seite des Clients HTTP und xmlhttprequest(Ajax), Serverseitig: PHP und eine mySql-DB.

Ziel:
korrekte Darstellung von Zeichen in utf-8 encoding (insbes. Umlauten usw) auf html Seiten, die über PHP oder xmlhttprequest geladen werden.

Lösung:
ich habe ziemlich geschwitzt an dem ganzen - besonders weil ich nirgendwo eine verständliche Doku zu diesem Problem gefunden habe. Ich hoffe, anderen mit diesem Post behilflich sein zu können:
PHP unterstützt Unicode leider nur mit den Funktionen utf8_encode() und utf8_decode() - dennoch ist das Ziel ohne zusätzliche Libraries erreichbar. html-seiten mit dem header tag:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
versehen.
Zur Sicherheit, besonders für das Laden durch einen xmlhttprequest (Safari hat utf-8 nicht als default) von php generierten Antworten vom Server vor jeglichem Output (sofern es sich nicht um xml sondern um html handelt):
<?php header("Content-type:text/html; charset=utf-8"); ?>
ausgeben.
Formulare können wie folgt definiert werden:
<form name="form1" id="form1" method="post" action="post-end.php" enctype="application/x-www-form-urlencoded" accept-charset="utf-8">
oder
<form name="form1" id="form1" method="post" action="post-end.php" enctype="multipart/form-data" accept-charset="utf-8">
Die 2. Möglichkeit wird benötigt, falls files mit dem Formular mitgeschickt werden. Die Attribute enctype und accept-charset haben aber bei praktisch keinem Browser einen Einfluss: das encoding wird vom weiter oben festgelegten header bestimmt.

Wird nun ein solches Formular via HTTP verschickt, so erreicht es den Webserver und damit PHP in der x-www-form-urlencoded Form. Um nun die mitgeschickten Werte in der mySql-DB zu speicher müssen diese decodiert werden:
<?php
$str = utf8_decode($_POST['formularfeld1']);
$sql = "UPDATE mytable SET myfield='{$str}' WHERE ...";
?>

Die 'Collation' der felder in der mytable auf der mySQL-DB sollte auf 'utf8_unicode_ci' gesetzt sein. Siehe phpMyAdmin.

Beim Auslesen der Werte aus der DB und ihrer Darstellung über PHP auf einem Webbrowser, sind erst die oben genannten header-infos zu schicken und dann der Wert der aus der DB zu enkodieren:
<?php header("Content-type:text/html; charset=utf-8"); ?>
...
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
...
<?php
echo utf8_encode($res['myfield']);//$res hat die ergebnisse der Datenbankabfrage gespeichert.
?>

und schon hat man eine funktionierende utf-8 Umgebung.

Sollen die Formular-Werte über xmlhttprequest an den Server verschickt werden, können sie der xmlhttprequest.send() als String-parameter übergeben werden:
Kommentare sind direkt in den Code geschrieben.

Formularbutton irgendwo zwischen <form></form>:
<input type="button" name="Submit" value="Bestellen" onClick="ajax.formstart('zielskript.php', myCallback, this.form);">

JavaScript:
<script type="text/javascript">
<!--
var ajax;
ajax = new JSLRequest();

function myCallback (req) {//wird ausgeloest, wenn xmlhttprequest seine antwort gekriegt hat: antwort des php-skriptes auf dem server.
 if(document.getElementById){
  var ele = document.getElementById('zielort');//<span id="zielort"></span> im html-body.
  ele.innerHTML = req.responseText;
 }
}

function JSLRequest () {//klasse mit dem xmlhttprequest objekt
    var reqobj;//xmlhttprequest objekt
    var callback;

this.handler = function () {
        if (reqobj.readyState == 4) {
            if (reqobj.status == 200) {
                callback(reqobj);
            }
            else {
                callback(reqobj);
            }
        }
    }

this.formstart = function(hostfunc, callback_func, form){//wird vom button im form ausgeloest
     try{
  reqobj = new ActiveXObject("Microsoft.XMLHTTP");
 }
 catch(Error){
  try{
   reqobj = new ActiveXObject("MSXML2.XMLHTTP");
  }
  catch(Error){
   try{
    reqobj = new XMLHttpRequest();
   }
   catch(Error){
    //hier auf die alternative verweisen
   }
  }
        }

var str = getFormValues(form);//str wird saemtliche form-werte beinhalten in der form var1=wert1&var2=wert2&var3=wert3 ...
 //form ist das dom-form objekt in welchem sich der form-button ausgelöst wurde.

callback = callback_func;

reqobj.onreadystatechange = this.handler;

reqobj.open ("POST", hostfunc, true);

reqobj.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");//sonst wird str nicht zum server geschickt.
       reqobj.send (str);
    }

getFormValues = function(fobj){//diese funktion setzt die variablen und werte aus dem form zusammen
 var str = "";
 var valueArr = null;
 var val = "";
 var cmd = "";

for(var i = 0;i < fobj.elements.length;i++){

switch(fobj.elements[i].type){//cases nicht vollständig, es kann noch andere form-element geben als die unten abefangenen, hier nur z Bsp:

case "hidden":
       str += fobj.elements[i].name + "=" + escape(fobj.elements[i].value) + "&";
       break;

case "text":
       str += fobj.elements[i].name + "=" + escape(fobj.elements[i].value) + "&";
       break;

case "select-one":
       str += fobj.elements[i].name + "=" + fobj.elements[i].options[fobj.elements[i].selectedIndex].value + "&";
       break;

}
 }
        str = str.substr(0,(str.length - 1));
 return encodeURI(str);//encodeURI damit auf der php-seite utf8_decode angewandt werden kann:
 //mitencodeURIComponent sind bei mir dann keine Werte gesendet worden... ???
      }
}
</script>