Jak ustawić nagłówek HTTP na UTF-8 za pomocą PHP, który jest poprawny w walidatorze W3C?

319

Mam kilka stron PHP odbijających różne rzeczy na stronach HTML z następującym kodem.

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

Jednak gdy sprawdzam poprawność za pomocą walidatora W3C , pojawia się:

Kodowanie znaków określone w nagłówku HTTP (iso-8859-1) różni się od wartości w elemencie (utf-8).

Jestem całkiem nowy w PHP i zastanawiałem się, czy mogę i powinienem zmienić nagłówek plików PHP, aby pasował do plików HTML.

manycheese
źródło

Odpowiedzi:

897

Służy headerdo modyfikowania nagłówka HTTP:

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

Uwaga, aby wywołać tę funkcję, zanim jakiekolwiek dane wyjściowe zostaną wysłane do klienta. W przeciwnym razie nagłówek również został wysłany i oczywiście nie możesz go już zmienić. Możesz to sprawdzić za pomocą headers_sent. Aby uzyskać więcej informacji, zobacz stronę podręcznikaheader .

Gumbo
źródło
4
Dodałbym tylko, że gdy poprawnie ustawisz nagłówek HTTP w ten sposób, nie potrzebujesz już <meta>tagu.
Jon
3
@Jon: Użyłbym obu. Odpowiednik HTTP METAjest używany, gdy dokument HTML nie jest ładowany przez HTTP (np. Z dysku).
Gumbo,
6
Działa to tylko wtedy, gdy wykonujesz php, aby to zrobić dla stron statycznych, powinieneś zapisać plik HTML jako utf-8. Spowoduje to dodanie znaku BOM utf-8 zakodowanego na początku pliku. bajty 0xEF, 0xBB, 0xBF dodane na początku pliku. Większość serwerów WWW to zauważy i zastosuje odpowiedni nagłówek. W rzeczywistości zapisanie pliku php jako utf-8 osiągnęłoby to samo.
Rahly,
1
@Jeremy Walton: Dodanie BOM UTF-8 niekoniecznie się zdarza. W rzeczywistości nie jest to nawet konieczne dla UTF-8, ponieważ ma tylko jedną kolejność bajtów (ale może być użyte do identyfikacji UTF-8).
Gumbo,
1
@Gumbo: jasne, upraszczam tutaj i skupiam się na jak najczęstszym scenariuszu internetowym (pytanie dotyczy tego scenariusza). Biorąc pod uwagę pozorny poziom pytania, po co coś robić, skoro nawet nie rozumiesz, jakie korzyści może kiedyś przynieść?
Jon
32

Najpierw upewnij się, że same pliki PHP są zakodowane w UTF-8 .

Meta tag jest ignorowany przez niektóre przeglądarki. Jeśli używasz tylko znaków ASCII, to i tak nie ma znaczenia.

http://en.wikipedia.org/wiki/List_of_HTTP_header_fields

header('Content-Type: text/html; charset=utf-8');
KingCrunch
źródło
15

Jest to problem z tym, że serwer WWW wysyła nagłówek HTTP, który nie jest zgodny z tym, który zdefiniowałeś. Aby uzyskać instrukcje, jak zmusić serwer do wysyłania poprawnych nagłówków, zobacz tę stronę .

W przeciwnym razie możesz także użyć PHP do modyfikacji nagłówków, ale należy to zrobić przed wypisaniem dowolnego tekstu za pomocą tego kodu:

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

Więcej informacji na temat wysyłania nagłówków za pomocą PHP można znaleźć w dokumentacji funkcji nagłówka .

EdoDodo
źródło
12

Możesz także użyć krótszego sposobu:

<?php header('Content-Type: charset=utf-8'); ?>

Zobacz RFC 2616 . Można podać tylko zestaw znaków.

Jason OOO
źródło
Podoba mi się ta opcja, ponieważ (zakładam, że pozwoli ci to ustawić osobno inną część typu zawartości (na przykład, masz jakieś strony tekstowe / zwykłe i niektóre strony tekstowe / html, ale wszystkie są UTF8). Czy moje rozumowanie jest prawidłowe?
Eric Seastrand
1
Nie mogę znaleźć tej części RFC 2616, która mówi, że można tak określić. Content-Type = "Content-Type" ":" media-typeimedia-type = type "/" subtype *( ";" parameter )
AI0867
1
Podanie tylko zestawu znaków nie jest poprawne. Nie jest zgodny z RFC 2616 (który jest zresztą przestarzały) ani z RFC 7231 (który nie jest przestarzały) ani z żadnym innym RFC. Zobacz stackoverflow.com/questions/41994062/…
sidehowbarker
10

Aby uzyskać poprawną implementację, musisz zmienić szereg rzeczy.

Baza danych (bezpośrednio po połączeniu):

mysql_query("SET NAMES utf8");

// Meta tag HTML (probably it's already set): 
meta charset="utf-8"
header php (before any output of the HTML):
header('Content-Type: text/html; charset=utf-8')
table-rows-charset (for each row):
utf8_unicode_ci
UnChien Andalou
źródło
4
Koalicja bazy danych nie wpływa na dane wyjściowe generowane przez PHP, ponieważ dane są kodowane do natywnego formatu skonfigurowanego do użycia z PHP, zanim zostaną one zwrócone użytkownikowi. Po drugie, OP nie wspomniał, że używa MySQL. Po trzecie, MyISAM jest przestarzały i nie powinien być zalecany, chyba że wiesz, co robisz. Istnieje powód, dla którego InnoDB stało się nowym domyślnym.
EWit,
wreszcie pełna lista wszystkich miejsc do ustawienia kodowania znaków.
Filip Overtone Piosenkarz Rydlo
mysql_query („SET NAMES utf8”); zanim moje wybrane zapytanie naprawiło problem. dzięki :)
Deepak Goswami
7

PHP automatycznie wysyła nagłówki, jeśli jest skonfigurowane do korzystania z wewnętrznego kodowania:

ini_set('default_charset', 'utf-8');
Nikl
źródło