As a MySQL ou Développeur PHP , une fois que vous dépassez les limites confortables des jeux de caractères uniquement en anglais, vous vous retrouvez rapidement empêtré dans le monde merveilleusement farfelu de l'encodage UTF-8.
Un apprêt UTF-8 rapideSur un précédent emploi , nous avons commencé à rencontrer des problèmes d'encodage des données lors de l'affichage des biographies d'artistes du monde entier. Il est vite devenu évident qu'il y avait des problèmes avec les données stockées, car parfois les données étaient correctement codées et parfois non.
Cela a conduit les programmeurs à implémenter un méli-mélo de correctifs, parfois avec JavaScript, parfois avec des balises méta HTML charset, parfois avec PHP, et ainsi de suite. Bientôt, nous nous sommes retrouvés avec une liste de 600 000 biographies d'artistes avec des informations à double ou triple codage, les données étant stockées de différentes manières selon qui a programmé la fonctionnalité ou implémenté le patch. Un nid de rat technique classique.
En effet, naviguer dans les problèmes d'encodage de données UTF-8 peut être une expérience frustrante et époustouflante. Cet article fournit un livre de recettes concis pour résoudre ces problèmes UTF-8 lorsque vous travaillez avec PHP et MySQL en particulier, basé sur l'expérience pratique et les leçons apprises (et grâce, en partie, aux informations découvertes Ici et Ici le long du chemin).
Plus précisément, nous aborderons les éléments suivants dans cet article:
php.ini
fichier et Code PHP .my.ini
fichier et autre Problèmes liés à MySQL à connaître (y compris les mods de configuration nécessaires si vous utilisez Sphinx )La première chose à faire est de modifier votre php.ini
fichier pour utiliser UTF-8 comme jeu de caractères par défaut:
default_charset = 'utf-8';
(Remarque: vous pouvez ensuite utiliser phpinfo()
pour vérifier que cela a été correctement défini.)
OK cool, donc maintenant PHP et UTF-8 devraient bien fonctionner ensemble. Droite?
Eh bien, pas exactement. En fait, même pas proche.
Bien que ce changement garantisse que PHP génère toujours UTF-8 comme encodage de caractères (dans les en-têtes de type de contenu de la réponse du navigateur), vous devez encore apporter un certain nombre de modifications à votre code PHP pour vous assurer qu'il traite et génère correctement UTF- 8 caractères.
En relation: Meilleures pratiques et astuces PHP par les développeurs ApeeScapePour être sûr que votre code PHP joue bien dans le bac à sable de codage de données UTF-8, voici ce que vous devez faire:
Définissez UTF-8 comme jeu de caractères pour tous les en-têtes générés par votre code PHP
Dans chaque en-tête de sortie PHP, spécifiez UTF-8 comme encodage:
header('Content-Type: text/html; charset=utf-8');
Spécifiez UTF-8 comme type de codage pour XML
vim vs emacs vs sublime
function utf8_for_xml($string) { return preg_replace('/[^x{0009}x{000a}x{000d}x{0020}-x{D7FF}x{E000}-x{FFFD}]+/u', ' ', $string); }
Supprimer les caractères non pris en charge de XML
Étant donné que tous les caractères UTF-8 ne sont pas acceptés dans un document XML, vous devrez supprimer ces caractères de tout XML que vous générez. Une fonction utile pour faire cela (que j'ai trouvé Ici ) est le suivant:
$safeString = utf8_for_xml($yourUnsafeString);
Voici comment vous pouvez utiliser cette fonction dans votre code:
comment concevoir une page de destination
htmlspecialchars
Spécifiez UTF-8 comme jeu de caractères pour tout le contenu HTML
Pour le contenu HTML, spécifiez UTF-8 comme encodage:
htmlspecialchars($str, ENT_NOQUOTES, 'UTF-8')
Dans les formulaires HTML, spécifiez UTF-8 comme encodage:
default_charset
Spécifiez UTF-8 comme encodage dans tous les appels à htmlspecialchars
par exemple .:
htmlentities
*Remarque: Depuis PHP 5.6.0, mysql_set_charset
La valeur est utilisée par défaut. A partir de PHP 5.4.0, UTF-8 était la valeur par défaut, mais avant PHP 5.4.0, ISO-8859-1 était utilisée par défaut. Il est donc judicieux de toujours spécifier explicitement UTF-8 pour être sûr, même si cet argument est techniquement facultatif.
Notez également que, pour UTF-8, $link = mysql_connect('localhost', 'user', 'password'); mysql_set_charset('utf8', $link);
et mysql_set_charset
peuvent être utilisés de manière interchangeable.
Définissez UTF-8 comme jeu de caractères par défaut pour toutes les connexions MySQL
Spécifiez UTF-8 comme jeu de caractères par défaut à utiliser lors de l'échange de données avec la base de données MySQL en utilisant mysqli::set_charset
:
$mysqli = new mysqli('localhost', 'my_user', 'my_password', 'test'); /* check connection */ if (mysqli_connect_errno()) { printf('Connect failed: %s
', mysqli_connect_error()); exit(); } /* change character set to utf8 */ if (!$mysqli->set_charset('utf8')) { printf('Error loading character set utf8: %s
', $mysqli->error); } else { printf('Current character set: %s
', $mysqli->character_set_name()); } $mysqli->close();
Notez que, depuis PHP 5.5.0, strlen
est obsolète et iconv
doit être utilisé à la place:
iconv_strlen
Utilisez toujours des versions compatibles UTF-8 des fonctions de manipulation de chaînes
Il y a plusieurs fonctions PHP qui échoueront, ou du moins ne se comporteront pas comme prévu, si la représentation de caractères a besoin de plus d'un octet (comme UTF-8). Un exemple est le mbstring
fonction qui renverra le nombre d'octets plutôt que le nombre de caractères.
Deux options sont disponibles pour gérer cela:
La my.ini
Les fonctions qui sont disponibles par défaut avec PHP fournissent des versions compatibles multi-octets de plusieurs de ces fonctions (par exemple, [client] default-character-set=UTF-8 [mysql] default-character-set=UTF-8 [mysqld] character-set-client-handshake = false #force encoding to uft8 character-set-server=UTF-8 collation-server=UTF-8_general_ci [mysqld_safe] default-character-set=UTF-8
, etc.). N'oubliez pas, cependant, que les chaînes que vous fournissez à ces fonctions doivent elles-mêmes être correctement codées.
Il y a aussi le my.ini
extension à PHP (des informations sur l'activation et la configuration sont disponibles Ici ). Cette extension fournit un ensemble complet de fonctions qui prennent correctement en compte le codage multi-octets.
Du côté MySQL / UTF-8, des modifications au mysql> show variables like 'char%';
sont requis comme suit:
Définissez les paramètres de configuration suivants après chaque balise correspondante:
| character_set_client | UTF-8 | character_set_connection | UTF-8 | character_set_database | UTF-8 | character_set_filesystem | binary | character_set_results | UTF-8 | character_set_server | UTF-8 | character_set_system | UTF-8 | character_sets_dir | /usr/share/mysql/charsets/
Après avoir apporté les modifications ci-dessus à votre latin1
fichier, redémarrez votre démon MySQL.
se référer aux données. l'élasticité-prix de la demande est relativement élastique :
Pour vérifier que tout a été correctement configuré pour utiliser l'encodage UTF-8, exécutez la requête suivante:
utf8mb4
La sortie devrait ressembler à quelque chose comme:
set names UTF-8;
Si vous voyez à la place sphinx.conf
répertorié pour l'un de ces éléments, vérifiez votre configuration et assurez-vous que vous avez correctement redémarré votre démon mysql.
MySQL UTF-8 est en fait une implémentation partielle du jeu de caractères UTF-8 complet. Plus précisément, le codage MySQL UTF-8 utilise un maximum de 3 octets, alors que 4 octets sont nécessaires pour coder le jeu de caractères UTF-8 complet. C'est bien pour tous les caractères de langue, mais si vous devez prendre en charge les symboles astraux (dont les points de code vont de U + 010000 à U + 10FFFF), ceux-ci nécessitent un codage à quatre octets qui n'est pas pris en charge dans MySQL UTF-8. Dans MySQL 5.5.3, ce problème a été résolu avec l'ajout de la prise en charge du utf8mb4 jeu de caractères qui utilise un maximum de quatre octets par caractère et prend ainsi en charge le jeu de caractères UTF-8 complet. Donc, si vous utilisez MySQL 5.5.3 ou une version ultérieure, utilisez charset_type = utf-8
au lieu de UTF-8 comme jeu de caractères de base de données / table / ligne. Plus d'informations sont disponibles Ici .
Si le client qui se connecte n'a aucun moyen de spécifier le codage pour sa communication avec MySQL, une fois la connexion établie, vous devrez peut-être exécuter la commande / requête suivante:
sql_query_pre = SET CHARACTER_SET_RESULTS=UTF-8 sql_query_pre = SET NAMES UTF-8
Lors de la détermination de la taille des champs varchar lors de la modélisation de la base de données, n'oubliez pas que les caractères UTF-8 peuvent nécessiter jusqu'à 4 octets par caractère.
Dans votre fichier de configuration Sphinx (c'est-à-dire charset_table
):
Définissez votre définition d'index pour avoir:
my.ini
Ajoutez ce qui suit à votre définition source:
ALTER SCHEMA `your-db-name` DEFAULT CHARACTER SET UTF-8;
Redémarrez le moteur et refaites tous les index.
Si vous souhaitez configurer sphinx de sorte que les lettres comme C c ć Ĉ ĉ Ċ ċ Č č soient toutes traitées comme équivalentes à des fins de recherche, vous devrez configurer un mysql> show variables like 'char%';
(a.k.a. caractère pliage) qui est essentiellement un mappage d'équivalence entre les caractères. Plus d'informations sont disponibles Ici .
Si vous avez une base de données MySQL existante qui est déjà encodée en latin1, voici comment convertir le latin1 en UTF-8:
Assurez-vous que vous avez apporté toutes les modifications aux paramètres de configuration dans votre mysqldump -u USERNAME -pDB_PASSWORD --opt --skip-set-charset --default-character-set=latin1 --skip-extended-insert DATABASENAME --tables TABLENAME > DUMP_FILE_TABLE.sql
fichier, comme décrit ci-dessus.
Exécutez la commande suivante:
mysqldump -u root --opt --skip-set-charset --default-character-set=latin1 --skip-extended-insert artists-database --tables tbl_artist > tbl_artist.sql
Via la ligne de commande, vérifiez que tout est correctement défini sur UTF-8
perl -i -pe 's/DEFAULT CHARSET=latin1/DEFAULT CHARSET=UTF-8/' DUMP_FILE_TABLE.sql
Créez un fichier de vidage avec le codage latin1 pour la table que vous souhaitez convertir:
mysql> source 'DUMP_FILE_TABLE.sql';
par exemple:
mysql> select count(*) from MY_TABLE where LENGTH(MY_FIELD) != CHAR_LENGTH(MY_FIELD);
Effectuez une recherche globale et remplacez le jeu de caractères dans le fichier de vidage de latin1 à UTF-8:
par exemple, en utilisant Perl:
les principes de l'accent sur la conception
create table temptable ( select * from MY_TABLE where LENGTH(MY_FIELD) != CHAR_LENGTH(MY_FIELD));
Remarque aux utilisateurs de Windows: Ce remplacement de chaîne de jeu de caractères (de latin1 à UTF-8) peut également être effectué à l'aide de rechercher et remplacer dans WordPad (ou dans un autre éditeur de texte, tel que vim). Assurez-vous de sauvegarder le fichier tel quel (ne le sauvegardez pas en tant que fichier txt unicode!).
À partir de là, nous commencerons à manipuler les données de la base de données, il serait donc probablement prudent de sauvegarder la base de données si vous ne l’avez pas déjà fait. Ensuite, restaurez le vidage dans la base de données:
alter table temptable modify temptable.ArtistName varchar(128) character set latin1;
Recherchez les enregistrements qui n'ont peut-être pas été convertis correctement et corrigez-les. Étant donné que les caractères non ASCII sont de par leur conception multi-octets, nous pouvons les trouver en comparant la longueur d'octet à la longueur des caractères (c'est-à-dire pour identifier les lignes qui peuvent contenir des caractères UTF-8 à double codage qui doivent être corrigés).
Vérifiez s'il existe des enregistrements avec des caractères multi-octets (si cette requête renvoie zéro, il ne semble pas y avoir d'enregistrements avec des caractères multi-octets dans votre table et vous pouvez passer à l'étape 8).
alter table temptable modify temptable.ArtistName blob; alter table temptable modify temptable.ArtistName varchar(128) character set UTF-8;
Copiez les lignes avec des caractères multi-octets dans une table temporaire:
delete from MY_TABLE where LENGTH(MY_FIELD) = CHAR_LENGTH(MY_FIELD);
Convertir les caractères UTF-8 à double codage en caractères UTF-8 appropriés
C'est en fait un peu délicat. Une chaîne codée en double est une chaîne qui a été correctement codée en UTF-8. Cependant, MySQL nous a alors fait la faveur erronée de le convertir (de quoi il pensée était latin1) en UTF-8 encore , lorsque nous définissons la colonne sur le codage UTF-8. Résoudre cela nécessite donc un processus en deux étapes par lequel nous «tromperons» MySQL afin de l'empêcher de nous faire cette «faveur».
Tout d'abord, nous redéfinissons le type d'encodage de la colonne sur latin1, supprimant ainsi le double encodage:
par exemple .:
replace into MY_TABLE (select * from temptable);
Remarque: veillez à utiliser le type de champ correct pour votre table. Dans l'exemple ci-dessus, pour notre tableau, le type de champ correct pour 'ArtistName' était varchar (128), mais le champ de votre tableau peut être du texte ou tout autre type. Assurez-vous de le spécifier correctement!
Le problème est que maintenant, si nous rétablissons le codage des colonnes sur UTF-8, MySQL exécutera à nouveau le codage des données latin1 en UTF-8 et nous reviendrons là où nous avons commencé. Pour éviter cela, nous changeons le type de colonne en blob et PUIS nous le définissons sur UTF-8. Cela exploite le fait que MySQL ne tentera pas d'encoder un objet blob. Nous sommes ainsi en mesure de «tromper» la conversion du jeu de caractères MySQL pour éviter le problème de double encodage.
par exemple .:
|_+_|
(Encore une fois, comme indiqué ci-dessus, assurez-vous d'utiliser le type de champ approprié pour votre table.)
Supprimez les lignes contenant uniquement des caractères à un octet de la table temporaire:
|_+_|
Réinsérez les lignes fixes dans la table d'origine (avant de faire cela, vous voudrez peut-être exécuter des sélections sur le tentable pour vérifier qu'il semble être correctement corrigé, tout comme une vérification de cohérence).
Vérifiez les données restantes et, si nécessaire, répétez le processus à l'étape 7 (cela peut être nécessaire, par exemple, si les données ont été codées trois fois). D'autres erreurs, le cas échéant, peuvent être plus faciles à résoudre manuellement.
Une autre chose à retenir et à vérifier est que vos fichiers de code source, vos fichiers de ressources, etc. sont tous correctement enregistrés avec le codage de données UTF-8. Sinon, les caractères «spéciaux» de ces fichiers risquent de ne pas être traités correctement.
Dans Netbeans, par exemple, vous pouvez cliquer avec le bouton droit de la souris sur votre projet, choisir les propriétés, puis dans «Sources», vous trouverez l'option de codage des données (elle est généralement par défaut UTF-8, mais cela vaut la peine de vérifier).
Ou dans le Bloc-notes de Windows, utilisez l'option «Enregistrer sous…» dans le menu Fichier et sélectionnez l'option d'encodage UTF-8 en bas de la boîte de dialogue. (Notez que l'option 'Unicode' fournie par le Bloc-notes est en fait UTF-16, ce n'est donc pas ce que vous voulez.)
Bien que cela puisse être quelque peu fastidieux, prendre le temps de suivre ces étapes pour résoudre systématiquement vos problèmes d'encodage de données MySQL et PHP UTF-8 peut finalement vous faire gagner beaucoup de temps et de peine. À long terme, ce type d'approche méthodique est de loin supérieur à la tendance bien trop courante de simplement continuer à patcher le système.
coût de l'examen d'associé d'architecte de solutions d'aws
Nous espérons que ce guide insiste sur l'importance de prendre en compte la définition du jeu de caractères lors de la configuration d'un environnement de projet en premier lieu et de travailler dans un environnement de projet logiciel qui prend correctement en compte le codage des caractères dans sa manipulation du texte et des chaînes.
En relation: Avant de déboguer PHP qui ne fonctionne pas, consultez cette liste des 10 erreurs les plus courantes commises par les développeurs PHPDéfini par le standard Unicode, UTF-8 est un encodage de caractères 8 bits capable de stocker un caractère Unicode. Il est rétrocompatible avec ASCII.
UTF est l'abréviation de Unicode Transformation Format, tandis que le suffixe «8» indique l'utilisation de blocs de 8 bits pour représenter des caractères.
Pour insérer des caractères Unicode dans MySQL, vous devez créer une table avec le support Unicode, sélectionner les paramètres de codage / collation appropriés et spécifier le jeu de caractères dans la connexion MySQL. Ensuite, vous pouvez continuer et utiliser du code PHP pour insérer Unicode à votre guise.