J'installe un nouveau serveur et souhaite prendre en charge UTF-8 entièrement dans mon application Web. J'ai essayé cela dans le passé sur des serveurs existants et il me semble toujours devoir revenir à ISO-8859-1.
Où dois-je exactement définir le codage / les jeux de caractères? Je suis conscient que je dois configurer Apache, MySQL et PHP pour ce faire - y a-t-il une liste de contrôle standard que je peux suivre, ou peut-être dépanner où les disparités se produisent?
Il s'agit d'un nouveau serveur Linux, exécutant MySQL 5, PHP, 5 et Apache 2.
utf-8
séparément pour chacun d'eux - MySQL 5, PHP 5 OU Apache 2.Réponses:
Stockage de données :
Spécifiez le
utf8mb4
jeu de caractères sur toutes les tables et colonnes de texte de votre base de données. Cela fait que MySQL stocke et récupère physiquement les valeurs encodées nativement en UTF-8. Notez que MySQL utilisera implicitement l'utf8mb4
encodage si unutf8mb4_*
classement est spécifié (sans aucun jeu de caractères explicite).Dans les anciennes versions de MySQL (<5.5.3), vous serez malheureusement obligé d'utiliser simplement
utf8
, qui ne prend en charge qu'un sous-ensemble de caractères Unicode. Je souhaite que je plaisante.Accès aux données :
Dans votre code d'application (par exemple PHP), quelle que soit la méthode d'accès à la base de données que vous utilisez, vous devrez définir le jeu de caractères de connexion sur
utf8mb4
. De cette façon, MySQL n'effectue aucune conversion à partir de son UTF-8 natif lorsqu'il transfère des données à votre application et vice versa.Certains pilotes fournissent leur propre mécanisme de configuration du jeu de caractères de connexion, qui à la fois met à jour son propre état interne et informe MySQL du codage à utiliser sur la connexion - c'est généralement l'approche préférée. En PHP:
Si vous utilisez la couche d'abstraction PDO avec PHP ≥ 5.3.6, vous pouvez spécifier
charset
dans le DSN :Si vous utilisez mysqli , vous pouvez appeler
set_charset()
:Si vous êtes bloqué avec mysql ordinaire mais que vous utilisez PHP ≥ 5.2.3, vous pouvez appeler
mysql_set_charset
.Si le conducteur ne fournit pas son propre mécanisme de fixation du jeu de caractères de connexion, vous pouvez avoir à émettre une requête pour indiquer à MySQL comment votre application attend des données sur la connexion à coder:
SET NAMES 'utf8mb4'
.La même considération concernant
utf8mb4
/utf8
s'applique que ci-dessus.Sortie :
Si votre application transmet du texte à d'autres systèmes, ils devront également être informés du codage des caractères. Avec les applications Web, le navigateur doit être informé de l'encodage dans lequel les données sont envoyées (via les en-têtes de réponse HTTP ou les métadonnées HTML ).
En PHP, vous pouvez utiliser l'
default_charset
option php.ini ou émettre manuellement l'Content-Type
en-tête MIME vous-même, ce qui est juste plus de travail mais a le même effet.Lors de l'encodage de la sortie à l'aide de
json_encode()
, ajoutezJSON_UNESCAPED_UNICODE
comme deuxième paramètre.Entrée :
Malheureusement, vous devez vérifier que chaque chaîne reçue est UTF-8 valide avant d'essayer de la stocker ou de l'utiliser n'importe où. PHP
mb_check_encoding()
fait l'affaire, mais vous devez l'utiliser religieusement. Il n'y a vraiment aucun moyen de contourner cela, car les clients malveillants peuvent soumettre des données dans l'encodage de leur choix, et je n'ai trouvé aucune astuce pour que PHP le fasse pour vous de manière fiable.D'après ma lecture de la spécification HTML actuelle , les sous-puces suivantes ne sont plus nécessaires ni même valables pour le HTML moderne. Ma compréhension est que les navigateurs travailleront avec et soumettront des données dans le jeu de caractères spécifié pour le document. Cependant, si vous ciblez des versions plus anciennes de HTML (XHTML, HTML4, etc.), ces points peuvent toujours être utiles:
accept-charset
attribut à tous vos<form>
tags:<form ... accept-charset="UTF-8">
.<form>
étiquette.Autres considérations relatives au code :
De toute évidence, tous les fichiers que vous allez servir (PHP, HTML, JavaScript, etc.) doivent être encodés en UTF-8 valide.
Vous devez vous assurer que chaque fois que vous traitez une chaîne UTF-8, vous le faites en toute sécurité. C'est malheureusement la partie la plus difficile. Vous voudrez probablement faire un usage intensif de l'
mbstring
extension PHP .Les opérations de chaîne intégrées de PHP ne sont pas par défaut sécurisées UTF-8. Il y a certaines choses que vous pouvez faire en toute sécurité avec les opérations de chaîne PHP normales (comme la concaténation), mais pour la plupart des choses, vous devez utiliser la
mbstring
fonction équivalente .Pour savoir ce que vous faites (lire: ne pas le gâcher), vous devez vraiment connaître l'UTF-8 et comment il fonctionne au niveau le plus bas possible. Consultez l'un des liens de utf8.com pour de bonnes ressources pour apprendre tout ce que vous devez savoir.
la source
Je voudrais ajouter une chose à l'excellente réponse de chazomaticus :
N'oubliez pas non plus la balise META (comme celle-ci, ou sa version HTML4 ou XHTML ):
Cela semble anodin, mais IE7 m'a déjà posé des problèmes avec cela.
Je faisais tout bien; la base de données, la connexion à la base de données et l'en-tête HTTP Content-Type étaient tous définis sur UTF-8, et cela fonctionnait bien dans tous les autres navigateurs, mais Internet Explorer insistait toujours pour utiliser l'encodage "Europe occidentale".
Il s'est avéré que la page n'avait pas la balise META. L'ajout a résolu le problème.
Éditer:
Le W3C a en fait une assez grande section dédiée à l'I18N . Ils ont un certain nombre d'articles liés à ce problème - décrivant le côté HTTP, (X) HTML et CSS des choses:
Ils recommandent d'utiliser à la fois l'en-tête HTTP et la balise Meta HTML (ou la déclaration XML dans le cas où XHTML est utilisé comme XML).
la source
En plus de la configuration
default_charset
dans php.ini, vous pouvez envoyer le jeu de caractères correct à l'aideheader()
de votre code, avant toute sortie:Travailler avec Unicode en PHP est facile tant que vous réalisez que la plupart des fonctions de chaîne ne fonctionnent pas avec Unicode, et certaines peuvent complètement supprimer les chaînes . PHP considère que les "caractères" font 1 octet de long. Parfois, cela
explode()
ne pose aucun problème (par exemple, ne recherche qu'une séquence d'octets et l'utilise comme séparateur - donc peu importe les caractères réels que vous recherchez). Mais d'autres fois, lorsque la fonction est réellement conçue pour fonctionner sur des caractères , PHP n'a aucune idée que votre texte contient des caractères multi-octets trouvés avec Unicode.Phputf8 est une bonne bibliothèque à vérifier . Cela réécrit toutes les "mauvaises" fonctions afin que vous puissiez travailler en toute sécurité sur les chaînes UTF8. Il y a des extensions comme l'extension mbstring qui essaient de le faire pour vous aussi, mais je préfère utiliser la bibliothèque car elle est plus portable (mais j'écris des produits grand public, donc c'est important pour moi). Mais phputf8 peut utiliser mbstring en coulisses, de toute façon, pour augmenter les performances.
la source
J'ai trouvé un problème avec quelqu'un utilisant PDO et la réponse a été d'utiliser ceci pour la chaîne de connexion PDO:
Le site sur lequel j'ai pris ceci est en panne, mais j'ai pu l'obtenir en utilisant le cache Google, heureusement.
la source
$dbh->exec("set names utf8");
; je préfère la méthode présentée ici). Btw. il y a aussi une note similaire à ce sujet en tant que commentaire dans le manuel PHP: php.net/manual/en/pdo.construct.php#96325 .Dans mon cas, j'utilisais
mb_split
, qui utilise l'expression régulière. Par conséquent, j'ai également dû manuellement m'assurer que l'encodage regex était utf-8 en faisantmb_regex_encoding('UTF-8');
En remarque, j'ai également découvert en exécutant
mb_internal_encoding()
que l'encodage interne n'était pas utf-8, et j'ai changé cela en exécutantmb_internal_encoding("UTF-8");
.la source
Tout d'abord si vous êtes <5.3PHP alors non. Vous avez une tonne de problèmes à résoudre.
Je suis surpris que personne n'ait mentionné la bibliothèque intl , celle qui prend bien en charge l' unicode , les graphèmes , les opérations de chaîne , la localisation et bien d'autres, voir ci-dessous.
Je vais citer quelques informations sur la prise en charge unicode en PHP par les diapositives d' Elizabeth Smith sur PHPBenelux'14
INTL
Bien:
Mauvais:
mb_string
ICONV
stream_filter_append($fp, 'convert.iconv.ISO-2022-JP/EUC-JP')
BASES DE DONNÉES
Quelques autres Gotchas
Je mettrai à jour cette réponse au cas où les choses changeraient, les fonctionnalités ajoutées, etc.
la source
--with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd
options.La seule chose que j'ajouterais à ces réponses incroyables est de mettre l'accent sur l'enregistrement de vos fichiers dans l'encodage utf8, j'ai remarqué que les navigateurs acceptent cette propriété plutôt que de définir utf8 comme encodage de code. Tout éditeur de texte décent vous le montrera, par exemple Notepad ++ a une option de menu pour la liaison de fichiers, il vous montre l'encodage actuel et vous permet de le changer. Pour tous mes fichiers php, j'utilise utf8 sans BOM.
Il y a quelque temps, quelqu'un m'a demandé d'ajouter le support utf8 pour une application php / mysql conçue par quelqu'un d'autre, j'ai remarqué que tous les fichiers étaient encodés en ANSI, j'ai donc dû utiliser ICONV pour convertir tous les fichiers, changer les tables de base de données pour utiliser le utf8 charset et utf8_general_ci collate, ajoutez 'SET NAMES utf8' à la couche d'abstraction de la base de données après la connexion (si vous utilisez 5.3.6 ou une version antérieure sinon vous devez utiliser charset = utf8 dans la chaîne de connexion) et changer les fonctions de chaîne pour utiliser le multi-octet php fonctions de chaîne équivalentes.
la source
J'ai récemment découvert qu'en utilisant
strtolower()
peut provoquer des problèmes où les données sont tronquées après un caractère spécial.La solution consistait à utiliser
la source
Je viens de passer par le même problème et j'ai trouvé une bonne solution dans les manuels PHP.
J'ai changé tout mon encodage de fichier en UTF8 puis l'encodage par défaut sur ma connexion. Cela a résolu tous les problèmes.
Voir la source
la source
set_charset('utf8mb4')
n'a pas fonctionné mais>set_charset("utf8")
a fonctionné et cela n'a pas été montré dans les autres réponses.set_charset("utf8")
peut fonctionner mais se comportera différemment (voir les remarques sur la différence entreutf8
etutf8mb4
et l'historique des versions de mysql). À utiliserutf8
si vous devez ET UNIQUEMENT si vous savez ce que vous faites !En PHP, vous devrez soit utiliser les fonctions multi - octets , soit activer mbstring.func_overload . De cette façon, des choses comme strlen fonctionneront si vous avez des caractères qui prennent plus d'un octet.
Vous devrez également identifier le jeu de caractères de vos réponses. Vous pouvez soit utiliser AddDefaultCharset, comme ci-dessus, soit écrire du code PHP qui renvoie l'en-tête. (Ou vous pouvez ajouter une balise META à vos documents HTML.)
la source
Le support Unicode en PHP est toujours un énorme gâchis. Bien qu'il soit capable de convertir une chaîne ISO8859 (qu'il utilise en interne) en utf8, il n'a pas la capacité de fonctionner en mode natif avec des chaînes unicode, ce qui signifie que toutes les fonctions de traitement de chaîne vont altérer et corrompre vos chaînes. Vous devez donc soit utiliser une bibliothèque distincte pour une prise en charge appropriée de utf8, soit réécrire toutes les fonctions de gestion des chaînes vous-même.
La partie facile consiste simplement à spécifier le jeu de caractères dans les en-têtes HTTP et dans la base de données, etc. C'est la partie difficile, et PHP ne vous y aide pratiquement pas. (Je pense que PHP6 est censé résoudre le pire de tout cela, mais c'est encore un peu plus loin)
la source
Si vous souhaitez que le serveur MySQL décide du jeu de caractères, et non PHP en tant que client (ancien comportement; préféré, à mon avis), essayez d'ajouter
skip-character-set-client-handshake
à votremy.cnf
, sous[mysqld]
et redémarrezmysql
.Cela peut entraîner des problèmes si vous utilisez autre chose que UTF8.
la source
La première réponse est excellente. Voici ce que je devais faire sur une configuration debian / php / mysql régulière:
c'était tout !
la source
si vous voulez une solution mysql, j'ai eu des problèmes similaires avec 2 de mes projets, après une migration de serveur. Après avoir cherché et essayé beaucoup de solutions, je suis tombé sur celui-ci / rien avant que celui-ci ne fonctionne):
Après avoir ajouté cette ligne à mon fichier de configuration, tout fonctionne bien!
J'ai trouvé cette solution https://www.w3schools.com/PHP/func_mysqli_set_charset.asp lorsque je cherchais à résoudre un insert à partir d'une requête html
bonne chance!
la source
Juste une note:
Vous êtes face au problème de vos personnages non-latin est montrant que
?????????
, vous avez posé une question, et il a été fermé avec une référence à cette question canonique, vous avez tout essayé et peu importe ce que vous faites vous obtenez toujours??????????
deMySQL
.C'est principalement parce que vous testez vos anciennes données qui ont été insérées dans la base de données en utilisant le mauvais jeu de caractères et qui ont été converties et stockées en fait les caractères du point d'interrogation
?
. Ce qui signifie que vous avez perdu votre texte d'origine pour toujours et peu importe ce que vous essayez, vous obtiendrez???????
.réappliquer ce que vous avez appris des réponses de cette question sur de nouvelles données pourrait résoudre votre problème.
la source
J'ai eu ce problème lors de l'affichage des tableaux. Je viens de mettre cela sur chaque variable de sortie d'écho:
la source