MySQL PHP Umlaute/Sonderzeichen fixen UTF-8/ISO


Jeder kennt das Problem, aus irgendeinem Grund wurden Wörter in der falschen Kodierung in die Datenbank geschrieben. Wenn das passiert ist, kann man daran erkennen, dass sich Zeichen wie diese untergemischt haben:

'¦, '¨, '?, '´, '¸, 'À, 'Á, 'Â, 'Ã, 'Ä, 'Å, 'Æ, 'Ç, 'È, 'É, 'Ê, 'Ë,
'Ì, 'Í, 'Î, 'Ï, 'Ñ, 'Ò, 'Ó, 'Ô, 'Õ, 'Ö, 'Ø, 'Ù, 'Ú, 'Û, 'Ü, 'Ý, 'Þ,
'ß, 'à, 'á, 'â, 'ã, 'ä, 'å, 'æ, 'ç, 'è, 'é, 'ê, 'ë, 'ì, 'í, 'î,
'ï, 'ð, 'ñ, 'ò, 'ó, 'ô, 'õ, 'ö, 'ø, 'ù, 'ú, 'û, 'ý, 'þ, 'ÿ

Das Problem ist, dass diese Zeichen nicht utf8 kodiert worden sind, aber in utf8 dargestellt worden sind, was eine Vielzahl an Gründen haben kann.

Iso-kodierte Strings nach UTF-8 umwandeln

Um dies zu vermeiden, sollte also vorher die Funktion

$string = utf8_encode($string);

angewendet werden.

Überprüfung der Kodierung

Die Kodierung von Strings kann überprüft werden mit der Funktion mb_detect_encoding.

echo mb_detect_encoding($string);

Für einen Quick and Dirty Fix kann man folgende Lösung nehmen:

if(mb_detect_encoding($string) != 'UTF-8') {          $string = utf8_encode($string); }

Ändern der Datenbankverbindungs-Kodierung

Eine weitere Fehlerquelle, ist die Übertragung der Daten zur Datenbank, diese sollte immer einmalig nach dem Öffnen der Datenbankverbindung auf UTF-8 gesetzt werden:

...
mysql_connect();
mysql_query("SET NAMES 'utf8'");

Laden von UTF-8 kodierten PHP Dateien in ein ISO-kodiertes Projekt

Wenn ausversehen UTF-8 kodierte PHP-Dateien geladen werden, kann es vorkommen, dass die Kodierung trotz aller Mühe auf UTF-8 umgestellt wird.

Dann hilft folgendes:

require_once "utf-8.php"
header('Content-Type: text/html; charset=ISO-8859-1');

Hilfsfunktion um Arrays nach UTF-8 zu kodieren

Eine einfache rekursive Funktion um ein mehrdimensionales Array nach UTF-8 zu kodieren ist (performanter wäre noch mit Referenzen zu arbeiten):

function utf8encodeArray($array)
{
        foreach($array as $key =>  $value)
        {
            if(is_array($value))
            {
                $array[$key] = utf8encodeArray($value);
            }
            elseif(!mb_detect_encoding($value, 'UTF-8', true))
            {
                $array[$key] = utf8_encode($value);
            }
        }
}

Der Header

Es sollte auch kontrolliert werden, ob der Header des HTML Dokuments auf UTF8 gesetzt worden ist:

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

oder mit PHP

header ('Content-type: text/html; charset=utf-8');

Datei-Kodierung

Die Codierung der PHP Datei muss auch UTF-8 sein, sonst werden Umlaute auch falsch dargestellt (kann z.B. mit Notepad++ überprüft und verändert werden: Hauptmenü->Kodierung->UTF-8 ). In jede gute IDE kann die Kodierung für ein ganzes Projekt voreingestellt werden.

Andere Fehlerquellen

Man kann die Kodierung eines Strings oder Dokuments auf vielfältige Weise verlieren. Besonders heimtückisch sind PHP Funktionen zur String-Manipulation, die den String automatisch nach UTF8 umwandeln und zurückgeben, was ein Problem darstellt, wenn die Webseite in ISO-8859-1 codiert ist. Leider habe ich die Funktionen nicht mehr gefunden, ich würde mich sehr freuen über Feedback zu dem Thema.

Wenn es bereits zu spät ist und die Daten in der DB gespeichert worden sind, kann man die falschen Umlaute wie folgt ersetzen:

