Ci sono alcune risposte davvero valide e tentativi di rispondere alla tua domanda qui. Non sono un master di codifica, ma capisco il tuo desiderio di avere un puro stack UTF-8 fino al tuo database. Ho usato la utf8mb4
codifica di MySQL per tabelle, campi e connessioni.
La mia situazione si riduce a "Voglio solo i miei disinfettanti, validatori, logica aziendale e dichiarazioni preparate per gestire UTF-8 quando i dati provengono da moduli HTML o collegamenti di registrazione e-mail". Quindi, nel mio modo semplice, ho iniziato con questa idea:
- Tentativo di rilevare la codifica:
$encodings = ['UTF-8', 'ISO-8859-1', 'ASCII'];
- Se la codifica non può essere rilevata,
throw new RuntimeException
- Se l'ingresso è
UTF-8
, continua.
Altrimenti, se lo è ISO-8859-1
oASCII
un. Tentativo di conversione in UTF-8 (attendere, non terminato)
b. Rileva la codifica del valore convertito
c. Se la codifica segnalata e il valore convertito sono entrambi UTF-8
, continua.
d. Altro,throw new RuntimeException
Dalla mia classe astratta 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;
}
Si potrebbe sostenere che dovrei separare le preoccupazioni di codifica dalla mia Sanitizer
classe astratta e semplicemente iniettare un Encoder
oggetto in un'istanza figlio concreta di Sanitizer
. Tuttavia, il problema principale con il mio approccio è che, senza ulteriori conoscenze, rifiuto semplicemente i tipi di codifica che non desidero (e mi affido alle funzioni PHP mb_ *). Senza ulteriori studi, non posso sapere se ciò danneggia alcune popolazioni o meno (o, se sto perdendo informazioni importanti). Quindi, ho bisogno di saperne di più. Ho trovato questo articolo.
Ciò che ogni programmatore deve assolutamente e positivamente sapere sulle codifiche e sui set di caratteri per lavorare con il testo
Inoltre, cosa succede quando i dati crittografati vengono aggiunti ai miei collegamenti di registrazione e-mail (utilizzando OpenSSL
o mcrypt
)? Questo potrebbe interferire con la decodifica? Che dire di Windows-1252? E le implicazioni sulla sicurezza? L'uso di utf8_decode()
e utf8_encode()
in Sanitizer::isUTF8
sono dubbi.
Le persone hanno sottolineato carenze nelle funzioni PHP mb_ *. Non ho mai avuto il tempo di indagare iconv
, ma se funziona meglio delle funzioni mb_ *, fammi sapere.