La solución a los problemas con los acentos en PHP, MySQL y HTML

Somos muchos los que, cuando estamos comenzando a programar, nos encontramos con un problema que a veces nos consume mucho mas tiempo del que debería y a veces al buscar una solución en la red lo complicamos todavía más, debido a la gran cantidad de información existente y a que en muchas de las webs y blogs que he estado viendo te lian mas que ayudan.

Yo voy a explicar mi método, sin entrar a ver las diferencias entre ISO 8859-1 y UTF-8, que son las dos mas comunes.

En mi caso yo siempre uso UTF-8 y la razón es que en las aplicaciones que estoy desarrollando utilizo mucho la clase SimpleXML de PHP y todos los datos extraidos con esta clase siempre están codificados en UTF-8, si mi aplicación utilizara ISO-8859-1 tendría que pasar toda la información por la función utf8_decode() de PHP, con lo que estaría sobrecargando el script sin necesidad.

La clave está en que hay que “decirle a todo” que cotejamiento es el que estamos utilizando.

1.- Codificación del documento.

En primer lugar hay que comprobar la codificación del documento, si usas DW y Windows en español posiblemente el valor de Codificación por defecto lo tendrás en Europeo occidental.

En Dreamweaver lo puedes comprobar pulsando CRTL-J, o en modificar – propiedades de pagina.

En Notepad++ lo verás en la pestaña Codificación.
Codificacion del archivo almacenado en PC

Si esto lo tienes bien, tu etiqueta <meta> del documento debería ser como sigue:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

2.- MySQL

Aquí es donde surgen la mayor parte de los problemas. Cuando creamos las tablas en la base de datos tenemos que tener especial cuidado de que todos los cotejamientos estén en utf-8. Cuando lo dejas por defecto, si utilizas phpmyadmin este proceso se convierte en una lotería y cuando termines de crear tu base de datos verás que cada cosa está cotejada de forma diferente…

Yo voy a utilizar UTF-8, si te decantas por ISO-8859-1, en todas las selecciones que nombro a continuación tendrás que elegir latin1_general_ci, si eliges latin1_spanish_ci también funcionará, pero por favor, usa en todas lo mismo.

Cotejamiento para las conexiones al servidor.

Cotejamiento de conexiones al servidor.

Cotejamiento para la base de datos

En la pestaña operaciones de la pantalla principal de la base de datos

Cotejamiento Base Datos

Cotejamiento para las tablas.

Cada tabla que creemos deberá tener el mismo cotejamiento

Cotejamiento de Tabla

Cotejamiento de Campo o Columna.

Es importante indicar el cotejamiento que va a tener el Campo, sobre todo si en este vamos a almacenar caracteres de texto. Lógicamente a un campo numérico, booleano etc no hay que indicar el cotejamiento porque su contenido no incluirán caracteres “extraños”.

Cotejamiento de Campo

3.- PHP

Por último vamos a “decirle” al Mysql en PHP cómo nos vamos a comunicar con la base de datos para que no haya ningún tipo de confusión.

Yo utilizo siempre PDO para la conexion de PHP con la base de datos, pero esto es otro tema que da para mucho. Así quedaría la conexión. Al crear el manejador de la conexión hay que incluir en el array de opciones la codificación, como sigue:

$pdo = new PDO('mysql:host= servidor; dbname=bd', $usuario, $clave, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES  \'UTF8\''))

Si usas la conexion estandar, basta con añadir

mysql_set_charset('utf8');

justo despues de abrir la conexion con la base de datos.

Anuncios
Esta entrada fue publicada en php y etiquetada , , , , , , , . Guarda el enlace permanente.

