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.

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 .


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


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 .


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.


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

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');
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.