Como o PHP representa internamente as strings?

18

UTF8?
UTF16?

As strings no PHP também acompanham a codificação usada?

Vamos dar uma olhada neste script, por exemplo. Digamos que eu corro:

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

O que realmente acontece?

Obviamente, acho $originalque não conterá apenas 7 caracteres. Cada um desses glifos deve ser representado por vários bytes.

Então eu faço:

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

O que vai acontecer $converted? Como será $converteddiferente $original?

Será exatamente a mesma sequência de bytes, $originalmas com uma codificação diferente?

user4951
fonte
1
Qual versão do PHP? O PHP <6 não pode lidar com UTF-8 nativo. Existem pacotes e métodos que ajudam / resolvem esse problema. Google diverte-se com utf-8 e php. Em seguida, mude para outra plataforma em vez de PHP. :)
Andrew T Finnell
4
PHP <6? Isso inclui todas as versões do PHP já lançado ...
tdammers
1
Além disso, o PHP pode lidar com UTF-8, ele simplesmente não possui um tipo de dados dedicado, então você precisa observar o que está fazendo.
tdammers

Respostas:

22

Uma string PHP é apenas uma sequência de bytes, sem nenhuma codificação marcada para ela. Os valores da string podem vir de várias fontes: o cliente (por HTTP), um banco de dados, um arquivo ou de literais da string no seu código-fonte. O PHP lê tudo isso como sequências de bytes e nunca extrai nenhuma informação de codificação.

Desde que todas as suas fontes e destinos de dados usem a mesma codificação, a pior coisa que pode acontecer é que as posições das strings estejam incorretas (se você usar codificações de vários bytes), pois o PHP contará bytes, não caracteres.

Mas se as codificações não corresponderem (por exemplo, você escreve uma string literal em um arquivo de origem armazenado como UTF-8 e a envia para um banco de dados que espera o Latin-1), o PHP não fará nenhuma conversão para você: copie alegremente os bytes em bruto.

A solução mais segura é esta:

  • Defina a codificação interna do PHP como UTF-8.
  • Salve todos os seus arquivos de origem como UTF-8.
  • Use UTF-8 como sua codificação de saída (não esqueça de enviar Content-typecabeçalhos adequados ).
  • Defina a conexão com o banco de dados para usar UTF-8 ( SET NAMES UTF8no MySQL).
  • Configure todo o resto para ser UTF-8, se possível.
  • Para qualquer coisa que você não possa controlar (por exemplo, serviços da web de terceiros), verifique a codificação e converta-a em UTF-8 o mais cedo possível, e volte para a outra codificação o mais tarde possível.

Por que UTF-8? Como ele pode representar todos os caracteres Unicode e, portanto, substitui todas as codificações de 7 e 8 bits existentes, e por ser binário compatível com ASCII, ou seja, toda string ASCII válida também é uma string UTF-8 válida (mas não vv .).

No seu exemplo, o que acontece é isso.

Primeiro, você salva seu arquivo de origem; seu editor de texto provavelmente está configurado para usar UTF-8, portanto, sua string literal termina em UTF-8 codificada no disco. O PHP lê esse arquivo, interpretando a string como uma série de bytes; $originalagora contém uma sequência codificada em UTF-8 de 7 caracteres, que é apenas uma sequência de bytes (embora contenha mais de 7 bytes, porque cada caractere é representado por dois ou mais bytes). Se você ligar echo $original, a sequência codificada será enviada ao cliente como está; se você disse ao cliente que esperava UTF-8, está tudo bem, mas se não tiver, o PHP não tem como saber a diferença e você acabará com lixo no navegador. Como um experimento, tente o seguinte:

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

strlen é independente de codificação e assume uma codificação de 8 bits de largura fixa, ou seja, um byte por caractere, portanto, contará bytes, não caracteres.

tdammers
fonte
Então $ convertido representará a mesma string, mas em outra codificação. A codificação bruta real, que é o que a loja PhP, será diferente.
usar o seguinte comando
2
Eu vou repetir isso para você: lojas PHP bytes, não caracteres, e ele não sabe sobre codificações em tudo (embora algumas funções da biblioteca fazer.
tdammers
1
Ah, e é "PHP", não "PhP".
tdammers
2
se os bytes brutos forem iguais, qual é a diferença entre $ original e $ convertidos? É isso que estou perguntando.
usar o seguinte comando
2
Oh, ok, é isso que você quer dizer. Sim, os bytes brutos mudam de acordo com a conversão de codificação. No entanto, o PHP não se lembra da codificação; portanto, se você converter uma string de, digamos, utf-8 para latin-1, e depois tratar o resultado como utf-8, verá resultados estranhos.
tdammers