php caractères - UTF-8 tout au long de




spéciaux read (13)

Je viens de passer par le même problème et 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.

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());
}

set_charset()

Je suis en train de mettre en place un nouveau serveur, et je veux soutenir complètement UTF-8 dans mon application web. J'ai essayé dans le passé sur des serveurs existants et je devais toujours revenir à ISO-8859-1.

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

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


Dans mon cas, j'utilisais mb_split , qui utilise regex. Par conséquent, j'ai également dû manuellement vérifier que l'encodage de regex était utf-8 en faisant mb_regex_encoding('UTF-8');

En guise de remarque, j'ai également découvert en exécutant mb_internal_encoding() que le codage interne n'était pas utf-8, et j'ai changé cela en exécutant mb_internal_encoding("UTF-8"); .


Je voudrais ajouter une chose à l'excellente réponse de Chazomaticus :

Ne pas oublier la balise META non plus (comme ceci, ou la version HTML4 ou XHTML ):

<meta charset="utf-8">

Cela semble trivial, mais IE7 m'a donné des problèmes avec cela avant.

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 fonctionnaient parfaitement dans tous les autres navigateurs, mais Internet Explorer insistait toujours sur l'utilisation de l'encodage «Western European».

Il s'est avéré que la balise META manquait à la page. Ajoutant cela a résolu le problème.

Modifier:

Le W3C a en fait une section plutôt importante dédiée à 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 méta HTML (ou déclaration XML dans le cas de XHTML servi en XML).


La seule chose que je voudrais ajouter à ces réponses étonnantes est de mettre l'accent sur la sauvegarde de vos fichiers en encodage utf8, j'ai remarqué que les navigateurs acceptent cette propriété plutôt que de configurer utf8 comme encodage de code. N'importe quel éditeur de texte décent vous le montrera, par exemple Notepad ++ a une option de menu pour enconding de fichier, il vous montre l'encodage actuel et vous permet de le changer. Pour tous mes fichiers php j'utilise utf8 sans nomenclature.

Il y a quelque temps, quelqu'un me demandait 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, donc j'ai dû utiliser ICONV pour convertir tous les fichiers, changer les tables de base de données utf8 charset et utf8_general_ci assembler, ajouter 'SET NAMES utf8' à la couche d'abstraction de 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 changez les fonctions de chaîne pour utiliser le php multibyte fonctions de chaîne équivalentes.


La meilleure réponse est excellente. Voici ce que j'ai dû faire sur une installation régulière de 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'était tout !


J'ai récemment découvert que l'utilisation de strtolower() peut entraîner 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.


Stockage de données

  • Spécifiez le utf8mb4 caractères utf8mb4 sur toutes les tables et colonnes de texte de votre base de données. Ceci fait que MySQL stocke et récupère physiquement les valeurs codées nativement en UTF-8. Notez que MySQL utilisera implicitement le codage utf8mb4 si un utf8mb4_* 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 supporte qu'un sous-ensemble de caractères Unicode. Je voudrais 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 devez définir le jeu de caractères de connexion sur utf8mb4 . De cette façon, MySQL ne fait aucune conversion à partir de son UTF-8 natif lorsqu'il transmet les données à votre application et vice versa.

  • Certains pilotes fournissent leur propre mécanisme de configuration du jeu de caractères de connexion, qui met à jour son propre état interne et informe MySQL de l'encodage à utiliser sur la connexion, ce qui 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 :

      $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 de définition du jeu de caractères de connexion, vous devrez peut-être émettre une requête pour indiquer à MySQL comment votre application s'attend à ce que les données de 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 de l'encodage des caractères. Avec les applications Web, le navigateur doit être informé du codage 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'option php.ini default_charset , ou émettre vous-même l'en-tête MIME Content-Type , ce qui représente plus de travail mais a le même effet.

Entrée :

  • Malheureusement, vous devriez vérifier chaque chaîne reçue comme 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 quel que soit l'encodage qu'ils veulent, et je n'ai pas trouvé de truc pour que PHP le fasse pour vous de manière fiable.

  • De ma lecture de la spécification HTML actuelle, les sous-puces suivantes ne sont plus nécessaires ou même plus 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 le document. Toutefois, si vous ciblez des versions plus anciennes de HTML (XHTML, HTML4, etc.), ces points peuvent toujours être utiles:

    • Pour le HTML avant HTML5 uniquement : vous voulez que toutes les données qui vous sont envoyées par les navigateurs soient en UTF-8. Malheureusement, si vous utilisez le seul moyen fiable de le faire, ajoutez l'attribut accept-charset à toutes vos balises <form> : <form ... accept-charset="UTF-8"> .
    • Pour le HTML avant HTML5 uniquement : notez que la spécification HTML du W3C indique que les clients "devraient" par défaut renvoyer des formulaires au serveur quel que soit le jeu de caractères utilisé par le serveur, mais ceci n'est qu'une recommandation, d'où la nécessité d'être explicite. <form> .

Autres considérations de 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 qu'à chaque fois que vous traitez une chaîne UTF-8, vous le faites en toute sécurité. C'est malheureusement la partie difficile. Vous voudrez probablement faire un usage intensif de l'extension mbstring de PHP.

  • Les opérations de chaîne de caractères PHP intégrées ne sont pas sécurisées par défaut par l'UTF-8. Il y a certaines choses que vous pouvez faire en toute sécurité avec les opérations de chaînes PHP normales (comme la concaténation), mais pour la plupart des choses, vous devez utiliser la fonction mbstring équivalente.

  • Pour savoir ce que vous faites (lire: ne pas le gâcher), vous avez vraiment besoin de connaître UTF-8 et comment cela 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.


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 avec des chaînes Unicode en mode natif, ce qui signifie que toutes les fonctions de traitement de chaînes altéreront et corrompront vos chaînes. Vous devez donc soit utiliser une bibliothèque séparée pour le support approprié de utf8, soit réécrire vous-même toutes les fonctions de gestion de chaîne.

