Pourquoi vos caractères spéciaux deviennent des "Привет" et comment y remédier définitivement
\n\nAvez-vous déjà ouvert votre site PHP et vu, au lieu du classique "Bonjour le monde !", quelque chose comme Привет, РјРёСЂ! ? Si oui, félicitations, vous avez rencontré le fameux problème UTF-8 all the way through. C'est cette situation où l'encodage se casse quelque part entre la base de données et le navigateur, et tout le monde est responsable, mais personne ne veut l'admettre.
Sur Stack Overflow, cette question cumule des milliers de vues et des centaines de réponses. Et pour cause. Même les développeurs expérimentés s'y perdent parfois. Dans ce tutoriel, nous allons voir une recette pas à pas pour faire collaborer PHP, MySQL et le navigateur, afin que UTF-8 fonctionne partout et tout le temps. Pas de magie, que des réglages précis.
\n\nÉtape 1. La base de données : le fondement de votre encodage
\n\nTout commence par la base. Si vos données MySQL sont stockées en latin1 ou cp1251 et que vous essayez de les afficher en UTF-8, vous obtiendrez des caractères illisibles. Mais même si la base est en UTF-8, attention : l'ancien encodage utf8 de MySQL ne supporte pas les emojis ni certains caractères rares. La solution est utf8mb4.
1.1. Créer des tables avec le bon encodage
\n\nLors de la création d'une nouvelle table, spécifiez toujours :
\n\nCREATE TABLE articles (\n id INT AUTO_INCREMENT PRIMARY KEY,\n title VARCHAR(255) NOT NULL,\n content TEXT NOT NULL\n) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n\nAlternative : définir l'encodage par défaut pour toute la base de données :
\n\nALTER DATABASE your_database_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n\nImportant : utf8mb4_unicode_ci est une collation (règle de comparaison). Elle gère correctement tous les caractères Unicode. Si vous n'avez pas besoin de tri multilingue, utf8mb4_general_ci peut suffire.
1.2. Convertir des tables existantes
\n\nSi vous avez déjà des données dans un autre encodage, convertissez-les d'abord :
\n\nALTER TABLE articles CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n\nMais attention : si la table contenait déjà des données en latin1, elles pourraient se transformer en double encodage (ex. Привет). Dans ce cas, il faut d'abord passer les colonnes en binaire, puis en utf8mb4. C'est une autre histoire, mais pour simplifier, partons du principe que vous partez d'une base vierge.
Étape 2. Connexion PHP à la base : configuration de PDO
\n\nEn PHP moderne, vous utilisez PDO (ou mysqli). Et ici, un point crucial : après la connexion à la base, vous devez explicitement définir l'encodage. Sinon, PHP communiquera avec MySQL dans l'encodage par défaut (souvent latin1).
\n\n2.1. Chaîne de connexion PDO correcte
\n\n$host = 'localhost';\n$dbname = 'your_database';\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 "Connection failed: " . $e->getMessage();\n}\n\nNotez le charset=utf8mb4 dans le DSN. Cela force PHP et MySQL à s'accorder sur l'encodage au niveau de la connexion.
2.2. Méthode alternative (si le DSN ne fonctionne pas)
\n\nParfois, les anciennes versions de PHP ou de serveurs ne lisent pas le charset depuis le DSN. Dans ce cas, ajoutez après la connexion :
\n\n$pdo->exec("SET NAMES 'utf8mb4'");\n\nMais la première méthode est préférable : plus propre et plus moderne.
\n\nÉtape 3. En-têtes HTTP et HTML : dites la vérité au navigateur
\n\nMême si la base et PHP fonctionnent en UTF-8, le navigateur peut décider que