Una delle grandi carenze di PHP è il supporto della codifica UTF8. Questo significa che gran parte delle funzioni (in particolare quelle che agiscono su stringhe) potrebbero dare risultati inaspettati quando gli si passano come parametri stringhe multi-byte. Quindi bisogna prestare attenzione ad alcuni particolari nella realizzazione di un sito multilingua in PHP e MySQL.
In attesa della versione 6 di PHP che dovrebbe supportare nativamente la codifica UTF8, ecco qualche indicazione utile a tal proposito.
I file e il bug del BOM
Salva tutti i file che compongono l’applicazione (sia template che script PHP) in utf-8. Ho sentito parlare di un bug connesso alla presenza o meno del BOM (Byte Order Mark) all’inizio del file. Su Windows usando Ultra-Edit o Eclipse non ho mai sperimentato il problema, quindi se pensi che la tua applicazione dia il famoso errore “headers already sent” per questo motivo, passa ad uno di questi editor.
Puoi continuare a salvare i css e i javascript in formato ASCII, anche per risparmiare qualche byte, a meno che non pensi di includere delle stringhe multi-byte nel javascript.
I dati
Ricorda di creare i database, le tabelle e i campi in MySQL con character set utf8 e collation utf_8_general_ci. Questo può essere fatto molto facilmente se si usano strumenti come PhpMyAdmin, perchè per ognuna di queste operazioni viene data la possibilità di specificare la collation.
La connessione
Accertati che la connessione tra PHP e MySQL avvenga nel giusto formato. Pertanto, appena effettuata la connessione, esegui sempre la seguente query:
SET CHARACTER SET utf8
Gli headers HTTP
Prima di qualsiasi output nello script, assicurati che anche la connessione HTTP avvenga in utf-8, eseguendo il seguente comando:
header('Content-type: text/html; charset=utf-8');
E’ consigliabile, poi, ripetere l’informazione anche all’interno della pagina HTML stessa, includendo nell’head la riga:
<meta http-equiv="Content-type" value="text/html; charset=UTF-8" />
Questo ovviamente nel caso più comune, ossia se l’output dello script è HTML o XHTML. Se stai producendo XML i due comandi sarebbero rispettivamente:
header('Content-type: text/xml; charset=utf-8');
e, all’inizio dell’XML:
<?xml version="1.0" encoding="utf-8" ?>
Le funzioni “pericolose” di PHP
Finita la fase preparatoria, puoi passare alla realizzazione dello script vero e proprio, momento in cui avrai a che fare con le numerose funzioni di PHP che potrebbero crearti grossi problemi se usate in un ambiente utf8 come quello appena creato. Puoi trovare un elenco minuzioso di tutte le possibili “trappole” nell’ottima documentazione di WACT.
A questo punto dovrai scegliere una delle seguenti strategie per aggirare il problema:
- usare l’estensione mbstring impostando l’overloading delle funzioni “standard”
- usare l’estensione mbstring sostituendo manualmente le funzioni “standard”
- usare una libreria dedicata come PHP UTF-8
- usare PHP UTF-8 e mbstring
Le alternative che ho elencato sono in ordine inverso di preferibilità.
La prima soluzione è infatti “quick and dirty” e può tornare molto utile se si intende adattare script già esistenti ad un ambiente utf-8. In pratica si tratta di installare l’estensione mbstring di PHP e poi dirgli di sostituire automaticamente molte delle funzioni “pericolose” con la loro alternativa multibyte. Per fare ciò basta inserire nel php.ini la seguente riga:
mbstring.func_overload = 7;
La soluzione può sembrare la migliore, ma potresti trovarti nei guai nel momento in cui vuoi lavorare, ad esempio, su un file binario o su un CSV salvato come ASCII.
Perciò potresti passare alla seconda soluzione, ossia sostituire manualmente i vari strlen, strtoupper eccetera in mb_strlen, mb_strtoupper…
Ma forse la soluzione migliore è quella di usare la libreria PHP UTF-8, che usa le funzioni mbstring qualora fossero presenti sul server o una versione alternativa per i server shared o in tutte quelle occasioni in cui non puoi installare estensioni.
Le entities
A questo punto hai affrontato quasi tutte le insidie (leggendo l’elenco di cui sopra ne scopro sempre di più!) dell’utf-8 in PHP e puoi goderti un piccolo lato positivo: puoi utilizzare i caratteri accentati nell’HTML senza bisogno delle relative entities. Quindi perchè non sostituire la vecchia funzione htmlentities con la nuovo utf8_entities?
function utf8_entities($str) {
return htmlentities($str, ENT_QUOTES, 'UTF-8');
}
Ringraziamenti
Molte delle informazioni contenute in questo tutorial sono prese dall’ottimo articolo PHP UTF-8 cheatsheet di Nick Nettleton e dalla già citata documentazione di PHP WACT. Grazie ad entrambi per i preziosi consigli.






7 commenti
Ciao, ti segnalo anche questo interessante post
http://www.zago-dev.net/appunti/programmazione/php/utilizzare-php-e-mysql-con-il-charset-utf-8.html
Giusto oggi parlavo con collega di UTF, import di dati, e \xc3\a8 (la e accentata in utf-8). Ora gli passo questo interessante post. Ciao, ZioBudda
utilissimo, grazie !
Porongo, piuttosto impreciso questo articolo.
“Salva tutti i file che compongono l’applicazione (sia template che script PHP) in utf-8″: presumo intendessi l’esatto contrario (cioè di salvarli in Latin1), dato che il problema del BOM si palesa nei files salvati in UTF8 da editor di testo pulciosi (tipo notepad) che aggiungono automaticamente il BOM ad inizio file.
“le tabelle e i campi in MySQL con character set utf8 e collation utf_8_general_ci”: totalmente irrilevante. Puoi usare charset/collation che più ti conviene, tanto il tutto viene convertito dopo nel charset del client.
“SET NAMES ‘utf8′ COLLATE ‘utf8_general_ci’
SET CHARACTER SET utf8″: basta il SET CHARSET.
ecc…
Ciao Nicola.
Effettivamente l’articolo non voleva essere un trattato scientifico sull’argomento, ma piuttosto una serie di consigli che “fanno funzionare le cose”, almeno per me.
Sul primo punto, però, sono in disaccordo. Se usi un sistema di template e salvi i file in latin1, potrebbe accadere che nonostante tu definisca il charset nell’html () il browser continui a ricevere file salvati in Latin1 e quindi ad interpretarli in questo modo.
Per quanto mi riguarda, quindi, la soluzione ottimale è salvare i file in UTF8 con un editor “non pulcioso”!
Sul secondo punto hai pienamente ragione, è un consiglio che ho dato per semplicità. Per coerenza, se stai sviluppando un’applicazione in UTF8, perchè mai salvare i dati su DB con un altro charset? Forse solo nel caso in cui volessi risparmiare dello spazio…
Per il terzo punto… hai ragione. Ora correggo.
Fammi sapere se hai notato qualche altra imprecisione.
Grazie mille!
well done, brother
Ciao nicola, riguardo al fatto di salvare i dati nel Db con un altro charset è TOTALMENTE sbagliato, in MYSQL li recuperi con il driver che effettua lui la conversione, ma se usi un altro Db (es. MSSQL ??).
Il mio consiglio è quello di uniformare il più possibile. TUTTE le pagine in UTF8, driver DB in UTF8 (dove possibile) DB in UTF8.