Как установить HTTP-заголовок в UTF-8 с помощью PHP, который действует в валидаторе W3C?


319

У меня есть несколько страниц PHP, выводящих различные вещи в страницы HTML со следующим кодом.

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

Тем не менее, когда я проверяю с помощью валидатора W3C, возникает следующее:

Кодировка символов, указанная в заголовке HTTP (iso-8859-1), отличается от значения в элементе (utf-8).

Я новичок в PHP, и мне было интересно, могу ли я и должен ли изменить заголовок для файлов PHP, чтобы он соответствовал файлам HTML.

Ответы:


897

Используйте headerдля изменения заголовка HTTP:

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

Обратите внимание на вызов этой функции до того, как какой-либо вывод будет отправлен клиенту. В противном случае заголовок тоже был отправлен, и вы, очевидно, больше не можете его изменить. Вы можете проверить это с headers_sent. Смотрите страницу руководстваheader для получения дополнительной информации.


4
Я бы только добавил, что когда вы правильно устанавливаете HTTP-заголовок, этот <meta>тег вам больше не нужен .
— Джон

3
@Jon: я бы использовал оба. HTTP-эквивалент METAиспользуется, когда HTML-документ не загружается по HTTP (например, с диска).
— Гамбо

6
Это будет работать, только если вы выполняете php, чтобы сделать это для статических страниц, вы должны сохранить ваш html-файл AS utf-8. Это добавит символ спецификации utf-8, закодированный в начало файла. байты 0xEF, 0xBB, 0xBF добавлены в начало файла. Большинство веб-серверов заметят это и применят соответствующий заголовок. Фактически, сохранение вашего php-файла как utf-8 приведет к тому же самому.
— Рахли

1
@ Джереми Уолтон: То, что добавлена ​​спецификация UTF-8, не обязательно происходит. На самом деле, это даже не обязательно для UTF-8, поскольку он имеет только один порядок байтов (но его можно использовать для идентификации UTF-8).
— Гамбо

1
@Gumbo: конечно, я упрощаю и нацеливаюсь на наиболее распространенный веб-сценарий (вопрос, кажется, говорит об этом сценарии). Принимая во внимание очевидный уровень вопроса, зачем делать что-то, когда вы даже не понимаете, какие преимущества это может когда-нибудь дать?
— Джон


15

Эта проблема связана с тем, что ваш веб-сервер отправляет заголовок HTTP, который не соответствует указанному вами. Инструкции о том, как заставить сервер отправлять правильные заголовки, см. На этой странице .

В противном случае вы также можете использовать PHP для изменения заголовков, но это необходимо сделать перед выводом любого текста с использованием этого кода:

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

Дополнительную информацию о том, как отправлять заголовки с помощью PHP, можно найти в документации по функции заголовка .


12

Вы также можете использовать более короткий путь:

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

См. RFC 2616 . Допустимо указывать только набор символов.


Мне нравится эта опция, потому что (я предполагаю) она позволит вам установить другую часть типа контента отдельно (например, у вас есть несколько текстовых / простых страниц и несколько текстовых / html-страниц, но все они UTF8.) Правильно ли мое понимание?
— Эрик Сеастранд

1
Я не могу найти часть RFC 2616, которая говорит, что это правильно указывать таким образом. Content-Type = "Content-Type" ":" media-typeиmedia-type = type "/" subtype *( ";" parameter )
— AI0867

1
Недопустимо указывать только кодировку. Он не действителен ни для RFC 2616 (который в любом случае устарел), ни для RFC 7231 (который не устарел), ни для любого другого RFC. См stackoverflow.com/questions/41994062/...
— sideshowbarker

10

Для правильной реализации вам нужно изменить ряд вещей.

База данных (сразу после подключения):

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
Коалиция базы данных не влияет на выходные данные, сгенерированные PHP, поскольку данные кодируются в собственном формате, настроенном для использования с PHP, еще до того, как они будут возвращены пользователю. Во-вторых, OP не упомянул, что он использует MySQL. В-третьих, MyISAM устарел и его не рекомендуется рекомендовать, если вы не знаете, что делаете. Есть причина, по которой InnoDB стал новым значением по умолчанию.
— EWit

наконец полный список всех мест для установки кодировки символов.
— Филип ОбертонеСингер Ридло

mysql_query ("SET NAMES utf8"); до того, как мой запрос на выбор решил проблему для меня. спасибо :)
— Дипак Госвами

7

PHP отправляет заголовки автоматически, если настроено использование внутренней кодировки:

ini_set('default_charset', 'utf-8');
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.