PHP rocks! wünscht allen Mitgliedern einen guten Rutsch ins neue Jahr 2017 !!!
Hinweis: Das Forum zieht um! Um keine Datenverluste zu haben, schalten wir zwecks Übernahme der Daten das Forum am Sonntag, den 24.04.2016 um ca. 21:00 Uhr offline und passen anschliessend die DNS-Einträge an.
www.php-rocks.de wird euch dann nach den Aktualisierungen der DNS-Server wieder wie gewohnt uneingeschränkt zur Verfügung stehen.
Danke für euer Verständnis!

Themabewertung:
  • 0 Bewertung(en) - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Entwicklung [Entwicklung] Die UTF8-Verschw�rung
#1
Die UTF8-Verschw�rung
Man mag es kaum glauben, aber auch in der heutigen Zeit werden Projekte online gestellt, die ein Problem mit Sonderzeichen haben. In diesem kleinen Tutorial möchte ich euch das Ganze etwas näher bringen, in der Hoffnung, dass die Mystik dessen etwas verschwindet.


Was bedeutet "Sonderzeichen"?
Um den Begriff Sonderzeichen im Zusammenhang mit diesem Tutorial zu definieren, sollte man wissen, dass wir von sogenannten Zeichenkodierungen und Kodierungstabellen sprechen. Alle Zeichen, die wir auf dem Bildschirm darstellen können, entstammen aus einer Zeichenkodierungen-Tabelle. Wenn wir nun versuchen ein Zeichen auszugeben, das sich in der verwendeten Tabelle nicht befindet, kommt es zu unerwünschten Ausgaben, die wir sicher alle schon mal gesehen haben.

Als Beispiel soll dieses kleine HTML mal herhalten:
Code:
<html>
<head>
<title></title>
</head>

<body>

<p>Hier steht ein ganz gewöhnlicher Satz mit lauter bekannten Zeichen</p>

</body>
</html>
Soweit ja nichts besonderes und relativ unspektakulär... Aber Moment... Im Browser sieht das auf einmal eher komisch aus:
Ausgabe:
Hier steht ein ganz gew�hnlicher Satz mit lauter bekannten Zeichen
Hier haben wir ein Problem mit der Zeichenkodierung. Die von uns verwendete scheint das ö nicht zu kennen und macht daraus eine sonderbare Konstellation.


Wo liegt mein Fehler?
Hier liegt ein Problem mit der Zeichenkodierung vor. Zugegeben, hier wäre es mit ein wenig Erfahrung leicht, die Kodierung an der richtigen Stelle zu setzen, um alles korrekt anzeigen zu lassen. Aber wir wollen heute mal alles richtig machen und schauen uns dazu mal kurz im Überblick an, an welchen Stellen wir auf eine korrekte Kodierung achten und diese konsequent auch einsetzen sollten:
  • Speicherung von Dateien
  • HTTP Header
  • Im HTML als <meta>-Tag
  • Datenbankverbindungen
  • Datenbank-, Tabellen- und Spaltenkollation
Ui... Für einige vielleicht schon zu viele unbekannte Begriffe?
Keine Angst, was das im einzelnen bedeutet, gehen wir jetzt mal Schritt für Schritt durch...


Speicherung von Dateien
Eure Dateien sollten immer als UTF-8 ohne BOM gespeichert werden. Viele gute Editoren oder IDE's bieten die Möglichkeit, die Kodierung beim Speichern einer Dateien einzustellen.
Beispielhaft wäre das im SublimeText 3 über den Menüpunkt File -> Save with Encoding -> UTF-8 erledigt oder ihr geht auf File -> Reopen with Encoding -> UTF-8 und speichert die Datei dann wieder.
Aber auch andere Editoren, wie bspw. Notepad++ haben diese Möglichkeiten.
Hinweis
Das BOM ( ByteOrderMark ) ist eine Kennung für die Unicode-Kodierung, die den Datenstrom einleitet und im Falle von UTF8 aus der Bytesequenz EF BB BF besteht.
Das wird in Browsern häufig als  interpretiert und ausgegeben ( im Quelltext des Browsers erkennbar ).
Das führt häufig zu bekannten Fehlern, wie Cannot add header information. Daher sollte man immer darauf achten, dass Dateien immer ohne BOM gespeichert werden!
Das gilt übrigens für alle Dateien ( .html, .php, .css, .js, usw. )!


HTTP Header
Im HTTP-Header werden Informationen über das Dokument, sowie HTTP-Cookies und Kennungen für den HTTP-Server, User-Agent und MIME-Typ übertragen.
Hier muß für unseren Zweck die entsprechende Kodierung bestimmt werden. Das geht bspw. über folgende PHP-Anweisung:
PHP-Code:
header 'Content-Type: text/html; Charset=utf-8' ); 
Hinweis
Bei der Verwendung der header()-Anweisung ist darauf zu achten, dass diese am Anfang des Root-Scriptes vor sämtlichen Ausgaben erfolgt, da ihr sonst schnell wieder den bereits erwähnten Fehler Cannot add header information bekommt.