private function getUmlauteArray() { return array( 'ü'=>'ü', 'ä'=>'ä', 'ö'=>'ö', 'Ö'=>'Ö', 'ß'=>'ß', 'à '=>'à', 'á'=>'á', 'â'=>'â', 'ã'=>'ã', 'ù'=>'ù', 'ú'=>'ú', 'û'=>'û', 'Ù'=>'Ù', 'Ú'=>'Ú', 'Û'=>'Û', 'Ãœ'=>'Ü', 'ò'=>'ò', 'ó'=>'ó', 'ô'=>'ô', 'è'=>'è', 'é'=>'é', 'ê'=>'ê', 'ë'=>'ë', 'À'=>'À', 'Á'=>'Á', 'Â'=>'Â', 'Ã'=>'Ã', 'Ä'=>'Ä', 'Ã…'=>'Å', 'Ç'=>'Ç', 'È'=>'È', 'É'=>'É', 'Ê'=>'Ê', 'Ë'=>'Ë', 'ÃŒ'=>'Ì', 'Í'=>'Í', 'ÃŽ'=>'Î', 'Ï'=>'Ï', 'Ñ'=>'Ñ', 'Ã’'=>'Ò', 'Ó'=>'Ó', 'Ô'=>'Ô', 'Õ'=>'Õ', 'Ø'=>'Ø', 'Ã¥'=>'å', 'æ'=>'æ', 'ç'=>'ç', 'ì'=>'ì', 'í'=>'í', 'î'=>'î', 'ï'=>'ï', 'ð'=>'ð', 'ñ'=>'ñ', 'õ'=>'õ', 'ø'=>'ø', 'ý'=>'ý', 'ÿ'=>'ÿ', '€'=>'€' );

public function fixeUmlauteDb() {                  $umlaute = $this->getUmlauteArray();                  foreach ($umlaute as $key => $value){                                         $sql = "UPDATE table SET tracks = REPLACE(row, '{$key}', '{$value}') WHERE row LIKE '%{$key}%'";                   } }

Achtung: Das Script funktioniert nur, wen die Codierung der PHP Datei UTF-8 ist (kann z.B. mit Notepad++ gecheckt/verändert werden: Hauptmenü->Kodierung->UTF-8 ).

Das Script funktioniert also nur mit einer UTF8 codierten Projekt (siehe Artikel: PHP Rätsel).

Hat Ihnen der Artikel geholfen bei Ihrem Umlaute-Problem?

Ergebnis der Umfrage anzeigen

Loading ... Loading ...

Hinterlasse eine Antwort


vier + 3 =

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

  1. ISO-Encodings sehen niemals “zufällig” aus wie valides UTF-8, daher lässt sich klar prüfen, ob einem gerade Windows alias ISO-8859-1 encoding angeboten wird oder nicht.

    if ( (strlen($s) > 0) && ‘ISO-8859-1′ == mb_detect_encoding($search, ‘UTF-8, ISO-8859-1′, true))
    $s = utf8_encode( $s );

    • Vielen Dank für den Hinweis, die Funktion kannte ich noch nicht, ich hab sie gleich in den Artikel angebaut!

  2. >Das Problem ist, dass diese Zeichen nicht utf8 kodiert worden sind, aber in utf8 abgespeichert worden sind, weil die DB Spalte so definiert worden ist (Kolation: utf8_general z.B:).

    Nach meiner Erfahrung sieht das so aus wenn Strings in einem Multibyte-Zeichensatz (z.B. UTF-8) vorliegen und in einer DB-Spalte abgelegt werden, die einen Singlebyte-Zeichensatz hat (z.B. latin1). Zwei oder drei Bytes ergeben zusammengenommen eigentlich ein Sonderzeichen – der Singlebyte-Zeichensatz interpretiert aber jedes Byte einzeln und speichert sie so.

    Es gibt aber viele (gemeine) Kombinationsmöglichkeiten wie so etwas in der Db ankommen kann.

  3. Hallo, eingangs steht: “Das Problem ist, dass diese Zeichen nicht utf8 kodiert worden sind, aber in utf8 abgespeichert worden sind, weil die DB Spalte so definiert worden ist (Kolation: utf8_general z.B:).”
    1. heißt es “Kollation”, also mit zwei “L”
    2. ist die Kollation nur die Sortierreihenfolge, die ist hier aber nicht das Problem, es handelt sich hier um den Zeichensatz (encoding).
    Bitte korrigieren.
    Gruß franc

    • Vielen Dank für deine Hilfe Franc, ist gändert. Du hast vollkommen recht, dass die Kollation nur die Sortierreihenfolge ist.
      Diese beeinflusst, ob das Ä als ae oder a beim Sortieren ersetzt wird z.B.

  4. Pingback: [PHP/MySQL] Sonderzeichen speichern

  5. Hallo Sebastian,

    ich habe ein Problem. Und zwar schreibe ich Daten in meine DB. Die einzelnen Seiten sind in UTF-8 ohne BOM kodiert und die Datenbank ebenfalls.
    Wenn ich vor dem Absenden der Informationen mit “mb_detect_encoding” prüfe, dann wird mir auch “UTF-8″ zurückgegeben.

    Und trotzdem habe ich die merkwürdigen Sonderzeichen in meiner Datenbank zu stehen. Wenn ich die Daten aber wieder auslese, dann ist alles in Ordnung – sprich auf der Seite gibt es augenscheinlich keine Probleme.

    Ich habe noch den Befehl “mysql_query(“SET NAMES ‘utf8′”);” versucht, bevor ich die Daten in die DB schreibe. Dadurch sind die Daten in der DB richtig, also ohne Sonderzeichen, allerdings habe ich dann auf der Seite wieder die Hieroglyphen.

    Der Header ist auch auf UTF-8 gesetzt.

    Kannst was dazu sagen?
    Danke im Voraus!

    • Hi,
      dann kann es nur noch an der Datei-Kodierung liegen, diwe auf ISO gestellt ist. Versuch mal die Datei in Notepad++ zu ändern….

  6. Ja super vielen dank dass sich jemand die Mühe macht.
    Hat mir geholfen meine Db Einträge sauber zu machen.

    Vielen dank Sebastian

  7. Die PHP-Funktion strtolower arbeitet mit dem aktuellen Gebietschema – das gibt manchmal Probleme mit dem encoding. Stattdessen mb_strtolower verwenden.

  8. Leider habe ich ein offenbar noch anderes Problem mit den deutschen Umlauten: sie werden bei mir allesamt durch ein ? ersetzt oder aber sie fehlen ganz. Ich versuche mal meine Vorgehensweise zu zeigen:

    Beim Einspielen der Daten in die MySQL-DB habe ich folgende Schreibweise verwendet:

    CREATE TABLE IF NOT EXISTS `t_MeineTabelle`(
    `ID` INT,
    `Abk` varchar(10),
    `Bemerkung` TEXT
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

    INSERT INTO t_MeineTabelle(ID,Abk,Bemerkung)VALUES
    (1,’s1′,’schön’),
    (2,’s2′,’noch schöner’),
    (3,’s3′,’äöüß’);

    Wenn ich diese Einträge mit PHP abfrage, öffne ich die Datenbank mit diesen Befehlen:
    $_SESSION['link'] = @ mysql_connect( $db_server, $db_user, $db_passwort )
    or die( ‘Konnte keine Verbindung zur Datenbank herstellen’ );

    if ( !mysql_select_db( $db_name, $_SESSION['link'] ) ) {
    die( ‘Konnte das Datenbankschema nicht selektieren!’ );
    }
    mysql_query(“SET NAMES ‘utf8′”);

    Der Zugriff auf die Daten erfolgt dann so:
    $result = mysql_query( $sql, $_SESSION['link'] );
    for ($i = 0; $i < mysql_num_rows($result); $i++) {
    if (!mysql_data_seek($result, $i)) {
    $strFehler = "Cannot seek to row $i: " . mysql_error() . "\n";
    continue;
    }
    if (!($row = mysql_fetch_assoc($result))) {
    continue;
    }
    $Ausgabe = $row['Bemerkung'];
    }
    mysql_free_result($result);

    Natürlich schließe ich die Datenbankverbindung zum Ende der php-Datei:
    mysql_close($_SESSION['link']);

    Ergebnis:
    die Umlaute werden als ? angezeigt, das ß fehlt völlig.

    Hat irgendjemand eine Idee, wie ich mein Problem beheben kann?
    Vielen Dank im voraus.

  9. Hallo,
    bisher war dieser Artikel der umfangreichste bei der Hilfe zu diesem Problem. Leider jedoch hat er mir bei meinem Problem nicht weitergeholfen, was mich schier zum ausflippen langsam bringt.
    Gibt es denn noch andere Fehlerquellen / Probleme als oben beschrieben?
    Ich habe einen Webspace von einem Anbieter (also keinen dedizierten Server, lediglich Webspace).
    Beim Programmieren bin ich noch quasi Neuling, aber worum es geht, habe ich schon verstanden. Nur das Fachwissen fehlt halt (mach das nicht beruflich).
    Grüße
    Jürgen