PHP & UTF-8: qualche indicazione utile

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 le due query seguenti:

SET NAMES 'utf8' COLLATE 'utf8_general_ci'
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:

  1. usare l’estensione mbstring impostando l’overloading delle funzioni “standard”
  2. usare l’estensione mbstring sostituendo manualmente le funzioni “standard”
  3. usare una libreria dedicata come PHP UTF-8
  4. 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 alternativamente 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.

2 commenti

  1. Pubblicato 18 Giugno 2008 alle 12:49 | Permalink

    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

  2. Pubblicato 18 Luglio 2008 alle 00:41 | Permalink

    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

Scrivi un commento

La tua e-mail non sarà mai pubblicata o ceduta ad altri. I campi obbligatori sono contrassegnati con un *

*
*