Il y a de très bonnes réponses et tentatives pour répondre à votre question ici. Je ne suis pas un maître d'encodage, mais je comprends votre désir d'avoir une pile UTF-8 pure jusqu'à votre base de données. J'utilise l' utf8mb4
encodage de MySQL pour les tables, les champs et les connexions.
Ma situation se résumait à "Je veux juste que mes désinfectants, mes validateurs, ma logique métier et mes déclarations préparées traitent UTF-8 lorsque les données proviennent de formulaires HTML ou de liens d'enregistrement de courrier électronique." Donc, à ma manière simple, j'ai commencé avec cette idée:
- Tentative de détection du codage:
$encodings = ['UTF-8', 'ISO-8859-1', 'ASCII'];
- Si l'encodage ne peut pas être détecté,
throw new RuntimeException
- Si l'entrée est
UTF-8
, continuez.
Sinon, si c'est ISO-8859-1
ouASCII
une. Tentative de conversion en UTF-8 (attendez, pas terminé)
b. Détecter le codage de la valeur convertie
c. Si le codage indiqué et la valeur convertie sont tous les deux UTF-8
, continuez.
ré. Autre,throw new RuntimeException
De ma classe abstraite Sanitizer
private function isUTF8($encoding, $value)
{
return (($encoding === 'UTF-8') && (utf8_encode(utf8_decode($value)) === $value));
}
private function utf8tify(&$value)
{
$encodings = ['UTF-8', 'ISO-8859-1', 'ASCII'];
mb_internal_encoding('UTF-8');
mb_substitute_character(0xfffd); //REPLACEMENT CHARACTER
mb_detect_order($encodings);
$stringEncoding = mb_detect_encoding($value, $encodings, true);
if (!$stringEncoding) {
$value = null;
throw new \RuntimeException("Unable to identify character encoding in sanitizer.");
}
if ($this->isUTF8($stringEncoding, $value)) {
return;
} else {
$value = mb_convert_encoding($value, 'UTF-8', $stringEncoding);
$stringEncoding = mb_detect_encoding($value, $encodings, true);
if ($this->isUTF8($stringEncoding, $value)) {
return;
} else {
$value = null;
throw new \RuntimeException("Unable to convert character encoding from ISO-8859-1, or ASCII, to UTF-8 in Sanitizer.");
}
}
return;
}
On pourrait faire valoir que je devrais séparer les préoccupations d'encodage de ma Sanitizer
classe abstraite et simplement injecter un Encoder
objet dans une instance enfant concrète de Sanitizer
. Cependant, le principal problème avec mon approche est que, sans plus de connaissances, je rejette simplement les types d'encodage que je ne veux pas (et je me fie aux fonctions PHP mb_ *). Sans une étude plus approfondie, je ne peux pas savoir si cela fait mal ou non à certaines populations (ou si je perds des informations importantes). Alors, j'ai besoin d'en savoir plus. J'ai trouvé cet article.
Ce que tout programmeur a absolument besoin de savoir sur les encodages et les jeux de caractères pour travailler avec du texte
De plus, que se passe-t-il lorsque des données cryptées sont ajoutées à mes liens d'enregistrement de courrier électronique (en utilisant OpenSSL
ou mcrypt
)? Cela pourrait-il interférer avec le décodage? Qu'en est-il de Windows-1252? Qu'en est-il des implications en matière de sécurité? L'utilisation de utf8_decode()
et utf8_encode()
dans Sanitizer::isUTF8
est douteuse.
Les gens ont signalé des lacunes dans les fonctions PHP mb_ *. Je n'ai jamais pris le temps d'enquêter iconv
, mais si cela fonctionne mieux que les fonctions mb_ *, faites-le moi savoir.