Estoy configurando un nuevo servidor y quiero admitir UTF-8 completamente en mi aplicación web. He intentado esto en el pasado en servidores existentes y siempre parece que tengo que recurrir a ISO-8859-1.
¿Dónde exactamente necesito configurar la codificación / charsets? Soy consciente de que necesito configurar Apache, MySQL y PHP para hacer esto: ¿hay alguna lista de verificación estándar que pueda seguir, o tal vez solucionar problemas donde ocurren las discrepancias?
Esto es para un nuevo servidor Linux, que ejecuta MySQL 5, PHP, 5 y Apache 2.
utf-8
para cada uno de ellos por separado: MySQL 5, PHP 5 O Apache 2.Respuestas:
Almacenamiento de datos :
Especifique el
utf8mb4
conjunto de caracteres en todas las tablas y columnas de texto en su base de datos. Esto hace que MySQL almacene y recupere físicamente valores codificados de forma nativa en UTF-8. Tenga en cuenta que MySQL utilizará implícitamente lautf8mb4
codificación siutf8mb4_*
se especifica una intercalación (sin ningún conjunto de caracteres explícito).En versiones anteriores de MySQL (<5.5.3), desafortunadamente se verá obligado a usar simplemente
utf8
, que solo admite un subconjunto de caracteres Unicode. Desearía estar bromeando.Acceso a datos :
En el código de su aplicación (por ejemplo, PHP), en cualquier método de acceso a base de datos que utilice, deberá configurar el conjunto de caracteres de conexión
utf8mb4
. De esta manera, MySQL no realiza conversión desde su UTF-8 nativo cuando transfiere datos a su aplicación y viceversa.Algunos controladores proporcionan su propio mecanismo para configurar el juego de caracteres de conexión, que actualiza su propio estado interno e informa a MySQL de la codificación que se utilizará en la conexión; este suele ser el enfoque preferido. En PHP:
Si está utilizando la capa de abstracción PDO con PHP ≥ 5.3.6, puede especificar
charset
en el DSN :Si está usando mysqli , puede llamar a
set_charset()
:Si está atrapado con mysql simple pero está ejecutando PHP ≥ 5.2.3, puede llamar
mysql_set_charset
.Si el controlador no proporciona su propio mecanismo para configurar el conjunto de caracteres de la conexión, es posible que deba realizar una consulta para decirle a MySQL cómo su aplicación espera que se codifiquen los datos de la conexión:
SET NAMES 'utf8mb4'
.La misma consideración con respecto a
utf8mb4
/utf8
aplica como anteriormente.Salida :
Si su aplicación transmite texto a otros sistemas, también deberán ser informados de la codificación de caracteres. Con las aplicaciones web, el navegador debe ser informado de la codificación en la que se envían los datos (a través de encabezados de respuesta HTTP o metadatos HTML ).
En PHP, puede usar la
default_charset
opción php.ini o emitir manualmenteContent-Type
encabezado MIME usted mismo, que es más trabajo pero tiene el mismo efecto.Al codificar la salida usando
json_encode()
, agregueJSON_UNESCAPED_UNICODE
como segundo parámetro.Entrada :
Desafortunadamente, debe verificar que cada cadena recibida sea UTF-8 válida antes de intentar almacenarla o usarla en cualquier lugar. PHP
mb_check_encoding()
hace el truco, pero tienes que usarlo religiosamente. Realmente no hay forma de evitar esto, ya que los clientes maliciosos pueden enviar datos en cualquier codificación que deseen, y no he encontrado un truco para que PHP haga esto por usted de manera confiable.Según mi lectura de la especificación HTML actual , las siguientes viñetas secundarias ya no son necesarias o incluso válidas para HTML moderno. Entiendo que los navegadores trabajarán y enviarán datos en el conjunto de caracteres especificado para el documento. Sin embargo, si está apuntando a versiones anteriores de HTML (XHTML, HTML4, etc.), estos puntos pueden ser útiles:
accept-charset
atributo a todas sus<form>
etiquetas:<form ... accept-charset="UTF-8">
.<form>
etiqueta.Otras consideraciones de código :
Obviamente, todos los archivos que servirá (PHP, HTML, JavaScript, etc.) deben estar codificados en UTF-8 válido.
Debe asegurarse de que cada vez que procese una cadena UTF-8, lo haga de manera segura. Esta es, desafortunadamente, la parte difícil. Probablemente querrás hacer un uso extensivo de la
mbstring
extensión de PHP .Las operaciones de cadena incorporadas de PHP no son por defecto seguras para UTF-8. Hay algunas cosas que puede hacer con seguridad con las operaciones normales de cadenas PHP (como la concatenación), pero para la mayoría de las cosas debe usar la
mbstring
función equivalente .Para saber lo que está haciendo (lea: no lo estropee), realmente necesita saber UTF-8 y cómo funciona en el nivel más bajo posible. Consulte cualquiera de los enlaces de utf8.com para obtener algunos buenos recursos para aprender todo lo que necesita saber.
fuente
Me gustaría agregar una cosa a la excelente respuesta de chazomaticus :
No olvide tampoco la etiqueta META (como esta, o la versión HTML4 o XHTML de la misma ):
Eso parece trivial, pero IE7 me ha dado problemas con eso antes.
Estaba haciendo todo bien; la base de datos, la conexión de la base de datos y el encabezado HTTP Content-Type se configuraron en UTF-8, y funcionó bien en todos los demás navegadores, pero Internet Explorer aún insistió en usar la codificación "Europa occidental".
Resultó que a la página le faltaba la etiqueta META. Agregar eso resolvió el problema.
Editar:
El W3C en realidad tiene una sección bastante grande dedicada a I18N . Tienen una serie de artículos relacionados con este problema, que describen el lado HTTP, (X) HTML y CSS de las cosas:
Recomiendan usar el encabezado HTTP y la metaetiqueta HTML (o la declaración XML en caso de que XHTML sirva como XML).
fuente
Además de configurar
default_charset
en php.ini, puede enviar el juego de caracteres correcto utilizandoheader()
desde su código, antes de cualquier salida:Trabajar con Unicode en PHP es fácil siempre y cuando se dé cuenta de que la mayoría de las funciones de cadena no funcionan con Unicode, y algunas podrían alterar completamente las cadenas . PHP considera que los "caracteres" tienen 1 byte de longitud. A veces esto está bien (por ejemplo,
explode()
solo busca una secuencia de bytes y la usa como separador, por lo que no importa qué caracteres reales busque). Pero otras veces, cuando la función está diseñada para funcionar en caracteres , PHP no tiene idea de que su texto tiene caracteres de varios bytes que se encuentran con Unicode.Una buena biblioteca para registrarse es phputf8 . Esto reescribe todas las funciones "malas" para que pueda trabajar con seguridad en cadenas UTF8. Hay extensiones como la extensión mbstring que también intentan hacer esto por usted, pero prefiero usar la biblioteca porque es más portátil (pero escribo productos de mercado masivo, así que eso es importante para mí). Pero phputf8 puede usar mbstring detrás de escena, de todos modos, para aumentar el rendimiento.
fuente
Encontré un problema con alguien que usa PDO y la respuesta fue usar esto para la cadena de conexión PDO:
El sitio del que saqué esto está caído, pero por suerte pude obtenerlo usando el caché de Google.
fuente
$dbh->exec("set names utf8");
método separado ; prefiero el método presentado aquí). Por cierto. También hay una nota similar sobre esto como un comentario en el manual de PHP: php.net/manual/en/pdo.construct.php#96325 .En mi caso, estaba usando
mb_split
, que usa expresiones regulares. Por lo tanto, también tuve que asegurarme manualmente de que la codificación regex era utf-8 haciendomb_regex_encoding('UTF-8');
Como nota al margen, también descubrí al ejecutar
mb_internal_encoding()
que la codificación interna no era utf-8, y cambié eso al ejecutarmb_internal_encoding("UTF-8");
.fuente
En primer lugar, si está en <5.3PHP, entonces no. Tienes muchos problemas que abordar.
Me sorprende que ninguno haya mencionado la biblioteca intl , la que tiene un buen soporte para unicode , grafemas , operaciones de cadenas , localización y muchos más, ver a continuación.
Citaré alguna información sobre el soporte Unicode en PHP por las diapositivas de Elizabeth Smith en PHPBenelux'14
INTL
Bueno:
Malo:
mb_string
ICONV
stream_filter_append($fp, 'convert.iconv.ISO-2022-JP/EUC-JP')
BASES DE DATOS
Algunas otras Gotchas
Actualizaré esta respuesta en caso de que las cosas cambien las características agregadas, etc.
fuente
--with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd
opciones.Lo único que agregaría a estas sorprendentes respuestas es enfatizar en guardar sus archivos en la codificación utf8, he notado que los navegadores aceptan esta propiedad en lugar de configurar utf8 como codificación de código. Cualquier editor de texto decente le mostrará esto, por ejemplo, Notepad ++ tiene una opción de menú para encontrar archivos, le muestra la codificación actual y le permite cambiarla. Para todos mis archivos php, uso utf8 sin BOM.
Hace algún tiempo, alguien me pidió que agregara soporte utf8 para una aplicación php / mysql diseñada por otra persona, noté que todos los archivos estaban codificados en ANSI, así que tuve que usar ICONV para convertir todos los archivos, cambiar las tablas de la base de datos para usar el utf8 charset y utf8_general_ci intercalan, agregue 'SET NAMES utf8' a la capa de abstracción de la base de datos después de la conexión (si usa 5.3.6 o anterior, de lo contrario, debe usar charset = utf8 en la cadena de conexión) y cambiar las funciones de cadena para usar el multibyte php funciones de cadena equivalentes.
fuente
Recientemente descubrí que el uso
strtolower()
puede causar problemas donde los datos se truncan después de un carácter especial.La solución fue usar
fuente
Acabo de pasar por el mismo problema y encontré una buena solución en los manuales de PHP.
Cambié toda mi codificación de archivo a UTF8 y luego la codificación predeterminada en mi conexión. Esto resolvió todos los problemas.
Ver fuente
fuente
set_charset('utf8mb4')
no funcionó, pero>set_charset("utf8")
funcionó y eso no se mostró realmente en las otras respuestas.set_charset("utf8")
puede funcionar, pero se comportan de forma diferente (ver los comentarios acerca de la diferencia entreutf8
yutf8mb4
y el historial de versiones de MySQL). ¡Úseloutf8
si es necesario Y SOLO si sabe lo que está haciendo !En PHP, deberá utilizar las funciones multibyte o activar mbstring.func_overload . De esa manera, cosas como strlen funcionarán si tienes caracteres que toman más de un byte.
También deberá identificar el conjunto de caracteres de sus respuestas. Puede usar AddDefaultCharset, como se indicó anteriormente, o escribir código PHP que devuelva el encabezado. (O puede agregar una etiqueta META a sus documentos HTML).
fuente
El soporte Unicode en PHP sigue siendo un gran desastre. Si bien es capaz de convertir una cadena ISO8859 (que usa internamente) a utf8, carece de la capacidad de trabajar con cadenas unicode de forma nativa, lo que significa que todas las funciones de procesamiento de cadenas alterarán y dañarán sus cadenas. Por lo tanto, debe usar una biblioteca separada para el soporte utf8 adecuado o reescribir todas las funciones de manejo de cadenas usted mismo.
La parte fácil es solo especificar el conjunto de caracteres en los encabezados HTTP y en la base de datos, pero nada de eso importa si su código PHP no genera UTF8 válido. Esa es la parte difícil, y PHP prácticamente no te brinda ayuda allí. (Creo que se supone que PHP6 arregle lo peor de esto, pero aún falta un tiempo)
fuente
Si desea que el servidor MySQL decida el conjunto de caracteres, y no PHP como cliente (comportamiento anterior; preferido, en mi opinión), intente agregar
skip-character-set-client-handshake
a sumy.cnf
, debajo[mysqld]
y reiniciemysql
.Esto puede causar problemas en caso de que esté usando algo que no sea UTF8.
fuente
La mejor respuesta es excelente. Esto es lo que tenía que hacer en una configuración debian / php / mysql normal:
eso fue todo !
fuente
si desea una solución mysql, tuve problemas similares con 2 de mis proyectos, después de una migración del servidor. Después de buscar y probar muchas soluciones, encontré esta / nada antes de que esta funcionara):
¡Después de agregar esta línea a mi archivo de configuración, todo funciona bien!
Encontré esta solución https://www.w3schools.com/PHP/func_mysqli_set_charset.asp cuando buscaba resolver un inserto de la consulta html
¡buena suerte!
fuente
Solo una nota:
Se enfrentan al problema de los caracteres no latinos se muestra como
?????????
, hecho una pregunta, y se puso cerró con una referencia a esta cuestión canónica, que ha intentado todo y no importa lo que haces sigue recibiendo??????????
desdeMySQL
.Esto se debe principalmente a que está probando sus datos antiguos que se insertaron en la base de datos utilizando el juego de caracteres incorrecto y se convirtieron y almacenaron en los caracteres de signo de interrogación
?
. Lo que significa que perdió su texto original para siempre y no importa lo que intente, obtendrá???????
.Si aplica lo que ha aprendido de las respuestas de esta pregunta a datos nuevos, podría resolver su problema.
fuente
Tuve este problema al mostrar tablas. Acabo de poner esto en cada variable de salida de eco:
fuente