Guía completa UTF-8 para desarrolladores PHP: solución definitiva

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

¿Por qué tus tildes y eñes se convierten en "ñ" y cómo solucionarlo para siempre

\n\n

¿Alguna vez has abierto tu sitio web en PHP y en lugar de ver "¡Hola, mundo!" has visto algo como ¡Hola, mundo!? Si es así, ¡enhorabuena! Te has topado con el clásico problema del UTF-8 end-to-end. Es esa situación en la que la codificación se rompe en algún punto entre la base de datos y el navegador, y todos tienen la culpa, pero nadie quiere asumirla.

\n\n

En Stack Overflow, esta pregunta acumula miles de visitas y cientos de respuestas. Y no es para menos. Incluso desarrolladores experimentados se confunden a veces con la configuración de codificación. En este tutorial, te daremos una receta paso a paso para que PHP, MySQL y el navegador trabajen juntos y UTF-8 funcione en todas partes y siempre. Sin magia: solo la configuración correcta.

\n\n

Paso 1. Base de datos: el cimiento de tu codificación

\n\n

Todo empieza en la base de datos. Si en MySQL almacenas datos en latin1 o cp1251 e intentas mostrarlos en UTF-8, obtendrás caracteres extraños. Pero incluso si la base está en UTF-8, hay un detalle: la codificación antigua utf8 de MySQL no soporta emojis ni algunos caracteres especiales. La solución es utf8mb4.

\n\n

1.1. Crear tablas con la codificación correcta

\n\n

Al crear una nueva tabla, especifica siempre:

\n\n
CREATE TABLE articulos (\n    id INT AUTO_INCREMENT PRIMARY KEY,\n    titulo VARCHAR(255) NOT NULL,\n    contenido TEXT NOT NULL\n) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
\n\n

Otra opción es definir la codificación por defecto para toda la base de datos:

\n\n
ALTER DATABASE nombre_de_tu_base CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
\n\n

Importante: utf8mb4_unicode_ci es el collation (regla de comparación). Maneja correctamente todos los caracteres Unicode. Si no necesitas ordenación multilingüe, también puedes usar utf8mb4_general_ci.

\n\n

1.2. Convertir tablas existentes

\n\n

Si ya tienes datos en otra codificación, conviértelos primero:

\n\n
ALTER TABLE articulos CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
\n\n

Pero ten cuidado: si la tabla ya contenía datos en latin1, podrían convertirse en doble codificación (por ejemplo, ¡). En ese caso, primero debes pasar las columnas a binary y luego a utf8mb4. Es otra historia, pero para simplificar, asumamos que empiezas desde cero.

\n\n

Paso 2. Conexión PHP con la base: configurar PDO

\n\n

En PHP moderno usas PDO (o mysqli). Aquí hay un punto crítico: después de conectarte a la base, debes indicar explícitamente la codificación. De lo contrario, PHP se comunicará con MySQL en la codificación por defecto (generalmente latin1).

\n\n

2.1. Cadena de conexión PDO correcta

\n\n
$host = 'localhost';\n$dbname = 'tu_base';\n$username = 'root';\n$password = '';\n\n$dsn = "mysql:host=$host;dbname=$dbname;charset=utf8mb4";\n\n$options = [\n    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,\n    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,\n    PDO::ATTR_EMULATE_PREPARES => false,\n];\n\ntry {\n    $pdo = new PDO($dsn, $username, $password, $options);\n} catch (PDOException $e) {\n    echo "Conexión fallida: " . $e->getMessage();\n}
\n\n

Fíjate en charset=utf8mb4 en el DSN. Esto obliga a PHP y MySQL a acordar la codificación a nivel de conexión.

\n\n

2.2. Método alternativo (si el DSN no funciona)

\n\n

A veces, versiones antiguas de PHP o servidores no leen el charset del DSN. En ese caso, añade después de la conexión:

\n\n
$pdo->exec("SET NAMES 'utf8mb4'");
\n\n

Pero el primer método es preferible: es más limpio y moderno.

\n\n

Paso 3. Cabeceras HTTP y HTML: decirle la verdad al navegador

\n\n

Incluso si la base y PHP funcionan en UTF-8, el navegador podría decidir que

Blogs

Book Recommendations