Home > Programowanie, Webmastering > Kodowanie polskich znaków w PHP

Kodowanie polskich znaków w PHP

Prawdziwym problemem dla początkujących programistów PHP, może być nie rzadko brak wyświetlania polskich znaków w skryptach PHP. Zamiast miotać się pomiędzy różnymi edytorami kodu, które w taki czy inny sposób oferują zmianę kodowania pliku, prześledźmy po kolei wszystkie etapy tej przypadłości i rozwiążmy je raz na zawsze.

Przyczyny mogą być różne, od błędnego zapisania pliku, aż po wymuszone kodowanie znaków w nagłówku HTTP. Jeśli spotkałeś się nie raz z popularnymi krzakami na swojej stronie, zamiast polskich znaków diakrytycznych, to zapraszam do przeczytania dalszej części wpisu.

Po pierwsze musimy zdecydować się na jakiś system kodowania znaków, których używamy w tworzonych plikach. W moim przypadku będzie to, obecnie najpopularniejszy, system utf-8. Nic nie stoi przeszkodzie aby używać chociażby iso-8859-2, jednakże utf-8 oferuje nam znacznie szerszy zestaw znaków i jest obsługiwany obecnie przez coraz więcej systemów docelowych (np.: przeglądarki mobilne).

Edytor

Zacznijmy od edytora w jakim tworzymy nasz skrypt. Początkowo jest to zapewne systemowy notatnik. Program ten, o ile nie wybierzemy inaczej, domyślnie zapisuje pliki w kodowaniu windows-1250. Kodowanie to obsługiwane jest wyłącznie na systemach firmy Microsoft i należy go unikać jak ognia na dzień dzisiejszy. Podczas zapisywania pliku, mamy możliwość zmiany na utf-8 na dole okna dialogowego – pole wyboru Kodowanie.

Osobiście, polecam korzystanie z narzędzi o większych możliwościach, takich jak środowiska NetBeans czy Eclipse. Mogą one wyglądać skomplikowanie dla początkującego programisty, jednakże oferują gamę udogodnień i przydatnych funkcji.

Sekcja meta

Przypuśćmy że mamy już poprawnie zapisany plik w wybranym przez nas systemie kodowania znaków. Uruchamiamy skrypt na lokalnym bądź wirtualnym serwerze a naszym oczom ukazują się znaczki o nieznanym dla nas pochodzeniu, które na pewno nie są naszymi rodzimymi ogonkami.

Drugim, często popełnianym błędem, jest brak sekcji meta strony, informującej o jej kodowaniu. Aby poprawnie zdefiniować kodowanie dokumentu HTML, używamy następującego zapisu:

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

…który umieszczamy między znacznikami <head></head>. Przykładowo:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <title>Moja strona w utf-8</title>
  </head>
  <body>
    <p>...</p>
  </body>
</html>

Co jednak zrobić jeśli wciąż nie otrzymujemy oczekiwanego efektu?

Nagłówek HTTP

Nagłówek protokołu HTTP zawiera szereg informacji przesyłanych do przeglądarki, mówiący o tym co tak właściwie jest wysyłane. Jedną z tych informacji jest kodowanie znaków dokumentu – znowu.

Problem polega na tym, iż przeglądarki wyświetlają stronę w takim kodowaniu, jakie zostało im przedstawione w nagłówku protokołu. W praktyce to co zostało zdefiniowane w sekcji meta strony nie ma znaczenia, chyba że nagłówek HTTP nie zawiera takiej informacji.

Bardzo często, parser PHP ma wymuszone wysyłanie dokumentów w jednym, określonym systemie kodowania znaków. Odpowiada za to następujący wpis w pliku konfiguracji php.ini:

default_charset = "iso-8859-1"

O ile dysponujemy własnym, lokalnie postawionym serwerem, możemy łatwo edytować bądź całkowicie wyłączyć tą linię, to w przypadku serwera wirtualnego z reguły nie posiadamy takiej władzy.

W takim wypadku musimy nadpisać sami nagłówek HTTP w skrypcie PHP. Służy do tego polecenie header. Nas interesuje oczywiście zmiana samego kodowania, inne możliwości tej komendy na razie zostawmy w spokoju. Dodajemy zatem do naszego skryptu następującą linię:

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

Nie mniej musimy pamiętać o tym, że ustawienie parametru nagłówka HTTP przy pomocy w/w komendy, musi nastąpić zanim wyślemy jakiekolwiek inne dane do przeglądarki. Innymi słowy, nie może użyć polecenia echo czy też print zanim nie ustawimy nagłówka. Jak sama nazwa wskazuje, jest to nagłówek, czyli znajduje się przed docelową treścią dokumentu.

Podsumowanie

Mój docelowy plik, jaki stworzyłem na potrzeby tego wpisu, prezentuje się następująco:

<?php header('Content-Type: text/html; charset=utf-8'); ?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <title>Moja strona w utf-8</title>
  </head>
  <body>
    <p><?php echo 'ęóąśłżźćń'; ?></p>
  </body>
</html>

Jak widzimy, wymusiliśmy tutaj kodowanie utf-8 w nagłówku HTTP, sekcji meta, oraz sam plik został zapisany z poprawnym kodowaniem znaków. Tak przygotowany dokument, nie powinien sprawiać żadnych problemów w dowolnej konfiguracji serwera. W efekcie otrzymamy poprawnie zakodowane oraz wyświetlone polskie znaki diakrytyczne.

  1. 27 grudnia 2009 at 22:11 | #1

    Ciekawy artykuł. Warto nadmienić że problem z kodowaniem zaczyna się robić gdy korzystamy z kilku źródeł danych: uwierzytelnianie w LDAP’ie (AD), więcej niż jedna baza danych (np oracle + mysql), dodatkowo każde ze źródeł danych posiada inne kodowanie. Zaczyna się wtedy przysłowiowe rzeźbienie – funkcja iconv nie wystarcza (nieprawidłowo zmienia niektóre polskie znaki), a nie mamy zainstalowanego modułu mb_string (Multibyte string). Warto uzupełnić artykuł o powyższe informację gdyż może się to przydać zarówno początkującym jak i zaawansowanym web deweloperom.

  2. 28 grudnia 2009 at 11:40 | #2

    Przy pobieraniu danych z baz, np: MySQL faktycznie czasami też zaczynają się schody, gdzie mamy inny kodowanie składowania danych, inne porównywania ciągów i jeszcze inne samego połączenia z bazą.

  3. 28 grudnia 2009 at 19:24 | #3

    Czy przewidujesz jakiś mały artykuł o systemach kontroli wersji SVN itd…., od korzystania z konsoli po nakładki graficzne. Z chęcią bym się z taką rzeczą zapoznał.

  4. 28 grudnia 2009 at 20:12 | #4

    Ogólnie rzecz biorąc – TAK, ale nie wiem kiedy :) .

  1. Brak jeszcze trackbacków