¿Cómo representa PHP internamente las cadenas?

14

UTF8?
UTF16?

¿Las cadenas en PHP también hacen un seguimiento de la codificación utilizada?

Por ejemplo, veamos este script. Di que corro:

$original = "शक्नोम्यत्तुम्";

¿Qué sucede realmente?

Obviamente, creo que $original no contendrá solo 7 caracteres. Esos glifos deben estar representados por varios bytes.

Luego lo hago:

$converted = mb_convert_encoding ($original , "UTF-8");

¿Qué pasará con $converted ? ¿En qué será diferente $converted de $original ?

¿Será exactamente la misma secuencia de bytes que $original pero con una codificación diferente?

    
pregunta user4951 02.06.2012 - 16:41

1 respuesta

20

Una cadena PHP es solo una secuencia de bytes, sin codificación alguna etiquetada. Los valores de cadena pueden provenir de varias fuentes: el cliente (a través de HTTP), una base de datos, un archivo o los literales de cadena en su código fuente. PHP lee todo esto como secuencias de bytes, y nunca extrae ninguna información de codificación.

Mientras todas sus fuentes de datos y destinos utilicen la misma codificación, lo peor que puede suceder es que las posiciones de las cadenas sean incorrectas (si utiliza codificaciones de múltiples bytes), ya que PHP contará los bytes, no los caracteres.

Pero si las codificaciones no coinciden (por ejemplo, escribe un literal de cadena en un archivo fuente almacenado como UTF-8 y luego lo envía a una base de datos que espera Latin-1), PHP no realizará ninguna conversión por usted. : felizmente copiará los bytes en bruto.

La solución más sensata es esta:

  • Establezca la codificación interna de PHP en UTF-8.
  • Guarde todos sus archivos de origen como UTF-8.
  • Use UTF-8 como su codificación de salida (no olvide enviar los encabezados Content-type adecuados).
  • Establezca la conexión de la base de datos para utilizar UTF-8 ( SET NAMES UTF8 en MySQL).
  • Configure todo lo demás para que sea UTF-8 si es posible.
  • Para cualquier cosa que no pueda controlar (por ejemplo, servicios web de terceros), asegúrese de conocer la codificación y conviértala a UTF-8 lo antes posible, y vuelva a la otra codificación lo más tarde posible.

¿Por qué UTF-8? Debido a que puede representar a todos los caracteres Unicode y, por lo tanto, reemplaza a todas las codificaciones existentes de 7 bits y 8 bits, y porque es compatible a nivel binario con ASCII, es decir, cada cadena ASCII válida también es una cadena UTF-8 válida (pero no vv .).

En tu ejemplo, lo que sucede es esto.

Primero, guardas tu archivo fuente; su editor de texto probablemente esté configurado para usar UTF-8, por lo que su cadena literal termina con codificación UTF-8 en el disco. PHP lee este archivo, interpretando la cadena como una serie de bytes; $original ahora contiene una cadena codificada en UTF-8 de 7 caracteres, que es solo una secuencia de bytes (aunque contiene más de 7 bytes, porque cada carácter está representado por dos o más bytes). Si luego llama a echo $original , la cadena codificada se envía al cliente como está; Si le has dicho al cliente que espere UTF-8, todo está bien, pero si no lo has hecho, PHP no tiene forma de notar la diferencia y terminarás con basura en el navegador. Como experimento, prueba esto:

$original = "शक्नोम्यत्तुम्";
echo strlen($original);

strlen es independiente de la codificación y asume una codificación de 8 bits de ancho fijo, es decir, un byte por carácter, por lo que contará bytes, no caracteres.

    
respondido por el tdammers 02.06.2012 - 16:57

Lea otras preguntas en las etiquetas