Как установить 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.

manycheese
источник

Ответы:

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, можно найти в документации по функции заголовка .

EdoDodo
источник
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
UnChien Andalou
источник
4
Коалиция базы данных не влияет на выходные данные, сгенерированные PHP, поскольку данные кодируются в собственном формате, настроенном для использования с PHP, еще до того, как они будут возвращены пользователю. Во-вторых, OP не упомянул, что он использует MySQL. В-третьих, MyISAM устарел и его не рекомендуется рекомендовать, если вы не знаете, что делаете. Есть причина, по которой InnoDB стал новым значением по умолчанию.
EWit
наконец полный список всех мест для установки кодировки символов.
Филип ОбертонеСингер Ридло
mysql_query ("SET NAMES utf8"); до того, как мой запрос на выбор решил проблему для меня. спасибо :)
Дипак Госвами
7

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

ini_set('default_charset', 'utf-8');
Nikl
источник