Pssst, ich verkaufe auch Templates!

Simon Stamm

Problematik

Wer kennt das Problem nicht? Man benutzt Umlaute in HTML/PHP-Dateien, verzichtet auf die HTML-Schreibweise (z.B. ä) und schon werden im Browser anstatt der Umlaute nur noch Fragezeichen angezeigt.

Um Probleme mit den Umlauten bei Ausgaben zu vermeiden, sollten alle Dateien in UTF-8 statt ANSI gespeichert werden. Dadurch werden die Umlaute zwar korrekt angezeigt, doch bringt das meist einige Probleme mit sich:

  • Die Zeichen ï»¿ erscheinen am Anfang.
  • Es wird eine leere/weiße Seite angezeigt.
  • Im Internet Explorer und ggf. anderen Browsern stimmt die Ausrichtung nicht mehr.
  • Einige JavaScript-Funktionen (besonders jQuery/Mootols-Effekte) funktionieren nicht.
  • Der BOM wird in einem HTML-Validator als Warnung angezeigt.

Wird in PHP z.B. mit der Funktion header() oder session_start() gearbeitet, kann es zu folgendem Fehler kommen:

Warning: session_start() [function.session-start]: Cannot send session cache limiter – headers already sent (output started at /var/www/example.php:1) in /var/www/example.php on line 1

Ursache

Der Grund für die Probleme ist, dass beim Speichern als UTF-8 am Anfang der Datei ein “Byte Order Mark” (kurz: BOM) geschrieben wird. Der BOM für UTF-8 lautet U+FEFF und ist drei Bytes groß – 0xEF, 0xBB und 0xBF. Die drei Bytes werden nach Windows-1252 als “” dargestellt. Für UTF-16 und UTF-32 wird das BOM für die Byte-Reihenfolge verwendet, welches bei UTF-8 nicht wirklich notwendig ist.

Leider interpretieren Browser bzw. PHP den BOM nicht richtig. Insbesondere PHP denkt, dass bereits eine Ausgabe stattgefunden hat, sodass es zu spät ist, den Header zu verändern. Der Fehler tritt bei ANSI nicht auf, weil dieser keinen BOM besitzt.

Lösung

Die Lösung ist einfach: Die Datei muss mit der Kodierung “UTF-8 ohne BOM” gespeichert werden.

Windows

Dies kann z.B. mit Notepad++ erledigt werden, indem man die Datei mit dem Editor öffnet und dann die Kodierung mittels Kodierung -> UTF8 ohne BOM erneut abspeichert.

UTF-8 ohne BOM in Notepad++

Linux

Eine elegante Lösung, um in einem Ordner alle PHP-Dateien (inkl. Unterordner) nach dem BOM zu durchsuchen und anschließend zu löschen, kann mittels der Bash erreicht werden.

find . -type f -iname "*.php" -exec sed '1s/^\xEF\xBB\xBF//' -i.bak {} \; -exec rm {}.bak \;

Möchte man nur die Dateien mit dem BOM aufspüren, kann dieser Einzeiler verwendet werden.

grep -rl $'\xEF\xBB\xBF' .

Natürlich geht das auch mit VIM.

# vim utf8_with_bom.php
:set nobomb
:wq

PHP

Das BOM kann auch mit PHP5 entfernt werden. Dadurch müssen die drei Bytes erkannt und gelöscht werden.

$str = file_get_contents('utf8_with_bom.php');
$bom = pack("CCC", 0xef, 0xbb, 0xbf);
if (0 == strncmp($str, $bom, 3)) {
	echo "BOM detected - file is UTF-8\n";
	$str = substr($str, 3);
}

PHP 6 wird Unicode Support erhalten, wodurch man sich nicht mehr mit diesem Problem rumärgern muss. Es wird korrekt mit PHP-Dateien, die das BOM beinhalten, umgehen können.

  • Daniel_aus_TUT

    Geschrieben: 30. November 2015


    Hi Simon,
    Danke für den Beitrag!!!!
    Ich hatte genau dieses Problem und bin fast verzweifelt: PHP hat dadurch die Session ID nicht angelegt.
    Jetzt funktioniert alles perfekt! :-)

    Gruss Daniel Antworten


    • Simon Stamm

      Geschrieben: 30. November 2015


      Schön, dass ich dir mit dem Beitrag helfen konnte, Daniel! :) Antworten


  • Peter

    Geschrieben: 7. März 2017


    Hi Simon,

    für Deinen Beitrag danke ich Dir herzlich!
    Seit mein Provider auf PHP 5.6 umgestellt hatte, fingen die Probleme auch auf meinen Webseiten an.
    Die Umstellung auf UTF-8 half schon - doch erst Dein Hinweis auf den BOM brachte die Erleuchtung!
    Danke nochmals!
    Herzliche Grüße
    Peter Antworten


    • Simon Stamm

      Geschrieben: 16. März 2017


      Hey Peter,



      mich freut sehr, dass ich dir mit dem Beitrag helfen konnte!



      Liebe Grüße

      Simon Antworten



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