93 respuestas a La solución a los problemas con los acentos en PHP, MySQL y HTML

  1. Xendess dijo:

    Dios. me has salvado la vida.

  2. Xavier Vela dijo:

    Te agradezco muchísimo!!

  3. Rubén dijo:

    Gracias. No había tomado en cuenta la función set_charset(). Resolví mi problema.

  4. dbarreno dijo:

    Muchas gracias a vosotros por vuestros comentarios.

  5. anghel dijo:

    Te agradezco muchísimo!!, de verdad

  6. Kurtsuke dijo:

    Eres el mejor 😀 muchos salu2 Gracias!!!

  7. juan carlos dijo:

    gracias amigo….. gracias de corazón

  8. juan carlos dijo:

    sabes me gustaría de me indiques como registrar fechas en mi base de datos de la siquiente forma “02/05/2013” y no “2013/05/02”

    • dbarreno dijo:

      Hola Juan Carlos,
      Gracias por tus comentarios.
      En MySQL hay varias formas de almacenar una fecha. Si no necesitas almacenar la hora yo te recomiendo usar el tipo de datos DATE.
      El formato para almacenar la fecha sólo puede ser YYYY-MM-DD, esto no se puede cambiar, pero eso no tiene que suponer ningún problema ya que existen muchas formas de “formatear” la fecha para mostrarla como nosotros queramos.
      Yo personalmente prefiero formatearla en PHP utilizando la clase DateTime() de la siguiente forma:

      $Fec = new DateTime('2013-11-25');
      $fecha = $Fec->format("d-m-Y");

      Otra forma es usar la típica funcion date() de esta forma
      $fecha = date('d-m-Y', strtotime('2013-11-25'))
      Pero ojo con este método ya que no soporta fechas inferiores al 13-Diciembre-1901 ni (lo que es mas importante) superiores a 19-Enero-2038.
      Pero hay otra forma y es que MySQL te de ya la fecha en el formato que necesites. Para ello hay que utilizar las funciones que MySQL tiene para utilizar con las fechas.
      La forma de usarlas es incluirlas en las consultas y un ejemplo podría ser el siguiente:
      SELECT `usuarios`.`nombre`, DATE_FORMAT(`usuarios`.`fecha_nacimiento`, '%d-%m-%Y') AS fecha_nacimiento FROM `usuarios` WHERE `usuarios`.`id_usuario` = 1

      Huye de almacenar fechas como VARCHAR, es poco eficaz y sólo te traerá problemas.
      Espero haberte ayudado.
      Un saludo

  9. Chicho dijo:

    Muchas gracias por este gran articulo, ya que en muchas ocasiones me habia vuelto loco con este tema.

  10. alopez dijo:

    Muy buen articulo, llevo mucho tiempo desarrollando y nunca me había ocurrido el problema… solo ahora que decidí pasarme a un servidor mas grande …. me ocurrió esto …

  11. SrlLvrs dijo:

    Por fin!! Gracias amigo, te agradezco esto, me dí muchos cabezazos antes de darme cuenta de mi error -.-”

    Algo que tal vez puedas agregar, es que si están trabajando con Sublime Text 2, el archivo .PHP van a menú File -> Save with Encoding -> UTF-8 with BOM.

    Saludos!! 😀

  12. Martín dijo:

    Anduvo espectacular tu solución, resumiendo:
    En HTML:

    En MYSQL:
    En la base, tabla y datos colocar en el cotejamiento utf8_general_ci
    En PHP:
    Luego de conectar con la base de datos
    mysql_set_charset(‘utf8’);
    Saludos

  13. Rocko dijo:

    en que parte va el code:

    mysql_set_charset(‘utf8′);

    ? Muchas gracias

  14. Maravilloso, resumido, sencillo y atacando todos los posibles puntos donde existen los problemas.
    Felicidades por el aporte y muchas gracias

  15. Iván dijo:

    Muchas gracias me ayudó demasiado. (Y)

  16. Gracias funciona yo tambien lo utlizo con PDO saludos

  17. Andrés dijo:

    Otro al que salvaste!

  18. Gracias, gracias, gracias

  19. henry h bogota, colombia dijo:

    Con phpmysqladmin necesito crear tabla con filas así: CUENTA y los doce meses, cada uno con SALDO ANTERIOR, DEBITOS en ese mes, CREDITOS en ese mes y NUEVO SALDO o sea un array para 12 meses dentro de una columna o tendré que definir 4 columnas por mes y definir entonces 4X12=48 columnas? Estoy aprendiendo, MUCHAS GRACIAS por orientarme!.

  20. Raúl dijo:

    Funcinó totalmente.
    ¡Gracias!

  21. Muchas gracias, mi problema se debía al cotejamiento en la DB, entidades y campos; a través de sugerencias probe con latin, utf-spanish_ci, ci2 y no funciono; otra alternativa es con htmlentities.
    La configuración del editor en mi caso Geany es en: Documento->EstablecerCodificación->Unicode->Unicode(UTF-8)

  22. rogervaldez dijo:

    Muchas Gracias Daniel!!!

  23. E-RZ dijo:

    Hola les comento que intente esto y no me funciono, mi principal problema es que parece que el comando mysql_set_charset(); ya no funciona, después de una búsqueda lo cambie por:

    mysqli_set_charset(database, ‘utf-8’);

    y al parecer funciona perfectamente.

    Saludos

    • dbarreno dijo:

      Buenas,

      Gracias por el aporte.
      MySQLi es una extensión algo más moderna de MySQL, mas recomendable de usar que ésta última, ya que efectivamente está obsoleta a partir de la version 5.5 de PHP y tiende a desaparecer.
      Pero actualmente sigue operativa, el motivo de que no te funcione mysql_set_charset() es que en tu script abrirás la conexión con mysqli_connect(), lo que significas que te conectas a la base de datos utilizando esta extensión y por tanto todas las funciones que utilices deben pertenecer al grupo de funciones de esta extension: mysqli_error(), mysqli_fetch_array() etc.

      De todas formas yo lo que recomiendo es utilizar PDO, es mas rápido y mas seguro, y no es tan complicado como al principio puede parecer. Con unos conocimientos mínimos de programacion orientada a objetos se puede implementar sin dificultad.

      Un saludo

  24. CARLOS dijo:

    ESTOY UTILIZANDO LA CLASE FPDF Y SIGO LAS INSTRUCCIONES ANTES EXPUESTA Y NO CONSIGO MOSTRAR LAS Ñ Y TILDES. QUE DEBO HACER POR FAVOR AYUDA

    • dbarreno dijo:

      Hola,
      Con tan poca información es muy complicado poder ayudarte. En la documentación de FPDF podrás encontrar el juego de caracteres que utiliza la clase.
      Dependiendo de qué estés utilizando tu y cómo esté configurado la clase externa (fpdf), intenta aplicar a cada cadena de texto la funcion utf8_encode() o utf8_decode(), a ver que tal.
      No es la mejor forma, pero a veces no queda mas remedio. Lo ideal sería configurar la clase FPDF para que toda la aplicación utilice el mismo juego de caracteres, pero con tan poca información, es lo que puedo decirte
      Saludos

  25. jorge dijo:

    Excelente. grandioso, busque y busque nada.
    Pero tu post es el bueno, mil gracias, saludos.

  26. Reynaldo dijo:

    Gracias amigo me ha sido de ayudo.
    Amigo tengo un problema y no se como solucionarlo, lo que pasa es cuando yo creo un documento HTML en cualquier programa (sublime text, notepad, dreamweaver, netbean) corren con normalidad pero cuando creo un documento PHP en cualquiera de los mencionados a excepción del -NetBeans- no se muestran nada por ejemplo este codigo:

    No se muestra. Esoty utilizando el xampp y le tengo el apache y mysql activado.

  27. Yorch dijo:

    Te quieeerooooo. Hace meses y meses, por no decir años, que tengo el problemilla de las tildes, y hasta ahora hacía apaños sustituyendo caracteres, pero finalmente y GRACIAS A TI se me ha resuelto. ¡Qué fácil parecía! Y pensar que tenía las tablas en un cotejamiento y las webs en otro… ¡¡GRACIAS!!

  28. peter dijo:

    Que buen post!!! Me acabas de solucionar un problema que me hubiera costado horas encontrar la solución!!!
    Muchas gracias!!!

  29. facuap dijo:

    que todos los dioses te bendigan, gran explicacion.!!!

  30. Rex Pest dijo:

    Sos groso… esto fue brillante, muchas gracias…

  31. Roger dijo:

    Hacía tiempo que había trabajado con todo esto pero a uno se le olvidan cosas. Gracias, me ha servido de mucho!

  32. Amigo muchísimas gracias!!! Funcionó tal como indicas. Bendiciones desde Ecuador!!!

  33. msolis86 dijo:

    Muchas Gracias me ha funcionado en mi proyecto!!!

  34. Luis Rivero dijo:

    Eres el mejor, me salvaste, ya estaba medio loco con esto

  35. Daniel dijo:

    Buenisima. Notable Solucion.

  36. José dijo:

    Muchísimas gracias, me quedó claro.
    Intentaré usar PDO.

  37. Luis Herazo dijo:

    Me Funciono mysql_set_charset(‘utf8’); Excelente Aporte

  38. eljihe dijo:

    estoy utilizando fpdf pero los datos que se extraen no reconoce los acentos
    coloque en la conexion mysql_set_charset(‘utf8’); y en el multicell utf8_decode pero aun así nada

  39. Pingback: Problemas de Acentos y caracteres al traer datos de un Database con PHP | Informatic To You

  40. Angry Birds dijo:

    Muchas gracias estaba enredado con las eñes me ha servido de mucho tú ayuda 🙂

  41. Cristian D dijo:

    Excelente aporte! Llevaba mucho tiempo luchando con esto de las tildes…

  42. javierceb dijo:

    Amigo tenia varios dias buscando una solucion para esto, mil gracias

  43. Rodrigo dijo:

    Estimado… nunca dejo un comentario, pero tu post vale la pena hacerlo…. Eres un Crack…. mi ídolo XD

  44. Jesús Piña dijo:

    Muy buen artículo una pregunta ¿Que diferencia hay entre lo que escribes con la vieja técnica de cambiar los acentos por su equivalente en HTML por ejemplo José Peña por José Peña?

    • dbarreno dijo:

      Hola Jesús,
      Con eso de la vieja técnica supongo que te refieres a usar entidades del tipo &oacute ;.
      No suelo usar entidades por varios motivos (si las usas que sea dentro del código HTML). Estando todo bien configurado no es necesario.
      No recomiendo almacenar nunca entidades en base de datos, asi que cuidado con los editores como TinyMce.

      Te pongo un ejemplo sencillo de por qué no lo recomiendo (puedes hacer pruebas de lo que te comento en tu phpMyAdmin local). Si quieres, por ejemplo, montar en tu web tu propio buscador interno, a la hora de buscar un usuario va a escribir, por ejemplo, Africa con acento o sin acento.
      Si tienes almacenado África y una configuración correcta de caracteres al realizar tus querys ejemplo: ....LIKE 'africa'... te va a dar resultados tanto si el usuario escribió África con tilde o sin ella.
      Pero si tienes almacenado en tu tabla &Aacute ;frica ni Africa, ni África te van a dar resultados, al menos que incluyas una función que te convierta antes en entidad la letra acentuada (si el cliente ha puesto la tilde). Esto de andar convirtiendo con funciones es tiempo de procesamiento, que hay que evitar para optimizar nuestra web al máximo, y además funciona relativamente bien si estas usando ISO, pero si en cambio usas UTF8 las conversiones se complican, tienes que crearte tus propias funciones.

      Se me ocurren mas motivos, pero creo que este es el mas claro, y además ya me he extendido demasiado xD

      Gracias por tu comentario
      Saludos

  45. Excelente una solución rápida que me ha servido bastante, gracias

  46. Armando dijo:

    necesito ayuda no funciona y segui los mismos pasos yo tambien utilizo una coneccion PDO y otra cosa, ¿es posible meter enters en la base de datos?

    • dbarreno dijo:

      Hola,
      Comprueba que los caracteres extraños no estén ya mal almacenados, en cuyo caso la solución es complicada.
      No se a que te refieres con Enters, podrias concretar?

      Gracias por tu comentario.

  47. Dyn Lr dijo:

    gracias por tu aporte me salvaste de otra noche sin dormir xd

  48. Jose dijo:

    estimado, simplemete agradezco , muy util y didactico. andubo a la perfeccion

  49. Mario dijo:

    Muchísimas gracias!! A mí también me has salvado la vida 😉

  50. Sergio dijo:

    Muchas gracias!!! Me estaba volviendo loco con este tema y me lo solucionaste!!!.
    Mil gracias por compartir.

  51. fosfiles dijo:

    Grande, grand&iacutesimo…. toda la noche sin dormir y por fin te encontré. Gracias!!!!

  52. Lipschitzz dijo:

    Genial esta entrada. Muchas gracias.

  53. TAP10N dijo:

    Eres el puto amo. Me as salvado la vida, de aqui hasta el futuro

  54. Muchas Gracias por compartir conocimiento…!

  55. Ethgar MTZ dijo:

    Excelente aporte, me salvaste de un dolor de cabeza de dos semanas

  56. Si señor, despues de ver en varios foros especialistas por fin consegui, se trataba del “set_charset” despues de abrir la conexion, muchisimas gracias por ayudar a los que estamos aprendiendo.

  57. lucio dijo:

    tenia este inconveniente en algunos campos de consulta y tu metodo funciono correctamente..mil gracias por aportar…

  58. Cristian dijo:

    Muchas gracias!! Me sirvió mucho

  59. Mil gracias, muy valioso tu aporte

  60. Lo maximo, muchas gracias!!!! xoxoxoxo

  61. yemir0904 dijo:

    Hola, disculpe, en phpmyadmin que tipo de fecha puedo usar si solo quiero que me indique en el registro un periodo, por ejemplo mes y año [junio – diciembre 2014]..

    • dbarreno dijo:

      Hola Yemir,
      Disculpa que no haya respondido antes a tu cuestión. Me había entrado como SPAM y lo acabo de rescatar. Supongo que ya lo tienes solucionado, pero respondo lo que yo haría en este caso, por si acaso alguien tiene un caso similar.
      Si lo que quieres es almacenar un periodo de tiempo yo siempre utilizo 2 registros, uno para la fecha inicio y otro para la fecha fin del periodo y el campo, por supuesto de tipo DATE. Siempre que quieras trabajar con fechas utiliza DATE. Si obligatoriamente tienes que almacenar la estructura con el formato Junio – Diciembre 2014 tendras que usar un campo string, pero no podrás realizar ningún tipo de operación de fecha con ese registro. Simplemente será una cadena de texto sin mas.
      En cambio, utilizando fecha inicio y fecha fin tienes muchas posibilidades para realizar ordenación y busquedas correctamente.
      Si a alguién se le ocurre otra forma, se agradecen los aportes.
      Saludos.

      • yemir0904 dijo:

        ok, gracias, ya comprendo, supongo que con el string puedo dar opciones preestablecidas que el usuario (en este caso). pero para mayor precisión DATE.

  62. angel dijo:

    @dbarreno grande igual que a muchos otros me has salvado de una mala noche jaja directo a favoritos, por favor sigue actualizando el blog 😉

  63. abimael macho dijo:

    Excelente amigo, tras horas de busqueda logre solucionar con esta guia, gracias.

  64. Carlos Uribe dijo:

    Gracias, la solución es precisa y muy sencilla de implementar. A partir de ahora, codificaré correctamente.

  65. Naoto dijo:

    Muchas gracias por la ayuda, agregue dentro de la conexión con PDO la sintaxis faltante, y todo funciona perfecto. Muchas gracias nuevamente.

  66. Horacio Lira dijo:

    ¡Gracias! me sirvió mucho

  67. Muchas gracias amigo, llevaba rato buscando la solucion.

  68. facu dijo:

    4 años y 1 dia despues de publicarlo sigue sirviendo 😀
    Graciaaaaaas!

  69. Cesar Martin Esparza Vera dijo:

    Muchisisisísimas gracias!!!!! Con este post pude solucionar el problema que tenía con los acentos y ñ’s, al hacer mis consultas……!!!! Gracias por todo……… ERES GRANDE.. 😀

  70. Muchas gracias esta linea me salvo “mysql_set_charset(‘utf8’);”

  71. KlooN SizmicO dijo:

    Muchas gracias me funciono , solo haciendo la opción 3 , ya que apenas comienzo en este cuento , fue de mucha ayuda !

  72. Bonetta dijo:

    sos Mago!!….Muchas Gracias ❤

  73. Pingback: Los problemas de acentos con NetBeans | Viajes y programacion

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s