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>