lunedì 22 aprile 2013

PHP e stringhe con caratteri strani ossia il charset UTF-8 e dintorni nel PHP (Parte 2/4)

Il carattere sostitutivo UTF-8
per le codifiche errate
Ora che abbiamo un'infarinata su UTF-8 grazie al post precedente, vediamo come questo charset agisce all'interno delle comuni pagine PHP a partire da quelle che non contengono script ma semplice codice HTML.

Si supponga di aprire Blocco Note di Windows per editare il nostro primo file HTML.

Dopo aver inserito gli elementi di base desidereremo salvare il nostro lavoro. Oggigiorno perfino Blocco Note, quando arriva il momento di salvare un file, ci permette di stabilire la codifica dei caratteri.

Editiare in Blocco Note il seguente codice

<!DOCTYPE html>
<html>
<head>
<title>Questa è la mia Home Page</title>
</head>
<body>
<h1>Questa è la mia Home Page</h1>
<p>
Benvenuti nella mia Home Page, dove è
possibile trarre tanto materiale interessante.
Però fate attenzione a non perdere troppo tempo
davanti al computer, e pensate anche a divertirvi.
</p>
</body>
</html>

Quindi fare clic su File|Salva. Nella finestra di dialogo Salva con nome dal menu a tendina Salva come selezionare Tutti i file, quindi nel campo di testo Nome file inserire index.html. C'è infine una tendina chiamata Codifica. In questa tendina selezioniare UTF-8 che da oggi in poi adotteremo come charset per le nostre applicazioni web.
La finestra di dialogo Salva con nome di Blocco Note in Windows
Scegliere la posizione nel file system in cui salvare il proprio file, quindi fare clic su Salva.

Perchè utilizzare proprio UTF-8 per le proprie applicazioni web? E' velatamente adottato dal W3C come codifica per internet, sebbene nelle specifiche il W3C consenta l'utilizzo di altri charset essendo HTML aderente allo standard ISO SGML (Standard Generalized Markup Language). D'altra parte UTF-8 è capace di mappare tutto Unicode o UCS, rappresentando di fatto ogni possibile carattere utilizzato nel mondo. Ogni esempio sul W3C è fatto con charset UTF-8 (un motivo ci sarà). Altre codifiche come le ISO8859-x sono più limitate e possono creare problemi non essendo in grado, prese singolarmente, di codificare ogni possibile carattere ma essendo localizzate su specifiche aree geografiche.

Regola 1 - Utilizzare sempre dati codificati UTF-8 ci permette di lavorare con un solo charset indipendentemente dall'area geografica di appartenenza dell'utente

Provare ad aprire il file appena creato con un browser. Potremo notare che i caratteri accentati, codificati in UTF-8 con 2 byte, sono correttamente visualizzati. Come fa il browser a sapere che UTF-8 è il charset del documento?
La corretta codifica dei caratteri applicata dal browser in automatico
Ciò che non è segnalato da Blocco Note di Windows è che il file appena creato fa uso del BOM (Byte Order Mark). E' il carattere Unicode FEFF posto all'inizio di un flusso di byte (sia esso un file o una trasmissione dati via rete), utilizzato per segnalare a chi riceve il susseguente flusso che UTF-8 è la codifica adottata per i bytes.

Utilizzando Netbeans potremo aprire in modifica il nostro file e notare all'inizio dello stesso una sequenza di caratteri non inseriti da noi.
Il precedente file aperto in NetBeans utilizzando la codifica ASCII.
Si noti il BOM costituito da tre caratteri se interpretati con codifica ASCII all'inizio del file.
Quei tre caratteri all'inizio son il BOM. Si potrebbe pensare che non ci sia nulla di male ad avere quella sequenza, correttamente interpretata dai browser, e quindi anche comoda. La comodità però cessa quando si utilizza il PHP. Esistono infatti delle funzioni, come session_start(), header() o setcookie(), che per funzionare hanno bisogno di essere invocate prima che un qualunque output sia prodotto. Ma se quei tre byte del BOM precedono il tag di apertura dello script (<?php) si ha che dell'output, anche se non visibile, è stato prodotto causando l'invio dell'header. Ne consegue che tutte quelle funzioni php che hanno bisogno di inviare dati tramite header non funzionano più generando errori.

Regola 2 - Accertarsi sempre che l'editor si capace di salvare i file UTF-8 senza BOM

Ad esempio NetBeans o Notepad++ come mostrato nell'immagine sottostante lavorano tranquillamente su file UTF-8 senza BOM.
Le codifiche supportate da Notepad++
Aprendo con Notepad++ il nostro file codificato UTF-8, basta cliccare sulla nuova codifica UTF-8 (senza BOM) per eliminare il BOM e salvare il file in modo corretto. Ma il browser sarà ancora in grado di visualizzare correttamente il file?

I browser non possono riconoscere la codifica del file UTF-8 senza BOM
Purtroppo no, e i nostri caratteri accentati (rappresentati da due byte in UTF-8) sono stati rappresentati dal browser con due caratteri indesiderati. Ciò perchè il browser, non conoscendo il charset del documento, adotta quella di default del sistema che è ISO8859-1 nel mio PC con sistema operativo in italiano ma varia in base all'area geografica di appartenenza.

Occorre quindi informare il browser sulla codifica da adottare, ed è possibile farlo inserendo nel documento html, dopo il tag <head> il codice <meta charset="UTF-8"> per HTML5 o, per HTML5 e predecessori, compreso XHTML, si può utilizzare <meta http-equiv="Content-type" content="text/html;charset=UTF-8">. Scrivendo codice php è anche possibile inviare l'informazione tramite la funzione header('Content-Type: text/html; charset=UTF-8');.

Inserire con Notepad++ la riga di codice mancante ottenendo il codice seguente:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Questa è la mia Home Page</title>
</head>
<body>
<h1>Questa è la mia Home Page</h1>
<p>
Benvenuti nella mia Home Page, dove è
possibile trarre tanto materiale interessante.
Però fate attenzione a non perdere troppo tempo
davanti al computer, e pensate anche a divertirvi.
</p>
</body>
</html>

Salvare il file così modificato e riaprirlo nel browser. questa volta i caratteri sono correttamente visualizzati.

Regola 3 - Non basta salvare file in formato UTF-8, ma occorre che ogni elemento partecipante nel sistema sia coerentemente configurato/informato sulla codifica adottata.

Ciò vale per la codifica utilizzata dal file per la codifica utilizzata dal browser, ma anche per quella utilizzata dal DataBase (inteso come collation della tabella) e dal motore di DataBase inteso come elemento che si frappone fra la tabella e chi ne crea/legge/aggiorna/cancella i contenuti che nel nostro caso è PHP.

Nel prossimo post vedremo come si comporta PHP con UTF-8.