Salut tout le monde,

Avant de devenir complètement fou et d'envisager le suicide au gaz, je vous soumets mon problème.
Je développe depuis 2 ans l'intranet de ma boite, sous MacOSX avec JEdit. De simples scripts PHP, une pincée de java, le tout attaquant une base de données MySQL.
Tout ce petit monde est en UTF-8 depuis le début, et tout se passait à merveille.

Ensuite, j'ai fait quelques changements (j'ai notamment ajouté des scripts java de chez jquery) et depuis c'est un truc de fou :
-la lecture de ma database (la même qu'avant) s'affiche mal. Pour avoir un bon affichage, je dois changer manuellement l'encodage de mon browser en windows-1250 ou ISO-8859-1 (les deux fonctionnent)
-l'écriture dans ma database se passe mal aussi, les accents sont tout pourris quand je lis les nouvelles entrées de ma DB direct avec phpMyAdmin.

Après avoir lu pas mal de ces pages, j'ai tout vérifié : tous mes fichiers .JS et .php sont en UTF8, j'ai viré presque tous les accents des commentaires PHP, toute ma base de données est en UTF8 et j'ai même essayé avec la base de donnée qui me servait avant les modifs et qui était un peu bancale (pas UTF8 partout), même résultat.

Bref, je deviens fou et je ne sais plus ou chercher...

Heeelllp !!

Merci d'avance pour vos lumières

El Manu
Modifié par elmanu (02 Mar 2011 - 17:14)
Tes caractères accentués s'affichent comment dans le navigateur (tu as plutôt quelques chose comme î ou plutôt des losanges avec des points d'interrogations) ?

Et quand tu regardes le contenu de ta base les accents ressemblent à quoi ?

PS : Tu confonds Java et Javascript.

Java
Javascript
alors, sur ma page web, les accents s'affichent tous en losange avec un point d'interrogation.
Par contre, quand j'écris une nouvelle entrée dans ma database avec des accents, ils se lisent correctement sur ma page ouaibe, mais dans la DB ils sont du genre î...

