Jest tutaj kilka naprawdę dobrych odpowiedzi i prób odpowiedzi na twoje pytanie. Nie jestem mistrzem kodowania, ale rozumiem Twoje pragnienie posiadania czystego stosu UTF-8 aż do bazy danych. Używam utf8mb4
kodowania MySQL dla tabel, pól i połączeń.
Moja sytuacja sprowadzała się do stwierdzenia: „Chcę tylko, aby moje środki dezynfekujące, walidatory, logika biznesowa i przygotowane oświadczenia radziły sobie z UTF-8, gdy dane pochodzą z formularzy HTML lub e-mailowych linków rejestracyjnych”. Tak więc, na swój prosty sposób, zacząłem od tego pomysłu:
- Spróbuj wykryć kodowanie:
$encodings = ['UTF-8', 'ISO-8859-1', 'ASCII'];
- Jeśli nie można wykryć kodowania,
throw new RuntimeException
- Jeśli dane wejściowe są
UTF-8
, kontynuuj.
W przeciwnym razie, jeśli jest ISO-8859-1
lubASCII
za. Próba konwersji na UTF-8 (czekaj, nie zakończono)
b. Wykryj kodowanie przekonwertowanej wartości
do. Jeśli raportowane kodowanie i przekonwertowana wartość są takie same UTF-8
, kontynuuj.
re. Jeszcze,throw new RuntimeException
Z mojej klasy abstrakcyjnej 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;
}
Można by argumentować, że powinienem oddzielić zagadnienia związane z kodowaniem od mojej Sanitizer
klasy abstrakcyjnej i po prostu wstrzyknąć Encoder
obiekt do konkretnej instancji podrzędnej Sanitizer
. Jednak głównym problemem związanym z moim podejściem jest to, że bez większej wiedzy po prostu odrzucam typy kodowania, których nie chcę (i polegam na funkcjach PHP mb_ *). Bez dalszych badań nie mogę wiedzieć, czy to boli niektóre populacje, czy nie (lub, jeśli tracę ważne informacje). Muszę się więc dowiedzieć więcej. Znalazłem ten artykuł.
To, co każdy programista absolutnie, pozytywnie musi wiedzieć o kodowaniu i zestawach znaków do pracy z tekstem
Co więcej, co się stanie, gdy zaszyfrowane dane zostaną dodane do moich łączy rejestracyjnych e-mail (przy użyciu OpenSSL
lub mcrypt
)? Czy może to przeszkadzać w dekodowaniu? A co z Windows-1252? A co z konsekwencjami dla bezpieczeństwa? Użycie utf8_decode()
i utf8_encode()
w Sanitizer::isUTF8
jest wątpliwe.
Ludzie wskazywali na niedociągnięcia w funkcjach PHP mb_ *. Nigdy nie poświęcałem czasu na badanie iconv
, ale jeśli działa lepiej niż funkcje mb_ *, daj mi znać.