Para que tu aplicación trabaje a todos los niveles a UTF-8
debes comprobar que:
- Tu servidor debe devolver la cabecera
Content-Type: text/html; charset=utf-8
ya sea generada desde el propio script PHP (con header('Content-type: text/html; charset=utf-8')
) o desde el servidor web (AddType
o AddCharset
en la configuración de apache, por ejemplo).
- Las locales de PHP también deben soportar
UTF-8
. Casi todos los sistemas Linux modernos tienen por defecto en_US.UTF-8
o es_ES.UTF-8
o equivalente. Si el que viene configurado por defecto es diferente deberás cambiarlo con setlocale(LC_ALL, 'es_ES.UTF-8')
. Usa locale -a
para obtener el listado disponible.
- Tu HTML debe tener definido el juego de caracteres usando la etiqueta
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
en compatibilidad con HTML4 y/o <meta charset="utf-8">
usando HTML5.
- Tus tablas en el servidor MySQL deben (aunque no es necesario) usar el cotejamiento (
utf8_spanish_ci
).
- La conexión con el servidor MySQL debe usar codificación
UTF-8
usando SET CHARACTER SET utf8
a través de una llamada a mysqli::set_charset()
en el caso de usar mysqli
.
Aunque las dos primeras pueden ser complementarias (la definición dentro del HTML suele tener preferencia y la cabecera HTTP suele usarse en ausencia de ella), es recomendable usar ambas para que evitar problemas.
Los dos últimos igual, los datos podrían estar almacenados en un cotejamiento diferente siempre que se especifique correctamente el protocolo de comunicaciones entre cliente y servidor, el servidor haría el trabajo de conversión de juegos de caracteres, pero es importante que si usamos consultas SQL con cadenas de caracteres en UTF-8
definamos ésto con el método propuesto.
Es equivalente a hacer:
SET character_set_client = 'utf-8';
SET character_set_results = 'utf-8';
SET collation_connection = @@collation_database;
Por lo que usar el cotejamiento correcto en base de datos y tablas nos ahorrará hacer más modificaciones, aunque sea opcional.
Ejemplo de código PHP/HTML correcto:
<?php
header('Content-type: text/html; charset=utf-8');
include_once 'conexion.php';
/* Ésto sería mejor meterlo dentro de "conexión.php" */
if ($conexion->set_charset('utf8') === false) {
die('Error: ' . $conexion->error);
}
if(isset($_POST['registrar'])) {
$nombre = $_POST['nom'];
$apellido = $_POST['ape'];
$gmail = $_POST['gmail'];
$consulta = $conexion->prepare('
INSERT INTO registros (
nombre_regisdb,
apellido_regisdb,
gmail
) VALUES (
?,
?,
?
)
');
if ($consulta === false) {
die('Error en la consulta: ' . $conexion->error);
}
$consulta->bind_param(
'sss',
$_POST['nom'],
$_POST['ape'],
$_POST['gmail']
);
/* Esto cambia un poco el resto del HTML, pero bueno */
if ($consulta->execute() !== false) {
header('location: mensaje.php');
} else {
die('Error');
}
}
?><!doctype html>
<html lang=es>
<head>
<meta charset="utf-8">
<title>Título</title>
</head>
<body>
...
</body>
</html>