2011-06-03 14 views
13

Estoy usando PHPUnit para validar el resultado XML de mi código PHP, pero aparentemente tengo problemas con la codificación de caracteres MySQL. Aquí está el error que recibo de DOMDocument:¿Cómo hago que MySQL devuelva UTF-8?

Input is not proper UTF-8, indicate encoding! 
Bytes: 0xE9 0x20 0x42 0x65 

Me inicializar el DOMDocument por lo que utiliza la codificación correcta:

$domDocument = new DOMDocument('1.0','UTF-8'); 

Y cuando compruebo la salida de saveXML() usando mb_detect_encoding el resultado es UTF-8 .

También comprobé todas las llamadas que se utilizan para crear el XML, usando mb_detect_encoding en todos los parámetros createCDATASection encontradas y todos son UTF-8 o ASCII (no hay nodos de texto sin formato, todo está en CDATA bloques).

Creo que el problema proviene del uso de un carácter 'é' (que es 0xE9 en ISO 8859-1). La línea que añade que el carácter a mi XML es:

$domDocument->createCDATASection($place->name); 

y mb_detect_encoding ($ lugar-> nombre) me da UTF-8.

Los datos ($ place-> name) se extraen de una base de datos MySQL. Esta base de datos tiene el juego de caracteres UTF-8.

Aquí es un código de ejemplo:

$query = sprintf('SELECT name FROM place where id = 1'); 
$result = mysql_query($query); 
$result = mysql_fetch_assoc($result); 


// -- Feeding UTF-8 data directly WORKS 
$domDocument = new DOMDocument('1.0','UTF-8'); 
$rootNode = $domDocument->createElement('Response'); 
$rootNode->appendChild($domDocument->createCDATASection('Café Belga')); 
$domDocument->appendChild($rootNode); 

$matcher = array('tag' => 'Response'); 
self::assertTag($matcher, $domDocument->saveXML(), '', FALSE); 

// -- Feeding UTF-8 data from the resultset FAILS 
$domDocument = new DOMDocument('1.0','UTF-8'); 
$rootNode = $domDocument->createElement('Response'); 
$rootNode->appendChild($domDocument->createCDATASection($result['name'])); 
$domDocument->appendChild($rootNode); 

$matcher = array('tag' => 'Response'); 
self::assertTag($matcher, $domDocument->saveXML(), '', FALSE); 

En mi depurador PhpStorm, la cadena tomaron de la base de datos es el siguiente:

Café Belga

Así que creo esa es la raíz del problema. En MySQLWorkbench, la cadena es correcta: Café Belga.

¡Cuando se usa utf8_encode($result['name']), sin embargo, todo funciona bien!

Una comprobación más en la ventana de relojes:

mb_detect_encoding($result['name']) -> "UTF-8"

mb_detect_encoding(utf8_encode($result['name'])) -> "UTF-8"

En una nota lateral, ¿Hay algún sitio donde Puedo simplemente copiar y pegar esos valores hexadecimales y ver qué personajes se supone que tienen en diferentes conjuntos de caracteres.

+0

¿Dónde se almacena el carácter 'E'? En un archivo? En tu código? – Yeroon

+0

Vaya, se olvidó de mencionar esto, edité mi pregunta: los datos se extraen de una base de datos mysql. Esta base de datos tiene el conjunto de caracteres utf8. –

+0

@Joris ¿usas loadXml en algún momento después de crear el domdocumento? Además, ¿puede proporcionarnos un modelo de prueba reproducible que ilustre el problema? – Gordon

Respuesta

42

Usted tiene que definir la conexión a su base de datos como UTF-8:

// Set up your connection 
$connection = mysql_connect('localhost', 'user', 'pw'); 
mysql_select_db('yourdb', $connection); 
mysql_query("SET NAMES 'utf8'", $connection); 

// Now you get UTF-8 encoded stuff 
$query = sprintf('SELECT name FROM place where id = 1'); 
$result = mysql_query($query, $connection); 
$result = mysql_fetch_assoc($result); 
+0

¡Gracias! ¡Eso lo resolvió! –

+0

Me alegro de haber podido ayudar :-) – strauberry

+0

No debe usar 'SET NAMES' (vea http://stackoverflow.com/questions/5288953/is-mysql-real-escape-string-broken/5289141#5289141). – Gumbo

0

Desde la versión de PHP 5.5.0 se debe utilizar

mysqli_set_charset($connection,"utf8"); 
Cuestiones relacionadas