In che modo PHP rappresenta internamente le stringhe?


18

UTF8?
UTF16?

Le stringhe in PHP tengono traccia anche della codifica utilizzata?

Diamo un'occhiata a questo script per esempio. Di 'che corro:

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

Cosa succede realmente?

Ovviamente penso $originalche non conterrà solo 7 caratteri. Questi glifi devono essere ciascuno rappresentato da diversi byte lì.

Quindi faccio:

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

Cosa succederà $converted? In che modo sarà $converteddiverso $original?

Sarà esattamente la stessa sequenza di byte $originalma con una codifica diversa?


1
Quale versione di PHP? PHP <6 non può gestire UTF-8 nativo. Esistono pacchetti e metodi che aiutano / risolvono questo problema. Divertimento di Google con utf-8 e php. Quindi passa a un'altra piattaforma anziché a PHP. :)
Andrew T Finnell,

4
PHP <6? Ciò includerebbe ogni versione di PHP mai pubblicata ...
tdammers,

1
Inoltre, PHP può gestire UTF-8, semplicemente non ha un tipo di dati dedicato, quindi devi guardare cosa stai facendo.
tdammers,

Risposte:


22

Una stringa PHP è solo una sequenza di byte, senza codifica taggata in alcun modo. I valori di stringa possono provenire da varie fonti: il client (su HTTP), un database, un file o letterali di stringa nel codice sorgente. PHP legge tutte queste come sequenze di byte e non estrae mai alcuna informazione di codifica.

Finché tutte le origini dati e le destinazioni utilizzano la stessa codifica, la cosa peggiore che può accadere è che le posizioni delle stringhe siano errate (se si utilizzano codifiche multi-byte), poiché PHP conterà i byte, non i caratteri.

Ma se le codifiche non corrispondono (ad esempio scrivi una stringa letterale in un file sorgente memorizzato come UTF-8 e poi lo invii a un database che prevede Latin-1), PHP non eseguirà alcuna conversione per te: lo farà copi felicemente i byte su raw.

La soluzione più sana è questa:

  • Imposta la codifica interna di PHP su UTF-8.
  • Salva tutti i tuoi file sorgente come UTF-8.
  • Usa UTF-8 come codifica di output (non dimenticare di inviare le Content-typeintestazioni adatte ).
  • Impostare la connessione al database per utilizzare UTF-8 ( SET NAMES UTF8in MySQL).
  • Configura tutto il resto per essere UTF-8 se possibile.
  • Per tutto ciò che non puoi controllare (ad es. Servizi Web di terze parti), assicurati di conoscere la codifica e di convertirla in UTF-8 il prima possibile e di tornare all'altra codifica il più tardi possibile.

Perché UTF-8? Poiché può rappresentare tutti i caratteri Unicode e quindi sostituisce tutte le codifiche esistenti a 7 e 8 bit e poiché è binario compatibile con ASCII, ovvero ogni stringa ASCII valida è anche una stringa UTF-8 valida (ma non vv .).

Nel tuo esempio, ciò che accade è questo.

Innanzitutto, si salva il file di origine; il tuo editor di testo è probabilmente configurato per utilizzare UTF-8, quindi la stringa letterale finisce con UTF-8 codificata su disco. PHP legge questo file, interpretando la stringa come una serie di byte; $originalora contiene una stringa codificata UTF-8 di 7 caratteri, che è solo una sequenza di byte (sebbene contenga più di 7 byte, poiché ogni carattere è rappresentato da due o più byte). Se si chiama quindi echo $original, la stringa codificata viene inviata al client così com'è; se hai detto al client di aspettarsi UTF-8, tutto va bene, ma se non lo hai fatto, PHP non ha modo di dire la differenza e finirai con la spazzatura nel browser. Come esperimento, prova questo:

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

strlen è codifica-agnostica e presuppone una codifica a 8 bit a larghezza fissa, ovvero un byte per carattere, quindi conterà i byte, non i caratteri.


Quindi $ convertito rappresenterà la stessa stringa ma in un'altra codifica. La codifica raw effettiva, che è ciò che PhP store, sarà diversa.
user4951

2
Lo ripeterò per te: PHP memorizza i byte, non i caratteri, e non conosce affatto le codifiche (anche se alcune funzioni di libreria lo fanno.
tdammers

1
Oh, ed è "PHP", non "PhP".
tdammers,

2
se i byte grezzi sono uguali qual è la differenza tra $ original e $ convertiti allora. È quello che sto chiedendo.
user4951

2
Oh, ok, ecco cosa intendi. Sì, i byte grezzi cambiano in base alla conversione della codifica. Tuttavia, PHP non ricorda la codifica, quindi se converti una stringa da, diciamo, utf-8 a latin-1, e poi tratti il ​​risultato come utf-8, vedrai strani risultati.
tdammers,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.