300x250 AD TOP

viernes, 23 de agosto de 2013

Etiquetado Como: , , , , ,

Solucionar Error/Problema con tildes, eñes y caracteres especiales en MySQL,PHP y AJAX - Codificación UTF-8 Parte 1


A quien no nos ha pasado que hacemos nuestra aplicación web bien bacan con php, mysql y ajax y vemos que se guardan en la base de datos o se muestra en la pagina caracteres raros por ejemplo "Perú Campeón" en lugar de "Perú Campeón" y damos vueltas y vueltas, bueno la idea de esta entrada es generar un método estándar de programar para poder solucionar este problema.
Para poder tener un control total de la codificación suponiendo que queremos que sea UTF-8 todas nuestras tecnologías deben estar configuradas en esta codificación para evitar cabos sueltos.
Tecnologias y solucion : Apache, PHP , Mysql , JQuery (ajax)

1. Crear nuestra Base de datos y tablas en Mysql
CREATE DATABASE dbname CHARACTER SET utf8 COLLATE utf8_general_ci;
y las tablas
CREATE TABLE IF NOT EXISTS `tablaprueba` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `nombre` varchar(250) COLLATE utf8_general_ci NOT NULL,
  `apellido` varchar(250) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci AUTO_INCREMENT=1
Hay que tener en cuenta que podemos utilizar utf8_general_ci, utf8_spanish_ci , utf_unicode_ci y tambien que los campos de la tabla automáticamente asumen la codificación de la tabla  por lo que en el ejemplo el campo apellido también tendrá utf-8 a si no lo hallamos declarado como en el campo nombre.
2. codificación en la Conexión PHP / Mysql
Es posible que php venga configurado a nivel servidor (vea segunda parte) para utilizar algún tipo de codificación que no sea UTF-8 por lo que al momento que php recibe los valores es que se hace la conversión de charset y ocurre el problema al almacenar en la base de datos para solucionar esto la conexión se debe hacer con la codificación esperada por lo que agregamos lo siguiente.
a. Utilizando la libreria Mysql:
mysql_query("SET NAMES 'utf8'");
b. Utilizando la libreria Mysql Improved (Mysqli):
$db->query("SET NAMES 'utf8'");
c. Utilizando PDO:
$pdodb->exec("set names utf8"); //donde pdodb es la instancia al objeto PDO $pdodb = new PDO(....); 
Otras soluciones con PDO pudes visitar PHP PDO: charset, set names?

3. Codificación UTF-8 en la presentaciones HTML
Supongamos que hemos realizado le paso 1 y 2 pero al momento de mostrar nuestro resultado en web nos siguen saliendo los errores esto es debido a que el Header de respuesta Content-type tiene algún tipo de codificación que no es utf-8 o no la tiene  para solucionar esto a nivel HTML siempre hay que asegurarnos de agregar la etiqueta meta con el charset=utf8

<meta http-equiv=content-type content=text/html; charset=utf-8>
y con html5 es semejante
<meta charset=utf-8>

4. Codificación UTF-8 al enviar vía Ajax, Json , etc.. con Jquery y recibiendo con PHP
Creo que la mayoría por no decir todas las aplicaciones utilizan algún método ya sea ajax o json para enviar datos al servidor utilizando javascript puro o Jquery para crear mejores experiencias de usuario sin embargo si no se tiene el control suficiente se pueden recibir caracteres en codificación diferente a lo que esperamos por lo que para un mayor control podríamos hacerlo de esta manera:

<script type="text/javascript">
jQuery.ajax({
    type: 'POST',
    encoding:"UTF-8",
    dataType:"json", 
    contentType: "text/json; charset=UTF-8",
    url: 'miarchivo.php',
    success: function(msg) {
        jQuery('#dataBox').html(msg);
    }
});
</script>
Hasta aquí todo vacan pero como mencione PHP puede estar configurado para ejecutarse en algun otro tipo de codificación por lo que miarchivo.php se ejecutara en la codificación por defecto por lo que tanta chamba para que al momento de recibir se reciban datos incorrectos esto lo solucionamos facil cambiándole el header con la codificación que necesitamos este codigo se pone al inicio del archivo php salvo que uses namespces ya lo pondrías debajo

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

Hasta este punto no creo que tengamos mas problemas con los acentos, eñes ,  y otros caracteres especiales, sin embargo existen otras formas a nivel configuración del servidor con ejemplo configurando el charset en apache y php o haciéndolo desde htaccess  esto lo veremos en la SEGUNDA PARTE del articulo, espero que les sirva

Update (14/03/2016) : Ayer me paso algo particular con php 5.6 ejecute todo como lo explico en este tutorial pero no me funcionaba siempre retirnaba de la base de datos de forma incorrecte para validar si un string es utf8 utilziamos la funcion

mb_detect_encoding($texto)


si como resultado retorna "UTF-8" el resultado es correcto en caso retorne ASII se debe hacer una converción a utf8 

mb_detect_encoding(utf8_encode($texto))



Referencias:

http://stackoverflow.com/questions/4279282/set-http-header-to-utf-8-php
http://xaviesteve.com/354/acentos-y-enes-aparecen-mal-a%C2%B1-en-php-con-mysql-utf-8-iso-8859-1/
http://stackoverflow.com/questions/14198907/jquery-utf-8-not-working-with-ajax-request
http://en.wikipedia.org/wiki/List_of_HTTP_header_fields

8 comentarios:

  1. Excelente, muchas gracias. Voy a probar si puedo soluciones mi problema con esto.

    ResponderBorrar
  2. Buen post amigo, te fijaste en todos los detalles, rara vez se encauntra algo asi! :D

    ResponderBorrar
  3. Bravo!
    Esto me ha ayudado mucho:

    $this->bbdd->query("SET NAMES 'utf8'");

    Gracias!!

    ResponderBorrar
  4. Hola, en que parte debo poner esto

    mb_detect_encoding($texto)

    Mis tablas estan con utf8_spanish_ci
    mis header en las páginas html tambien
    pero cuando guardo en la base de datos acentos y eñes me los cambia, y tambien cuando hago una consulta de la base de datos desde mi pagina web php me tira las eñes asi � pero si la consulta la hago en mi base de datos me la tira normal...

    ResponderBorrar
  5. eres grande, uno batalla mucho al programar en php y nunca agrega los headers al inicio

    ResponderBorrar
  6. Me salvaste la vida papu, con el $bd->query("SET NAMES 'utf8'"); se soluciono todo. Un abrazo master !

    ResponderBorrar

Gracias por comentarnos