Cuando la codificación falla al presentar nuestra información es necesario emprender un camino de retorno hacia los datos para determinar dónde está el problema.
Cuando digo camino de retorno quiero decir que debemos empezar a revisar en la superficie e ir profundizando, para depurar el problema. Un ejemplo de camino de retorno sería :
Documento (HTML-Javascript-CSS, etc) > Nivel 1
Servidor (PHP u otro lenguaje) > Nivel 2
Conexión a la Base de Datos (PDO, MySQLi u otros) > Nivel 3
Configuración de la BD (MySQL u otros) > Nivel 4
Considero que es un método inteligente de depuración, pues en este caso los datos que se presentan en nuestra pantalla son sacados de una base de datos a través de un lenguaje de servidor y presentados en pantalla. Si revisamos en este orden siempre llegaremos al fondo del problema, pero por niveles. Es algo lógico : no se puede llegar al fondo sin pasar por la superficie :)
Además, aquí lo más precioso son los datos, así que, cuanto menos los toquemos o alteremos, mejor. Eso implica también que es muy importante al crear la base de datos configurar adecuadamente la BD misma, así como cada tabla y cada columna... así no tendremos que estar manipulando su estructura, lo cual podría ser un riesgo sobre todo si la BD ya tiene información , pues como es sabido podríamos perderla o provocar errores en los datos... pero ese es ya otro asunto.
Entonces empezamos a revisar desde la superficie hacia el fondo para ver dónde está el problema.
Nota: Antes de emprender este camino de retorno, consideremos un posible Nivel 0 de revisión. Es posible que si hemos trabajado nuestro contenido en cualquier editor de texto como Notepad u otros, la codificación del documento no sea la adecuada. Así que, según el editor, sería conveniente verificar la codificación que ha sido establecida en nuestro archivo. Esto sólo en el caso de que hayamos tomado el texto de algún editor.
Este Nivel 0 es importante, sobre todo si tenemos mal configurada la codificación en el editor y pensemos seguir introduciendo datos en la base de datos con una codificación que no es la que necesitamos.
La configuración del HTML
- Colocar lo siguiente en el
<head>
:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
La configuración del servidor (PHP u otro)
mb_internal_encoding("UTF-8");
O bien: default_charset
(Desde PHP 5.6+ viene establecido a UTF-8
por defecto).
ini_set("default_charset", "UTF-8");
NOTA MUY IMPORTANTE: Aquí me refiero a una configuración
global de PHP, no a aplicar funciones de codificación/decodificación sobre los datos constantemente, lo cual sería un error (el cual muchos
recomiendan, por desconocimiento, en respuestas a casos parecidos a
este). Cuando tengamos problemas con la codificación a nivel de PHP
resolvámoslo de raíz, en la configuración, no aplicando soluciones a
medio camino que nos mantendrán esclavizados aplicando
constantemente funciones como utf8_encode
a los datos.
- La forma en que te conectas a la BD, estableciendo la codificación a UTF-8
En el caso de MySQLi
/* cambiar el conjunto de caracteres a utf8 */
if (!$mysqli->set_charset("utf8")) {
printf("Error cargando el conjunto de caracteres utf8: %s\n", $mysqli->error);
exit();
} else {
printf("Conjunto de caracteres actual: %s\n", $mysqli->character_set_name());
}
Ver: mysqli::set_charset
En el caso de PDO
Se puede hacer enviando el siguiente atributo a los parámetros de conexión:
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"
. Ejemplo:
$options = array(
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"
);
try {
# Intentar la conexión
$pdo = new PDO($dsn, $usr, $pwd, $options);
}
catch (PDOException $e) {
# Escribir posibles excepciones en el error_log
error_log($e->getMessage(),0);
}
...
Se puede hacer también poniendo el charset en la cadena del DSN, como se explica en esta Nota del Manual de PHP. Por ejemplo:
$pdo = new PDO("mysql:host=localhost;dbname=DB;charset=UTF8");
- La codificación de los datos en sí (que puede ser: a. una columna de una tabla, b. una tabla de la base de datos, c. la base de datos en general).
Yo iría depurando en ese orden, del 1 al 4.
Como dices que en algún escenario se ve correctamente, parece que el problema está en el nivel 3.
Verifica que cuando te conectas a la Base de Datos estás estableciendo la codificación a UTF-8.