Hay algunas respuestas realmente buenas e intenta responder a su pregunta aquí. No soy un maestro de codificación, pero entiendo su deseo de tener una pila UTF-8 pura hasta su base de datos. He estado usando la utf8mb4
codificación de MySQL para tablas, campos y conexiones.
Mi situación se redujo a "Solo quiero que mis desinfectantes, validadores, lógica de negocios y declaraciones preparadas se ocupen de UTF-8 cuando los datos provienen de formularios HTML o enlaces de registro por correo electrónico". Entonces, de manera simple, comencé con esta idea:
- Intenta detectar la codificación:
$encodings = ['UTF-8', 'ISO-8859-1', 'ASCII'];
- Si no se puede detectar la codificación,
throw new RuntimeException
- Si la entrada es
UTF-8
, continúe.
De lo contrario, si es ISO-8859-1
oASCII
a. Intento de conversión a UTF-8 (espera, no terminado)
si. Detectar la codificación del valor convertido.
C. Si la codificación informada y el valor convertido son ambos UTF-8
, continúe.
re. Más,throw new RuntimeException
De mi clase abstracta 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;
}
Se podría argumentar que debería separar las preocupaciones de codificación de mi Sanitizer
clase abstracta y simplemente inyectar un Encoder
objeto en una instancia secundaria concreta de Sanitizer
. Sin embargo, el principal problema con mi enfoque es que, sin más conocimiento, simplemente rechazo los tipos de codificación que no quiero (y confío en las funciones PHP mb_ *). Sin más estudios, no puedo saber si eso perjudica a algunas poblaciones o no (o si estoy perdiendo información importante). Entonces, necesito aprender más. Encontré este artículo.
Lo que todo programador debe saber de manera absoluta y positiva sobre las codificaciones y los conjuntos de caracteres para trabajar con texto
Además, ¿qué sucede cuando se agregan datos cifrados a mis enlaces de registro de correo electrónico (usando OpenSSL
o mcrypt
)? ¿Podría esto interferir con la decodificación? ¿Qué pasa con Windows-1252? ¿Qué pasa con las implicaciones de seguridad? El uso de utf8_decode()
y utf8_encode()
en Sanitizer::isUTF8
es dudoso.
La gente ha señalado fallas en las funciones PHP mb_ *. Nunca me tomé el tiempo para investigar iconv
, pero si funciona mejor que las funciones mb_ *, avíseme.