jesteś w: Główna > PHP > Kodowanie UTF-8
Ostatnia aktualizacja tej strony: 2010-01-01, 21:01:08

UTF-8 i problemy w PHP oraz Flash - BOM (Byte Order Mark)

Ale o co chodzi z tym BOM?

Problem 1: przy kodowaniu stron w UTF-8 i dołączaniu ich do innego dokumentu przy pomocy PHP (np. instrukcją include, require lub porzez wczytywanie pliku fopen()) pojawia się pusta linia lub ciąg dziwnych znaków. Często usługa walidacyjna XHTML pokazuje komunikat, że dana linia nie może być odczytana.

Problem 2: plik tekstowy utworzony w PHP i wczytany do Flasha nie jest pokazywany poprawnie - brak polskich liter.

Problem 3: plik PHP w kodowaniu UTF8 nie działą poprawnie z funkcjami session_start() czy header(). Błąd "Headers alrready sent".

Rozwiązanie problemów z BOM

Wszystkie problemy są spowodowane przez budowę pliku zakodowanego w UTF. Ja kodowałem UTF-8. Plik zakodowany w ten sposób może (ale nie musi) zawierać nagłówek "Byte Order Mark" czyli BOM. W przypadku UTF-8 są to trzy znaki o wartościach ef bb bf, co jest zupełnie nieistotne. Istotne jest to, że znaki są trzy.

Problem 1: dodatkowe znaki w załaczonym pliku PHP

Problem pierwszy wynika z tego, że większość przeglądarek nie interpretuje poprawnie tych znaków i chociaż widnieją one w źródle strony to na ekranie ich nie widać. Rozwiązaniem jest używanie edytora, który nie dodaje tego nagłówka (np. SciTE, z ustawioną opcją zapisu "UTF-8 cookie").

Problem 2: Flash i polskie litery

Drugi problem jest ciut trudniejszy do rozwiązania. Wydaje się, że flash wymaga nagłówka BOM, ale PHP tworząc plik tekstowy go nie dodaje (chociaż jeśli zmienne zostaną przesłane z Flasha do PHP i dopiero zostanie stworzony plik tekstowy to wszystko działa). Wyjściem jest zastosowanie takiego tricku, który przekonweruje wcześniej podane znaki ef bb bf na ciąg ASCII i zapisze do pliku.

<?php
$doPliku = "tekst, który ma być w pliku i zażółcić gęślą jaźń";
$doPliku = chr(hexdec('EF')).chr(hexdec('BB')).chr(hexdec('BF')) . $doPliku; //dodaj BOM

$file=fopen("plik.txt", "w");
fwrite($file, $doPliku);
fclose($file);
?>

To, że plik zawiera trzy dodatkowe znaki łatwo sprawdzić. Wystarczy utworzyć w notatniku i zapisać jako UTF-8 plik bom.txt z krótką treścią:

<php 
//plik bom.txt zawiera treść "x"
$tmp=file_get_contents("bom.txt");
echo strlen($tmp);
//strlen zwraca ilość znaków w ciągu
//ponieważ plik ma tylko literkę "x" strlen powinno zwrócić 1
//tymczasem zwraca 4
?>

lub utworzyć plik z treścią zerową i sprawdzić jego rozmiar.

Drugi sposób można także wykorzystać do załączania dokumentów do stron PHP (zamiast przez np. include) - wystarczy załadować plik do zmiennej, wyrzucić pierwsze trzy znaki i zrobić "echo $zmienna".

roblem 3: PHP, BOM, headers already sent

Błąd "Headers already sent" pojawia się gdy próbujemy użyć funkcji header() lub session_start() po wysłaniu treści do przeglądarki. Tych funkcji nie można użyć jeśli przed nimi była wyświetlona dowolna treść, na przykład użyto funkcji print() czy użyto jakiegoś tekstu (choćby spacji czy znaku nowej linii czyli "entera") przed znacznikiem <?php rozpoczynającym kod PHP. Jeśli chcemy użyć tych funkcji plik php musi zaczynać się od znacznika <?php. Niestety, kiedy mamy plik kodowany w UTF8 edytor może dodać BOM. Problem polega na tym, ze BOM jest w edytorze niewidzialny i możemy przegapić, ze został dodany. Jeśli tak się stało to znacznik BOM zostanie wysłany do przeglądarki przez rozpoczęciem interpretacji kodu PHP i zostanie zwrócony właśnie błąd "Headers already sent". Żeby usunąć bom, uzyj edytora który pozwala zapisać plik bez niego (np. wspomniany wcześniej SciTe).

Więcej o BOM

Znaki ef bb bf występują w pliku zakodowanym w UTF-8. Żeby było śmieszniej inne kodowania UTF mają inny BOM. Zobacz BOM dla innych kodowań niż UTF-8 w Wikipedii.

RemoveBOM_utf8()

string removeBOM_utf8(string);

Pozwoliłem sobie popełnić taką małą funkcję, która obcina z początku stringu BOM (jeśli takowy występuje)

function removeBOM_utf8($s){
if(substr($s,0,3)==chr(hexdec('EF')).chr(hexdec('BB')).chr(hexdec('BF'))){
return substr($s,3);
}else{
return $s;
}
}

Menu

Działy:

Quick start:

Inne:

animacje Flash

Diablo 2: