Estoy configurando un nuevo servidor y quiero soportar UTF-8 completamente en mi aplicación web. He intentado esto en el pasado en los servidores existentes y siempre parecen terminar teniendo que caer de nuevo a ISO-8859-1.
¿Dónde tengo que establecer exactamente la codificación/conjuntos de caracteres? Soy consciente de que tengo que configurar Apache, MySQL y PHP para hacer esto - ¿hay alguna lista de verificación estándar que pueda seguir, o tal vez solucionar los problemas donde se producen los desajustes?
Esto es para un nuevo servidor Linux, corriendo MySQL 5, PHP, 5 y Apache 2.
**Almacenamiento de datos:
utf8mb4
en todas las tablas y columnas de texto de su base de datos. Esto hace que MySQL almacene y recupere físicamente valores codificados nativamente en UTF-8. Tenga en cuenta que MySQL utilizará implícitamente la codificación utf8mb4
si se especifica una colación utf8mb4_*
(sin ningún conjunto de caracteres explícito).utf8
, que sólo soporta un subconjunto de caracteres Unicode. Ojalá fuera una broma.
Acceso a los datos:utf8mb4
. De esta manera, MySQL no hace ninguna conversión de su UTF-8 nativo cuando entrega los datos a su aplicación y viceversa.charset
en el DSN:
$dbh = new PDO('mysql:charset=utf8mb4');set_charset()
:
$mysqli->set_charset('utf8mb4'); // estilo orientado a objetos
mysqli_set_charset($link, 'utf8mb4'); // estilo procedimentalmysql_set_charset
.SET NAMES 'utf8mb4'
.utf8mb4
/utf8
que la anterior.
Salida:default_charset
php.ini, o emitir manualmente la cabecera MIME Content-Type
usted mismo, lo cual es más trabajo pero tiene el mismo efecto.json_encode()
, añada JSON_UNESCAPED_UNICODE
como segundo parámetro.
Entrada:mb_check_encoding()
hace el truco, pero tiene que usarlo religiosamente. Realmente no hay manera de evitar esto, ya que los clientes maliciosos pueden enviar datos en cualquier codificación que quieran, y no he encontrado un truco para que PHP haga esto por usted de manera confiable.accept-charset
a todas tus etiquetas <form>
: <form ... accept-charset="UTF-8">
.
Sólo para HTML antes de HTML5: ten en cuenta que la especificación HTML del W3C dice que los clientes "deberían" enviar por defecto los formularios al servidor en el conjunto de caracteres que éste sirva, pero aparentemente esto es sólo una recomendación, de ahí la necesidad de ser explícito en cada etiqueta "form".
Otras consideraciones sobre el código:mbstring
de PHP.mbstring
.Además de establecer default_charset
en php.ini, puede enviar el conjunto de caracteres correcto utilizando header()
desde su código, antes de cualquier salida:
header('Content-Type: text/html; charset=utf-8');
Trabajar con Unicode en PHP es fácil siempre y cuando te des cuenta de que la mayoría de las funciones de cadena no funcionan con Unicode, y algunas pueden manipular las cadenas completamente. PHP considera que los "caracteres" tienen una longitud de 1 byte. A veces esto está bien (por ejemplo, explode()
sólo busca una secuencia de bytes y la usa como separador - así que no importa qué caracteres reales busque). Pero otras veces, cuando la función está realmente diseñada para trabajar con caracteres, PHP no tiene idea de que su texto tiene caracteres multibyte que se encuentran con Unicode.
Una buena biblioteca para revisar es phputf8. Esta reescribe todas las funciones "malas" para que pueda trabajar con seguridad en cadenas UTF8. Hay extensiones como la extensión mbstring que intentan hacer esto por usted, también, pero prefiero usar la biblioteca porque es más portable (pero escribo productos para el mercado masivo, así que eso es importante para mí). Pero phputf8 puede utilizar mbstring detrás de las escenas, de todos modos, para aumentar el rendimiento.
En PHP, tendrá que usar las funciones multibyte, o activar mbstring.func_overload. De esta forma, cosas como strlen funcionarán si tiene caracteres que ocupan más de un byte.
También tendrá que identificar el conjunto de caracteres de sus respuestas. Puede usar AddDefaultCharset, como arriba, o escribir código PHP que devuelva la cabecera. (O puede añadir una etiqueta META a sus documentos HTML).