Existem algumas boas respostas e tentativas de responder sua pergunta aqui. Não sou um mestre de codificação, mas entendo seu desejo de ter uma pilha UTF-8 pura até o banco de dados. Eu tenho usado a utf8mb4
codificação do MySQL para tabelas, campos e conexões.
Minha situação se resumia a "Eu só quero que meus desinfetantes, validadores, lógica de negócios e instruções preparadas lidem com o UTF-8 quando os dados vierem de formulários HTML ou links de registro de email". Então, da minha maneira simples, comecei com esta ideia:
- Tente detectar a codificação:
$encodings = ['UTF-8', 'ISO-8859-1', 'ASCII'];
- Se a codificação não puder ser detectada,
throw new RuntimeException
- Se houver entrada
UTF-8
, continue.
Senão, se é ISO-8859-1
ouASCII
uma. Tentativa de conversão para UTF-8 (espera, não concluída)
b. Detectar a codificação do valor convertido
c. Se a codificação relatada e o valor convertido forem ambos UTF-8
, continue.
d. Outro,throw new RuntimeException
Da minha aula abstrata 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;
}
Alguém poderia argumentar que eu deveria separar as preocupações de codificação da minha Sanitizer
classe abstrata e simplesmente injetar um Encoder
objeto em uma instância filha concreta de Sanitizer
. No entanto, o principal problema com a minha abordagem é que, sem mais conhecimento, simplesmente rejeito os tipos de codificação que não quero (e confio nas funções do PHP mb_ *). Sem um estudo mais aprofundado, não sei se isso machuca algumas populações ou não (ou se estou perdendo informações importantes). Então, eu preciso aprender mais. Encontrei este artigo.
O que todo programador precisa absolutamente e positivamente sobre codificações e conjuntos de caracteres para trabalhar com texto
Além disso, o que acontece quando dados criptografados são adicionados aos meus links de registro de e-mail (usando OpenSSL
ou mcrypt
)? Isso poderia interferir na decodificação? E o Windows-1252? E as implicações de segurança? O uso de utf8_decode()
e utf8_encode()
em Sanitizer::isUTF8
é duvidoso.
As pessoas apontaram falhas nas funções do PHP mb_ *. Nunca levei tempo para investigar iconv
, mas se funcionar melhor que as funções mb_ *, informe-me.