¿Cómo configurar el encabezado HTTP a UTF-8 usando PHP que es válido en el validador W3C?

319

Tengo varias páginas PHP haciendo eco de varias cosas en páginas HTML con el siguiente código.

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

Sin embargo, cuando valido usando el validador W3C aparece:

La codificación de caracteres especificada en el encabezado HTTP (iso-8859-1) es diferente del valor en el elemento (utf-8).

Soy bastante nuevo en PHP, y me preguntaba si podría y debería cambiar el encabezado de los archivos PHP para que coincida con los archivos HTML.

muchos quesos
fuente

Respuestas:

897

Use headerpara modificar el encabezado HTTP:

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

Tenga en cuenta que debe llamar a esta función antes de enviar cualquier salida al cliente. De lo contrario, el encabezado también se ha enviado y, obviamente, ya no puede cambiarlo. Puedes verificar eso con headers_sent. Consulte la página del manual deheader para obtener más información.

Gumbo
fuente
44
Solo agregaría que cuando configura el encabezado HTTP correctamente de esta manera, ya no necesita la <meta>etiqueta.
Jon
3
@ Jon: usaría ambos. El equivalente de HTTP METAse utiliza cuando el documento HTML no se carga a través de HTTP (por ejemplo, desde el disco).
Gumbo
66
Esto solo funcionará si está ejecutando php, para hacerlo para páginas estáticas, debe guardar su archivo html AS utf-8. Al hacerlo, se agregará el carácter BOM utf-8 codificado al comienzo del archivo. bytes 0xEF, 0xBB, 0xBF agregados al comienzo del archivo. La mayoría de los servidores web lo notarán y aplicarán el encabezado apropiado. De hecho, guardar su archivo php como utf-8 lograría lo mismo.
Rahly
1
@ Jeremy Walton: Que se agregue la lista de materiales UTF-8 no sucede necesariamente. De hecho, ni siquiera es necesario para UTF-8 ya que solo tiene un orden de bytes (pero podría usarse para identificar UTF-8).
Gumbo
1
@Gumbo: claro, estoy simplificando aquí y apuntando al escenario web más común (la pregunta parece hablar sobre este escenario). Teniendo en cuenta el nivel aparente de la pregunta, ¿por qué hacer algo cuando ni siquiera comprende cuáles son las ventajas que algún día puede ofrecer?
Jon
15

Este es un problema con su servidor web que envía un encabezado HTTP que no coincide con el que usted define. Para obtener instrucciones sobre cómo hacer que el servidor envíe los encabezados correctos, consulte esta página .

De lo contrario, también puede usar PHP para modificar los encabezados, pero esto debe hacerse antes de generar cualquier texto con este código:

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

Puede encontrar más información sobre cómo enviar encabezados utilizando PHP en la documentación de la función de encabezado .

EdoDodo
fuente
12

También puedes usar una forma más corta:

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

Ver RFC 2616 . Es válido especificar solo un conjunto de caracteres.

Jason OOO
fuente
Me gusta esta opción, porque (supongo) le permitiría configurar la otra parte del tipo de contenido por separado (por ejemplo, tiene algunas páginas de texto / sin formato y algunas páginas de texto / html, pero todas son UTF8). ¿Es correcto mi entendimiento?
Eric Seastrand
1
No puedo encontrar la parte de RFC 2616 que dice que es válido especificar de esa manera. Content-Type = "Content-Type" ":" media-typeymedia-type = type "/" subtype *( ";" parameter )
AI0867
1
No es válido solo especificar el juego de caracteres. No es válido por RFC 2616 (que de todos modos está obsoleto) ni por RFC 7231 (que no está obsoleto) ni por ningún otro RFC. Ver stackoverflow.com/questions/41994062/…
sideshowbarker
10

Para una implementación correcta, debe cambiar una serie de cosas.

Base de datos (inmediatamente después de la conexión):

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
fuente
44
La coalición de la base de datos no influye en la salida generada por PHP porque los datos están codificados en el formato nativo configurado para su uso con PHP antes de que sea devuelto al usuario. En segundo lugar, OP no ha mencionado que está usando MySQL. En tercer lugar, MyISAM está desactualizado y no debe recomendarse a menos que sepa lo que está haciendo. Hay una razón por la que InnoDB se convirtió en el nuevo valor predeterminado.
EWit
finalmente una lista completa de todos los lugares para configurar la codificación de caracteres.
Filip OvertoneSinger Rydlo
mysql_query ("SET NOMBRES utf8"); antes de que mi consulta de selección solucionara el problema por mí. gracias :)
Deepak Goswami
7

PHP envía encabezados automáticamente si está configurado para usar codificación interna:

ini_set('default_charset', 'utf-8');
Nikl
fuente