Des accents remplacés par des é ou des ? viennent presque toujours d'un désaccord d'encodage entre votre code, la connexion à la base et la base elle-même. Voici les trois endroits à mettre d'accord.
La règle : employez utf8mb4 partout. C'est l'UTF-8 complet de MySQL, celui qui accepte aussi les emoji et les caractères asiatiques rares, là où l'ancien utf8 de MySQL s'arrêtait à trois octets.
En bref : mettez d'accord les trois maillons : la connexion PHP en utf8mb4 (dans le DSN ou avec set_charset()), la base et ses tables converties en utf8mb4 après une sauvegarde, et les pages déclarées en UTF-8 (<meta charset="utf-8">, fichiers sans BOM).
Comment régler l'encodage de la connexion depuis PHP ?
C'est le point le plus souvent oublié : même si la base est en UTF-8, la connexion peut négocier un autre jeu de caractères.
Avec PDO, déclarez l'encodage dans le DSN :
$pdo = new PDO(
'mysql:host=localhost;dbname=ma_base;charset=utf8mb4',
$utilisateur,
$motdepasse,
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
Avec mysqli :
$mysqli = new mysqli('localhost', $utilisateur, $motdepasse, 'ma_base');
$mysqli->set_charset('utf8mb4');
N'utilisez plus mysql_query("SET NAMES utf8"). L'extension mysql_* a été supprimée de PHP 7 : ce code ne s'exécute simplement plus. Et même du temps de PHP 5, SET NAMES laissait la fonction d'échappement dans l'ignorance du changement, ce qui pouvait ouvrir une faille d'injection SQL. Préférez charset=utf8mb4 dans le DSN, ou set_charset().
Comment convertir la base et les tables en utf8mb4 ?
Vérifiez l'interclassement depuis phpMyAdmin, accessible dans la console Apanel : Gestion de l'hébergement > Bases de données > phpMyAdmin.
Les bases créées depuis la console Apanel le sont en utf8 (interclassement utf8_general_ci), l'ancien utf8 de MySQL limité à trois octets : c'est ce qui fait disparaître les emoji. Pour les accepter, convertissez la base et ses tables en utf8mb4 comme ci-dessous.
Pour convertir une table existante :
ALTER TABLE ma_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Et pour que les futures tables suivent :
ALTER DATABASE ma_base CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Sauvegardez avant de convertir. Si les données ont déjà été enregistrées avec le mauvais encodage, une conversion peut figer la corruption au lieu de la corriger. La console permet de restaurer une base : voir Restaurer une base de données.
Comment déclarer l'encodage des pages au navigateur ?
Déclarez l'encodage dans vos pages :
<meta charset="utf-8">
Et assurez-vous que vos fichiers sources sont eux-mêmes enregistrés en UTF-8 sans BOM : la plupart des éditeurs proposent ce choix au moment de l'enregistrement.
Le serveur, lui, annonce déjà UTF-8 par défaut. Ce réglage, Jeu de caractères par défaut, se trouve dans Gestion de l'hébergement > Site web > Configuration Apache, à ne modifier que si votre site est réellement dans un autre encodage.
Comment reconnaître le problème ?
| Ce que vous voyez |
Ce qui se passe |
é à la place de é |
Du texte UTF-8 est affiché comme s'il était en ISO-8859-1. La donnée est saine : c'est la déclaration d'encodage qui manque. |
? ou � |
Le caractère a été perdu à l'écriture. La donnée est abîmée en base : il faut la ré-enregistrer après avoir corrigé la connexion. |
| Les emoji disparaissent, le reste va bien |
La table est en utf8 (3 octets) et non en utf8mb4. |
Pour aller plus loin