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' utf8mb4encodage 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-1ouASCII
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 Sanitizerclasse abstraite et simplement injecter un Encoderobjet 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 OpenSSLou 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::isUTF8est 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.