mysqli_set_charset - Resolución de codificación de caracteres incorrecta al mostrar los resultados de la base de datos MySQL después de la actualización a PHP 5.3
utf8 php sql (3)
descripcion del problema
Después de actualizar PHP en nuestro servidor de desarrollo de 5.2 a 5.3, nos encontramos con un problema donde los datos solicitados desde nuestra base de datos y mostrados en una página web se muestran con una codificación incorrecta cuando se intenta mostrar caracteres rusos.
Ambiente
- SO Dev: Debian GNU / Linux 6.0
- Dev PHP: 5.3.5-0.dotdeb.1
- Live MySQL: Distrib 5.1.49
Detalles
En PHP 5.3, la biblioteca cliente predeterminada para interactuar con las bases de datos MySQL cambió de libmysql a mysqlnd , lo que parece ser la causa del problema que estamos enfrentando.
Nos estamos conectando a la base de datos con el siguiente código:
$conn = mysql_pconnect(''database.hostname'', ''database_user'', ''database_password'');
$mysql_select_db(''database'', $conn);
Los datos almacenados en nuestra base de datos están codificados con codificación UTF-8. Al conectarse a la base de datos a través del cliente de línea de comandos y al ejecutar consultas, se confirma que los datos están intactos y codificados correctamente. Sin embargo, cuando consultamos la base de datos en PHP y tratamos de mostrar exactamente los mismos datos, se confunde. En este caso específico, estamos intentando mostrar caracteres rusos y el resultado es caracteres no ingleses, no rusos:
Los encabezados de respuesta que recibimos confirman que el tipo de contenido es UTF-8:
Probamos las cadenas antes de mostrarlas con mb_detect_encoding en modo estricto y mb_check_encoding y nos dijeron que la cadena era una cadena UTF-8 antes de mostrarla. También usamos mysql_client_encoding para probar la codificación del cliente y también indica que el conjunto de caracteres es UTF-8.
Al realizar una investigación, descubrimos algunas sugerencias para tratar de solucionar este problema:
header("Content-type: text/html; charset=utf-8");
mysql_set_charset(''utf8'');
mysql_query("SET SESSION character_set_results = ''UTF8''");
mysql_query(''SET NAMES UTF8'', $conn);
Incluso probamos utf8_encode :
utf8_encode($string);
Sin embargo, ninguna de estas soluciones funcionó.
Al quedar sin opciones, actualizamos MySQL en nuestro sistema de desarrollo a Distrib 5.1.55. Después de esa actualización, todo se mostró correctamente cuando nos conectamos a nuestra base de datos de desarrollo. Por supuesto, continúa mostrándose incorrectamente cuando nos conectamos a nuestra base de datos en vivo.
Idealmente, nos gustaría resolver este problema sin actualizar MySQL en nuestros servidores de producción a menos que podamos verificar el motivo exacto por el que esto no funciona y por qué la actualización lo solucionará. ¿Cómo podemos resolver este problema de codificación sin actualizar MySQL? Alternativamente, ¿por qué la actualización de MySQL soluciona el problema?
Si se ha asegurado de que tanto las tablas como la codificación de salida sean UTF-8, casi lo único que queda es la codificación de la conexión.
El motivo del cambio de comportamiento al actualizar los servidores podría ser un cambio en la codificación de conexión predeterminada:
[mysql]
default-character-set=utf8
Sin embargo, no puedo ver ningún cambio en la codificación predeterminada entre versiones, por lo que si se tratara de instalaciones completamente nuevas, no puedo ver que eso ocurra.
De todos modos, ¿qué ocurre si ejecuta esto desde su consulta PHP y muestra los resultados? ¿Alguna diferencia con la salida de línea de comando?
SHOW VARIABLES LIKE ''character_set%'';
SHOW VARIABLES LIKE ''collation%'';
Veo que lo has intentado, pero la sintaxis que uso es: mysql_query ("SET NAMES utf8"). Tu sintaxis puede ser correcta, nunca antes la había visto así.
Ejemplo:
// connect to database stuff
$Connection = mysql_connect($server, $username, $password)
or die ("Error connecting to server");
// connect to database stuff
$db = mysql_select_db($database, $Connection)
or die ("Error selecting database");
mysql_query("SET NAMES utf8");
Tuve un problema similar después de actualizar PHP de 5.2.3 a 5.3.5 (5.3.5-Win32-VC6-x86), MySQL 5.0.41 (no actualizado). Creo que esa razón es una pequeña diferencia entre las versiones de PHP.
PHP 5.2.3 por defecto (sin SET NAMES):
character_set_client = latin1
character_set_connection = latin1
character_set_database = utf8
character_set_filesystem = binary
character_set_results = latin1
character_set_server = latin2
character_set_system = utf8
collation_connection = latin1_swedish_ci
collation_database = utf8_polish_ci
collation_server = latin2_general_ci
PHP 5.3.5 por defecto (sin SET NAMES):
character_set_client = latin2
character_set_connection = latin2
character_set_database = utf8
character_set_filesystem = binary
character_set_results = latin2
character_set_server = latin2
character_set_system = utf8
collation_connection = latin2_general_ci
collation_database = utf8_polish_ci
collation_server = latin2_general_ci
Agregué datos a la base de datos en PHP 5.2.3 por defecto (sin SET NAMES), así que ahora para mostrarlo correctamente debo leerlo usando:
$pdo -> query("SET NAMES ''latin1''");
Quizás algo similar es la razón de tu problema.