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.