2010-03-30 11 views
5

Ho un sito che desidero migrare da ISO a UTF-8.La funzione di serializzazione PHP è compatibile con UTF-8?

Ho un record nel database di indicizzato dal seguente chiave primaria:

s:22:"Informations générales"; 

Il problema è, ora (con UTF-8), quando ho serializzare la stringa, ottengo:

s:24:"Informations générales"; 

(notare la dimensione della stringa è ora il numero di byte, non lunghezza della stringa)

Quindi questo non è compatibile con i record precedenti non UTF8!

Ho fatto qualcosa di sbagliato? Come potrei risolvere questo?

Grazie

+1

@Col Shrapnel: Si chiama 'francese' ed è, come tale, non questo strano. – Boldewyn

+1

Non si riferiva alla lingua. Sta usando una stringa PHP serializzata come chiave primaria. Questo è strano. –

+1

@Boldewyn probabilmente non si sta riferendo al francese. – pars

risposta

2

Il comportamento è completamente corretto. Due stringhe con codifiche diverse generano flussi di byte diversi, quindi stringhe di serializzazione diverse.

+0

Ok, questo è normale: il processo di serializzazione richiede una lunghezza di memoria, non una lunghezza di stringa –

+0

@Matthieu: so che suona strano, ma in PHP le stringhe sono in realtà array di byte. Otterrete lo stesso risultato se echo strlen ($ utf8EncodedString) '. Per la lunghezza * character *, è necessario 'mb_strlen()'. – soulmerge

+0

Un altro: 'file_get_contents()' ti darà una stringa (anche quando ricevi i contenuti dei file binari). Anche le funzioni di socket. – soulmerge

2

PHP 4 e 5 non hanno integrato il supporto Unicode; Credo che PHP 6 stia iniziando ad aggiungere più supporto Unicode anche se non sono sicuro di quanto sia completo.

+0

Lo so, volevo solo sapere la situazione della "chiave primaria" –

0

Non hai fatto niente di sbagliato. PHP precedente alla v6 non è a conoscenza di Unicode, e come tale non lo supporta, se non lo si batte (vale a dire, tramite l'estensione mbstring o altri mezzi).

Qui abbiamo scritto il nostro involucro attorno a serialize() per risolvere questo problema. Potresti anche passare ad altre tecniche di serializzazione, come JSON (con json_encode() e json_decode() in PHP dalla 5.2.0).

3

Eseguire il dump del database in latin1.

Nella riga di comando:

sed -e 's/latin1/utf8/g' -i ./DBNAME.sql 

Importare il file convertito in un nuovo database in UTF-8.

Utilizzare uno script php per aggiornare ogni campo. fare una query, ciclo attraverso ogni campo e aggiornare la stringa serializzata utilizza questo:

$str = preg_replace('!s:(\d+):"(.*?)";!se', "'s:'.strlen('$2').':\"$2\";'", $str); 

Dopo di che, sono stato in grado di utilizzare unserialize() e tutto lavorare con UTF-8.

+0

Il grosso problema con questo è che se la stringa ha doppie virgolette in esso saranno preceduti da una barra rovesciata, dato che PHP cerca in maniera priva di aiuto (questo è un effetto collaterale del flag "e"). Usare "preg_replace_callback" sembra essere un modo decente per risolvere questo problema. –

1

Per unserialize una matrice serializzati codifica UTF-8:

$array = @unserialize($arrayFromDatabase); 
if ($array === false) { 
    $array = @unserialize(utf8_decode($arrayFromDatabase)); //decode first 
    $array = array_map('utf8_encode', $array); // encode the array again 
} 
+0

Ho trovato questa soluzione molto utile quando si preesistono dati serializzati codificati in ISO-8859-X e occorre utilizzarli in un'applicazione porting su UTF-8. –