(au temps pour moi pour la java, c'est effectivement du javascript)
Bonjour,

Le piège avec MySQL c'est que, par défaut, il va effectuer des transcodages quand il reçoit des données qu'il croit être dans un codage A et qu'il pense devoir fournir des données dans un codage B. (Ça vaut en lecture et en écriture.) Pour éviter ça, il faut vérifier tout un tas de trucs et s'assurer qu'on travaille bien avec le même codage à toutes les étapes.

- Les tables et champs de la base ont bien un interclassement UTF-8 (utf8_unicode_ci ou utf8_general_ci notamment)?
- Le serveur MySQL est configuré (de manière globale) pour ouvrir des connexions en UTF-8?
- L'outil que tu utilises pour parcourir et modifier ta base de données ouvre bien une connexion en UTF-8?
- Ton application PHP ouvre bien des connexions MySQL en UTF-8?
- Tu as pu vérifier de manière fiable que tes données en base sont bien en UTF-8 (ou minimum avec un script de test qui ouvre une connexion en UTF-8)?

PS: il y a au moins une centaine de sujets sur ce thème sur ce forum. Une recherche peut donner quelques précisions.
Modifié par fvsch (28 Feb 2011 - 18:54)
à priori (je dis à priori parce que je n'ai pas tout vérifié ce dont tu parles) oui.
Le système fonctionnait très bien avant, et encore, avec une base de données "bancale" (tout n'était pas en UTF8, certaines tables étaient en latin1_sweedish_ci)

C'est juste mon nouveau système qui intègre de nouveaux fichiers, notamment javascript, qui ne lis plus cette base correctement, et c'est là ou je m'arrache les cheveux..

Mais je vais vérifier l'ensemble..
bon, j'avance un peu, toujours sans résultats :

je suis passé sous Linux et j'ai vérifié mes encodages avec la fonction file -i
je découvre avec stupeur que la plupart de mes fichiers sont en us-ascii, quelques autres en utf-8

Je découvre avec encore plus de stupeur que lorsque j'essaie de les ré-encoder avec un bon vieux iconv -f us-ascii -t utf-8, le fichier reste en us-ascii

-est-ce que mon problème peut venir de là ?
-comment recoder mes fichiers ? (je vais essayer de ce pas la commande recode)
elmanu a écrit :
je découvre avec stupeur que la plupart de mes fichiers sont en us-ascii, quelques autres en utf-8

UTF-8 est rétrocompatible avec ASCII. C'est à dire que tous les caractères de ASCII existent dans UTF-8 et ont la même valeur numérique (ils sont codés avec le même octet). Si tu convertis un fichier de ASCII à UTF-8, rien ne change. Et si ton fichier UTF-8 ne contient que des caractères ASCII, il peut être détecté comme étant en ASCII.

(On peut lire les pages de Wikipedia sur ASCII, ISO-8859-1 et UTF-8, pour la route.)

Donc d'après ce test les données en base seraient bien en UTF-8.
Il faut donc s'assurer:
- que tous les interclassement sont marqués en UTF-8 (certains sont peut-être marqués en latin1_machinchose pour les tables et colonnes qui ne contiennent que des données numériques, ça arrive);
- que les connexions entre le client (phpMyAdmin, ton application, etc.) et le serveur MySQL sont toujours en UTF-8 (voir du côté de SET NAMES).
Okay, au temps pour moi : pour être vraiment sur de moi j'avais viré tous les accents de mes fichiers php (dans les commentaires). Il m'a suffit d'en mettre juste un pour constater le changement, file -i me le donne en UTF-8

-toutes mes tables sont en interclassement UTF-8 (d'ailleurs, y a-t-il une différence entre utf8_general_ci et utf8_unicode_ci ? Tout doit être exactement pareil dans toute la base ?)

-je vais chercker les SET NAMES, mais finalement, peut-être que c'est ma façon de les stocker dans la database qui ne va pas depuis le début...

pour créer une entrée, je récupère un formulaire de la page d'avant, puis fait pour chaque variable
$variable = addslashes($_POST['variable']);

et ensuite je crée
mysql_query("INSERT INTO maTable VALUES('', '" .$variable1. "', '" .$variable2"')");

Pour le moment, ça m'écrit les accents dans la table en ©A ou autre, mais quand je les lis, ils sont correctement lus.
Pour les lire (dans un tableau)
$sql = "
SELECT *
FROM maTable {$tri} ORDER BY entree_id DESC";
$retour = mysql_query($sql);

while ( $row = mysql_fetch_array($retour))
{
<td><?php echo stripslashes($row['variable']); ?></td>
etc..

Si quelqu'un voit un souci quelque part...
En creusant un peu...je vérifie les variables et réglages de mon serveur MySQL distant :
character set client utf8
(Valeur globale) latin1
character set connection utf8
(Valeur globale) latin1
character set database latin1
character set filesystem binary
character set results utf8
(Valeur globale) latin1
character set server latin1
character set system utf8
character sets dir /usr/share/mysql/charsets/
collation connection utf8_general_ci
(Valeur globale) latin1_swedish_ci
collation database latin1_swedish_ci
collation server latin1_swedish_ci

Y'a un souci, non ?
(j'aime bien parler tout seul dans mon topic, épisode 4 Smiley cligne )

J'ai *presque* résolu mon problème...
Il m'a suffit de reprendre à la base tout mon truc et de faire pas à pas les étapes pour voir ce qu'il manquait à mon nouveau système par rapport à l'ancien, notemment la manière de se connecter à la base de données...
Bingo, un petit ajout de mysql_query("set names 'utf8'"); après le connect et select me corrige mon souci d'accents (yalllahhhhhhhhh !!)

Par contre, dernier point à corriger, les apostrophes sont gérés de manière différente par rapport à avant : "c'est" m'apparaît dans la DB comme "c\'est" alors qu'avant, non.

-est-ce qu'avant, j'étais VRAIMENT en UTF-8 ?
-avant de me lancer dans la conversion de la database pour ajouter un \ devant tous les ', je voulais savoir si cette notation était normale en UTF8, ou si c'est que j'ai encore un dernier souci.

A vous les studios !
(je résouds la fin du problème comme un grand, épisode final)

Bien. J'ai donc regardé mon code de plus près.
Si tout est en UTF8 de partout, vu qu'avant d'insérer quoi que ce soit dans ma database, je lui passe un addslashes, il me semble normal de retrouver \' dans ma database à la place d'un simple apostrophe.
La vraie question étant : pourquoi je fais ça (addslashes) à la base ? (mais là n'est pas le sujet du topic)

Dans mon système d'avant, j'étais bien à priori en UTF8 pour les connections, mais ma DB ne l'était pas entièrement. Ma fonction addslashes n'ajoutait rien devant les apostrophes et guillemets.

Mon nouveau système sait lire comme il faut la DB, qu'il y ait ou non d'antislash devant les ', et ça me convient.

Si vous trouvez la chose curieuse et/ou pouvant me causer des soucis plus tard, vous pouvez vous signaler ! Smiley cligne

En attendant, merci pour vos réponses qui m'ont permis de fouiller un peu et de trouver.

EDIT : retrouver \' dans ma database à la place d'un simple apostrophe n'est pas normal du tout, c'est simplement parce que sur ma plateforme de dev', magic_quotes_gpc est à "on" donc je double ma protection des ' ou " avec mon addslashes, et que sur ma plateforme de prod, c'est à "off", donc j'avais une bonne raison d'utiliser addslashes, et c'est pourquoi je n'avais pas le souci dans mon ancien système. End of the story. Applaudissements. Rideau Smiley cligne
Modifié par elmanu (02 Mar 2011 - 17:32)
elmanu a écrit :
-toutes mes tables sont en interclassement UTF-8 (d'ailleurs, y a-t-il une différence entre utf8_general_ci et utf8_unicode_ci ? Tout doit être exactement pareil dans toute la base ?

L'interclassement détermine le tri des caractères pour les classements ascendants et descendants (autrement dit, pour les caractères latins, ça détermine l'ordre alphabétique). utf8_unicode_ci trie en fonction du numéro Unicode du caractère (il triera dans cet ordre: "a, b, c, ..., A, B, C, ... À, ...") ; utf8_general_ci est plus complexe et permet d'obtenir des tris alphabétiques plus cohérents (en simplifiant un peu: "a, A, À, b, B, ..."). Le premier est un peu plus rapide, mais en général on peut utiliser utf8_general_ci les yeux fermés. Enfin, pas de problème particulier si on utilise l'un et l'autre sur différentes tables.