La partie facile est juste en spécifiant le jeu de caractères dans les en-têtes HTTP et dans la base de données et ainsi de suite, mais rien de tout cela n'a d'importance si votre code PHP ne sort pas un UTF8 valide. C'est la partie difficile, et PHP ne vous aide pratiquement pas là-bas. (Je pense que PHP6 est censé résoudre le pire de tout ça, mais c'est encore loin)


Vieux sujet, je sais. 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 que j'ai pris est en panne, a été en mesure de l'obtenir en utilisant google cache heureusement.


Bon objectif à avoir dès le début - en fonction de la nature de votre site, j'ai trouvé beaucoup de ressources à ce sujet par Googling - vous n'êtes pas le premier à le faire, bien sûr.

Le mystique PHP6 est censé avoir tout redressé, n'est-ce pas?

Vous pouvez presque définir utf-8 comme le jeu de caractères par défaut global pour mysql au niveau du serveur et il sera par défaut correctement aux niveaux plus granulaires.


En plus de définir default_charset dans php.ini, vous pouvez envoyer le jeu de caractères correct en utilisant header() depuis votre code, avant toute sortie:

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

Travailler avec Unicode en PHP est facile tant que vous vous rendez compte que la plupart des fonctions de chaîne ne fonctionnent pas avec Unicode, et que certaines peuvent altérer complètement les chaînes . PHP considère que les "caractères" ont une longueur de 1 octet. Parfois cela est correct (par exemple, explode() recherche uniquement une séquence d'octets et l'utilise comme séparateur - 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.

Une bonne bibliothèque à vérifier est phputf8 . 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 essaye de faire ça aussi pour vous, mais je préfère utiliser la librairie parce qu'elle est plus portable (mais j'écris des produits grand public, donc c'est important pour moi). Mais phputf8 peut utiliser mbstring en coulisse, de toute façon, pour augmenter les performances.


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 a un bon support pour unicode , les graphèmes , les opérations de chaînes de caractères , la localisation et bien d'autres, voir ci-dessous.

Je vais citer quelques informations sur le support unicode en PHP par les slides Elizabeth Smith à PHPBenelux'14

INTL

Bien:

  • Wrapper autour de la bibliothèque ICU
  • Paramètres régionaux normalisés, définissez les paramètres régionaux par script
  • Formatage des nombres
  • Formatage de devise
  • Formatage des messages (remplace gettext)
  • Calendriers, dates, fuseau horaire et heure
  • Translitteur
  • Spoofchecker
  • Bundles de ressources
  • Convertisseurs
  • Support IDN
  • Graphemes
  • Collation
  • Iterators

Mal:

  • Ne supporte pas zend_multibite
  • Ne prend pas en charge la conversion de sortie d'entrée HTTP
  • Ne supporte pas la surcharge de fonction

mb_string

  • Active le support zend_multibyte
  • Prend en charge le codage HTTP in / out transparent
  • Fournit des wrappers pour funtionallity tels que strtoupper

ICONV

  • Primaire pour la conversion de jeu de caractères
  • Gestionnaire de tampon de sortie
  • fonctionnalité d'encodage mime
  • conversion
  • quelques aides de chaîne (len, substr, strpos, strrpos)
  • Filtre de flux stream_filter_append($fp, 'convert.iconv.ISO-2022-JP/EUC-JP')

BASES DE DONNÉES

  • mysql: Charset 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

Quelques autres Gotcha

  • Vous ne pouvez pas utiliser de noms de fichiers Unicode avec PHP et Windows à moins d'utiliser une extension de 3ème partie.
  • Envoyez tout en ASCII si vous utilisez exec, proc_open et d'autres appels de ligne de commande
  • Le texte brut n'est pas du texte brut, les fichiers ont des codages
  • Vous pouvez convertir des fichiers à la volée avec le filtre iconv

Je mettrai à jour cette réponse au cas où les choses changeraient les fonctionnalités ajoutées et ainsi de suite.


Pour le cas mis en évidence par Guus, je suggère fortement d'utiliser soit utf8_unicode_cs (sensible à la casse, correspondance stricte, la commande correctement pour la plupart) au lieu de utf8_bin (appariement strict, ordre incorrect).

Si le champ est destiné à être recherché, contrairement à un utilisateur, utilisez utf8_general_ci ou utf8_unicode_ci. Les deux sont insensibles à la casse, l'un correspondra difficilement («ß» est égal à «s», et non à «ss»). Il existe également des versions spécifiques à la langue, comme utf8_german_ci où la correspondance de perte est plus adaptée à la langue spécifiée.

[Modifier - près de 6 ans plus tard]

Je ne recommande plus le jeu de caractères "utf8" sur MySQL, et recommande plutôt le jeu de caractères "utf8mb4". Ils correspondent presque entièrement, mais permettent un peu (beaucoup) plus de caractères Unicode.

De manière réaliste, MySQL aurait dû mettre à jour le jeu de caractères "utf8" et les classements respectifs pour correspondre à la spécification "utf8", mais plutôt un jeu de caractères séparé et des classements respectifs pour ne pas affecter la désignation de stockage pour ceux qui utilisent leur jeu de caractères "utf8" incomplet .





php mysql linux apache utf-8