<meta>-Tag
Um auch dem Browser mitzuteilen, welche Codierung wir in dem Dokument verwenden, müssen wir dies per <meta>-Tag entsprechend dem verwendeten <!DOCTYPE mitteilen:

Für Dokumente mit HTML4.x-Doctype:
Code:
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
Für Dokumente mit HTML5-Doctype:
Code:
<meta charset="utf-8">
Der <meta>-Tag wird im <head> des Dokuments, am besten direkt nach dem <title>-Tag angegeben.
Tipp
Solltet ihr Formulare verwenden, setzt am besten auch darin gleich die korrekte Kodierung für die Datenübertragung:
Code:
<form name="form" method="post" accept-charset="utf-8">


Datenbankverbindung
Verwendet ihr in eurem Projekt eine Datenbank, ist natürlich auch darauf zu achten, dass die Daten über eine einheitliche Kodierung ausgetauscht werden.
Für die Verbindung mit der Datenbank ( hier beispielhaft MySQL ) können wir dies wie folgt angeben:

PDO:
PHP-Code:
$oDB = new PDO'mysql:host=localhost;dbname=exampledb;charset=utf8'$username$password ); 
MySQLi:
PHP-Code:
$oDB = new MySQLi 'localhost'$username$password'exampledb' );
$oDB->set_charset'utf8' ); 
Hinweis
In Bezug auf PDO sei erwähnt, dass der Parameter charset im DSN ( Data Source Name ) in PHP-Versionen vor 5.3.6 ignoriert wurde. Solltet ihr tatsächlich noch eine dieser Versionen haben, müsst ihr die Kodierung ähnlich folgender Weise setzen:
PHP-Code:
$options = array( MYSQL_ATTR_INI_COMMAND => 'set names utf8' );
$oDB = new PDO'mysql:host=localhost;dbname=exampledb'$username$password$options ); 
Noch besser wäre es natürlich, wenn ihr in dem Falle eher die PHP-Version updated!


Kollation der Tabellen, Spalten und der Datenbank selbst
Wenn wir dafür sorgen, dass die Verbindung zur Datenbank sauber über UTF-8 abgewickelt wird, müssen wir natürlich auch die Datenhaltung sinnvoller Weise darauf auslegen.
Hierzu gibt es in Administrations-Tools, wie etwa phpMyAdmin ( MySQL ), pgAdmin ( pgSQL ), u.w. eine Einstellung, die sich Kollation ( Collation ) nennt. Hier kann sowohl auf Datenbank-, Tabellen- und Spalten-Ebene festgelegt werden, mit welcher Kodierung gearbeitet werden soll.

Die gängigsten Kollationen in dem Bereich Unicode sind utf8_unicode_ci und utf8_general_ci. Nennenswerter Unterschied ist die genauere Sortierung bei utf8_unicode_ci, während utf8_general_ci etwas mehr Performance nachgesagt wird. Weitere nennenswerte Unterschiede sind mir von den verschiedenen utf8_-Kodierungen nicht bekannt. Ein Spezialfall bildet allerdings utf8_bin, das die Vergleiche im Binär-Format durchführt.

Hinweis
Sollte euer verwendetes DBMS utf8mb4 unterstützen, wäre das die noch die bessere Wahl. Damit stehen euch bis zu 4 Bytes pro Character zur Verfügung, womit ein zusätzlicher Umfang an Character dargestellt werden kann. MySQL unterstützt utf8mb4 ab Version 5.3.3

Danke an @mermshaus für die Info: http://www.php-rocks.de/thema/143;777-re-utf-8-verschwoerung-ergaenzung.html#pid777



Sonderfälle
Aus diesem Tutorial solltet ihr mitnehmen, dass ihr immer mit der richtigen Kodierung arbeitet und zwar an jeder Stelle, an der ihr Einfluss darauf habt!
Es gibt allerdings Situationen, in denen man vielleicht keinen Einfluss auf die Daten-Kollation hat. Bspw. bei einer Datenbank-Migration aus einer alten Datenbank in eine neue. Die alte Datenbank hält die Daten nicht in UTF-8 vor und ihr müsst diese zu UTF-8 in die neue übertragen. Hier wäre bspw. die PHP-Funktion utf8_encode() oder mb_convert_encoding() zu verwenden.

Hinweis
Vielleicht ist dem einen oder anderen bereits aufgefallen, dass auf Datenbank- und Datenbankverbindungs-Ebene grundsätzlich utf8 und in allen anderen Kontexten utf-8 verwendet wird. Wer sich daran hält, spart sich manche Fehlersuche...


Gehe zu: