UTF-8 tout le chemin à travers

Je mets en place un nouveau serveur, et je veux prendre en charge L'UTF-8 entièrement dans mon application web. J'ai essayé dans le passé sur des serveurs existants et semble toujours finir par devoir retomber à ISO-8859-1.

Où dois-je mettre l'encodage/les jeux de caractères? Je suis conscient que J'ai besoin de configurer Apache, MySQL et PHP pour le faire - y a-t-il une liste de contrôle standard que je peux suivre, ou peut-être dépanner où les inadéquations se produisent?

C'est pour un nouveau serveur Linux, tournant MySQL 5, PHP 5 et Apache 2.

1017
demandé sur Machavity 2008-11-11 00:04:56
la source

13 ответов

Stockage De Données :

  • spécifiez le jeu de caractères utf8mb4 sur toutes les tables et les colonnes de texte dans votre base de données. Cela permet à MySQL de stocker et de récupérer physiquement des valeurs encodées nativement en UTF-8. Notez que MySQL utilisera implicitement l'encodage utf8mb4 si une collation utf8mb4_* est spécifiée (sans jeu de caractères explicite).

  • dans les versions plus anciennes de MySQL (<5.5.3), vous serez malheureusement forcé d'utiliser simplement utf8 , qui ne supporte qu'un sous-ensemble de caractères Unicode. Je souhaite que j'étais une blague.

Accès Aux Données :

  • dans votre code d'application (par exemple PHP), quelle que soit la méthode D'accès DB que vous utilisez, vous devrez définir le jeu de caractères de connexion à utf8mb4 . De cette façon, MySQL ne se convertit pas de son natif UTF-8 quand il remet des données à votre application et vice versa.

  • certains pilotes fournissent leur propre mécanisme pour configurer le jeu de caractères de connexion, qui à la fois met à jour son propre état interne et informe MySQL de l'encodage à utiliser sur la connexion-c'est généralement l'approche préférée. En PHP:

    • si vous utilisez la PDO couche d'abstraction avec PHP ≥ 5.3.6, vous pouvez spécifier charset dans le DSN :

      $dbh = new PDO('mysql:charset=utf8mb4');
      
    • si vous utilisez mysqli , vous pouvez appeler set_charset() :

      $mysqli->set_charset('utf8mb4');       // object oriented style
      mysqli_set_charset($link, 'utf8mb4');  // procedural style
      
    • si vous êtes bloqué avec mysql mais que vous utilisez PHP ≥ 5.2.3, vous pouvez appeler mysql_set_charset .

  • si le pilote ne fournit pas son propre mécanisme pour définir le jeu de caractères de connexion, vous pouvez avoir à émettre une requête pour dire MySQL comment votre application s'attend à ce que les données sur la connexion soient encodées: SET NAMES 'utf8mb4' .

  • la même considération concernant utf8mb4 / utf8 s'applique comme ci-dessus.

Sortie :

  • si votre application transmet du texte à d'autres systèmes, ils devront également être informés du codage de caractères. Avec les applications web, le navigateur doit être informé du codage dans lequel les données sont envoyées (par l'intermédiaire des en-têtes de réponse HTTP ou HTML metadata ).

  • en PHP, vous pouvez utiliser le default_charset de php.l'option ini, ou bien lancer vous-même l'en-tête MIME Content-Type manuellement, ce qui est juste plus de travail mais a le même effet.

Entrée :

  • malheureusement, vous devez vérifier chaque chaîne reçue comme étant valide UTF-8 avant d'essayer de la stocker ou de l'utiliser n'importe où. mb_check_encoding() de PHP 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 n'importe quel encodage qu'ils veulent, et je n'ai pas trouvé d'astuce pour que PHP le fasse pour vous de manière fiable.

  • D'après ma lecture de l'actuel HTML spec , les sous-puces suivantes ne sont plus nécessaires ou même valides pour le HTML moderne. Ma compréhension est que les navigateurs vont travailler avec et soumettre des données dans le jeu de caractères spécifié pour document. Cependant, si vous ciblez des versions plus anciennes de HTML (XHTML, HTML4, etc.), ces points peuvent encore être utiles:

    • pour HTML avant HTML5 seulement : vous voulez que toutes les données qui vous sont envoyées par les navigateurs soient en UTF-8. Malheureusement, si vous allez par le seul moyen fiable de faire cela est d'ajouter l'attribut accept-charset à tous vos <form> tags: <form ... accept-charset="UTF-8"> .
    • pour HTML avant HTML5 seulement : notez que la spécification HTML W3C dit que les clients" devraient "envoyer des formulaires au serveur par défaut dans n'importe quel jeu de caractères que le serveur a servi, mais ce n'est apparemment qu'une recommandation, d'où la nécessité d'être explicite sur chaque étiquette <form> .

Autres Considérations Relatives Au Code :

  • de toute évidence, tous les fichiers que vous serez service (PHP, HTML, JavaScript, etc.) doit être codé 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 extensif de L'extension mbstring de PHP.

  • les opérations de chaîne intégrées de PHP sont Non par défaut UTF-8 safe. il y a certaines choses que vous pouvez faire en toute sécurité avec des opérations normales de chaîne PHP (comme la concaténation), mais pour la plupart des choses, vous devez utiliser la fonction équivalente mbstring .

  • pour savoir ce que vous faites (lisez: ne pas tout gâcher), vous avez vraiment besoin de savoir UTF-8 et comment cela fonctionne au niveau le plus bas possible. Consultez les liens de utf8.com pour quelque bien ressources pour apprendre tout ce que vous devez savoir.

884
répondu chazomaticus 2017-05-23 15:34:44
la source

je voudrais ajouter une chose à excellente réponse de chazomaticus :

n'oubliez pas non plus la balise META (comme celle - ci, ou la version HTML4 ou XHTML de celle-ci ):

<meta charset="utf-8">

ça semble insignifiant, mais IE7 m'a déjà posé des problèmes avec ça.

j'ai tout fait correctement; la base de données, la connexion à la base de données et L'en-tête HTTP de type de contenu étaient tous définis à UTF-8, et il fonctionne bien dans tous les autres navigateurs, mais Internet Explorer a toujours insisté sur l'utilisation de l'encodage "Europe de l'Ouest".

il s'est avéré que la page manquait la balise META. L'ajout qui a résolu le problème.

Edit:

le W3C a en fait une assez grande section dédiée à I18N . Ils ont un certain nombre d'articles liés à cette question – décrivant les côtés HTTP, (x) HTML et CSS de choses:

ils recommandent D'utiliser à la fois le HTTP en-tête et métabalise HTML (ou déclaration XML dans le cas de XHTML servant de XML).

136
répondu mercator 2017-05-23 15:02:49
la source

en plus du paramètre default_charset en php.ini, vous pouvez envoyer le jeu de caractères correct en utilisant header() à partir de votre code, avant toute sortie:

header('Content-Type: text/html; charset=utf-8');

travailler avec Unicode en PHP est facile Aussi longtemps que vous vous rendez compte que la plupart des fonctions de chaîne de caractères ne fonctionnent pas avec Unicode, et certains pourraient manipuler des chaînes complètement . PHP considère que les "caractères" sont longs d'un octet. Parfois, c'est correct (par exemple, explode() ne cherche une séquence d'octets et l'utilise comme séparateur -- donc peu importe les caractères que vous recherchez). Mais d'autres fois, quand la fonction est réellement conçue pour fonctionner sur caractères , PHP n'a aucune idée que votre texte a des caractères multi-octets qui se trouvent avec Unicode.

une bonne bibliothèque à vérifier est phputf8 . Ceci réécrit toutes les fonctions "mauvaises" pour que vous puissiez travailler en toute sécurité sur les chaînes UTF8. Il y a des extensions comme l'extension mbstring qui essaie de le faire pour vous aussi, mais je préfère utiliser la bibliothèque parce que c'est plus portable (mais j'écris des produits de masse, donc c'est important pour moi). Mais phputf8 peut utiliser mbstring en coulisse, de toute façon, pour augmenter la performance.

55
répondu chroder 2008-11-11 00:35:46
la source

Vieux sujet, je sais. J'ai trouvé un problème avec quelqu'un utilisant PDO et la réponse était d'utiliser ceci pour la chaîne de connexion PDO:

$pdo = new PDO(
    'mysql:host=mysql.example.com;dbname=example_db',
    "username",
    "password",
    array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));

le site d'où j'ai pris ceci est en panne, j'ai pu l'obtenir en utilisant google cache heureusement.

26
répondu Brad F Jacobs 2014-01-26 23:02:46
la source

dans mon cas, j'utilisais mb_split , qui utilise regex. Par conséquent, j'ai aussi dû m'assurer manuellement que l'encodage regex était utf-8 en faisant mb_regex_encoding('UTF-8');

comme note secondaire, j'ai aussi découvert en exécutant mb_internal_encoding() que l'encodage interne n'était pas utf-8, et j'ai changé cela en exécutant mb_internal_encoding("UTF-8"); .

20
répondu JDelage 2012-02-24 02:20:22
la source

tout d'abord si vous êtes dans < 5.3 PHP alors no. Vous avez une tonne de problèmes à aborder.

je suis surpris qu'aucun n'ait mentionné la bibliothèque intl , celle qui a un bon support pour unicode , graphèmes , opérations de chaîne de caractères , localisation et beaucoup plus, voir ci-dessous.

je vais citer quelques informations sur le support unicode en PHP par Elizabeth Smith slides at PHPBenelux ' 14

INTL

Bonne:

  • Wrapper autour de la bibliothèque ICU
  • "1519320920 Standardisés" paramètres régionaux, définissez les paramètres régionaux par le script
  • formatage du numéro
  • mise en forme des devises
  • mise en forme du Message (remplace gettext)
  • calendriers, dates, fuseau horaire et heure
  • Translitterator
  • Spoofchecker
  • Ressources
  • Convertisseurs
  • IDN support
  • Graphèmes
  • Classement
  • Itérateurs

Bad:

  • Ne prend pas en charge zend_multibite
  • ne supporte pas la conversion HTTP input output
  • ne supporte pas la surcharge de la fonction

mb_string

  • Permet zend_multibyte support
  • supporte l'encodage HTTP in/out transparent
  • fournit quelques enveloppements pour funtionallity comme strtoupper

ICONV

  • la Primaire pour la conversion de jeux de caractères
  • tampon de Sortie gestionnaire
  • fonctionnalité d'encodage mime
  • conversion
  • some string helpers (len, substr, strpos, strpos)
  • Flux " Filtre stream_filter_append($fp, 'convert.iconv.ISO-2022-JP/EUC-JP')

bases de données

  • mysql: jeu de caractères et collation sur les tables et sur la connexion (pas la collation). N 'utilisez pas non plus mysql - msqli ou PDO
  • postgresql: pg_set_client_encoding
  • sqlite (3): Assurez-vous qu'il a été compilé avec le support unicode et intl

Certains autres Problèmes

  • Vous vous ne pouvez pas utiliser les noms de fichiers unicode avec PHP et windows à moins d'utiliser une extension de troisième partie.
  • envoyer tout en ASCII Si vous utilisez exec, proc_open et autres appels en ligne de commande
  • le texte en clair n'est pas du texte en clair, les fichiers ont des encodages
  • vous pouvez convertir des fichiers à la volée avec le filtre iconv""

je vais mettre à jour cette réponse au cas où les choses changent les fonctionnalités ajoutées et ainsi de suite.

19
répondu Jimmy Kane 2014-02-16 21:37:22
la source

j'ai récemment découvert que l'utilisation de strtolower() peut causer des problèmes lorsque les données sont tronquées après un caractère spécial.

la solution était d'utiliser

mb_strtolower($string, 'UTF-8');

mb_ utilise MultiByte. Il supporte plus de caractères mais en général il est un peu plus lent.

13
répondu Notflip 2016-05-04 15:26:56
la source

la seule chose que j'ajouterais à ces réponses étonnantes est de mettre l'accent sur la sauvegarde de vos fichiers dans l'encodage utf8, j'ai remarqué que les navigateurs acceptent cette propriété sur le réglage de l'encodage utf8 que votre code. N'importe quel éditeur de texte décent vous montrera ceci, par exemple Notepad++ a une option de menu pour l'encodage de fichier, 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 utf8 prise en charge d'une application php/mysql conçue par quelqu'un d'autre, j'ai remarqué que tous les fichiers étaient encodés dans ANSI, donc J'ai dû utiliser ICONV pour convertir tous les fichiers, changer les tables de base de données pour utiliser le jeu de caractères utf8 et le Collat utf8_general_ci, ajouter 'SET NAMES utf8' à la couche d'abstraction de la base de données après la connexion (si vous utilisez 5.3.6 ou plus tôt sinon vous devez utiliser charset=utf8 dans la chaîne de connexion) et changer les fonctions de chaîne de caractères pour utiliser les fonctions de chaîne multibyte php équivalentes.

12
répondu Puerto AGP 2015-06-17 03:20:58
la source

en PHP, vous aurez besoin soit d'utiliser les multibyte fonctions , ou allumer mbstring.func_overload . De cette façon, des choses comme strlen fonctionneront si vous avez des personnages qui prennent plus d'un octet.

vous devrez également identifier le jeu de caractères de vos réponses. Vous pouvez utiliser AddDefaultCharset, comme ci-dessus, ou écrire du code PHP qui renvoie l'en-tête. (Ou vous pouvez ajouter une balise META à vos documents HTML.)

8
répondu JW. 2008-11-11 00:29:21
la source

je viens de passer par le même problème et j'ai trouvé une bonne solution chez PHP manuals.

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.

if (!$mysqli->set_charset("utf8")) {
    printf("Error loading character set utf8: %s\n", $mysqli->error);
} else {
   printf("Current character set: %s\n", $mysqli->character_set_name());
}

Afficher La Source

8
répondu Abdul Sadik Yalcin 2017-01-21 17:24:09
la source

support Unicode en PHP est encore un énorme gâchis. Bien qu'il soit capable de convertir une chaîne de caractères ISO8859 (qu'il utilise en interne) en utf8, il n'a pas la capacité de travailler avec des chaînes unicode nativement, ce qui signifie que toutes les fonctions de traitement des chaînes vont manipuler et corrompre vos chaînes. Vous devez donc soit utiliser une bibliothèque séparée pour le support utf8 approprié, soit réécrire toutes les fonctions de gestion des chaînes de caractères vous-même.

la partie facile spécifie simplement le jeu de caractères Les en-têtes HTTP et dans la base de données et autres, mais rien de tout cela n'a d'importance si votre code PHP ne produit pas un UTF8 valide. C'est la partie la plus difficile, et PHP vous donne pratiquement aucune aide. (Je pense que PHP6 est censé réparer le pire de cela, mais c'est encore un peu loin)

6
répondu jalf 2014-02-11 23:49:45
la source

La première réponse est excellente. Voici ce que j'ai dû faire avec une configuration debian/php/mysql:

// storage
// debian. apparently already utf-8

// retrieval
// the mysql database was stored in utf-8, 
// but apparently php was requesting iso. this worked: 
// ***notice "utf8", without dash, this is a mysql encoding***
mysql_set_charset('utf8');

// delivery
// php.ini did not have a default charset, 
// (it was commented out, shared host) and
// no http encoding was specified in the apache headers.
// this made apache send out a utf-8 header
// (and perhaps made php actually send out utf-8)
// ***notice "utf-8", with dash, this is a php encoding***
ini_set('default_charset','utf-8');

// submission
// this worked in all major browsers once apache
// was sending out the utf-8 header. i didnt add
// the accept-charset attribute.

// processing
// changed a few commands in php, like substr,
// to mb_substr

c'est tout !

5
répondu commonpike 2011-01-14 19:13:18
la source

si vous voulez que MySQL server décide du jeu de caractères, et non pas de PHP en tant que client (ancien comportement; préféré, à mon avis), essayez d'ajouter skip-character-set-client-handshake à votre my.cnf , sous [mysqld] , et redémarrez mysql .

cela peut causer des problèmes au cas où vous utilisez autre chose que UTF8.

5
répondu Nikola Tulimirovic 2015-02-12 02:52:55
la source

Autres questions sur linux php mysql utf-8 apache