Infocurci - programmatore Php Roma
Infocurci - programmatore Php Roma
"faster than 98% of all tested websites" (tools.pingdom.com) - 100/100 Google PageSpeed Insights - Benvenuti :)

Mysql : Creare un sito in Unicode

Prima o poi capita a tutti di imbattersi in un sito, o un database, che non riesce a gestire caratteri particolari che arrivano in output all'utente sotto forma di punti interrogativi o simboli incomprensibili. Questo accade per siti che non implementano correttamente la specifica Unicode. Ecco i passaggi necessari per la corretta gestione di un sito in questo formato.

Mysql

Con il termine "Unicode" si definisce una codifica di caratteri che consente di gestire praticamente tutti gli alfabeti del mondo, compresi quelli diversi dal sistema occidentale come il cirillico o il cinese. Lo scopo di Unicode è ancor più nobile visto che si prefigge di codificare anche le lingue del passato e l'esperanto. Tutto questo è possibile grazie all'utilizzo di 21 bit, capaci di rappresentare oltre 1 milione di caratteri (unicode determina ogni carattere con un valore numerico, univoco, espresso in esadecimale). Il problema è che Unicode associa solo il valore al carattere, delegando l'effettiva conversione in byte ad un altro livello chiamato codec. Esistono diversi codec che però non coprono tutti i caratteri: ecco il motivo per cui ci troviamo a volte davanti a siti pieni di "?". Finchè il sito utilizza caratteri riconosciuti dal codec (ad esempio ISO/IEC 8859-1 gestisce l'alfabeto latino) funziona tutto, ma come appare un simbolo diverso, ad esempio la la "ñ", il sistema non riesce a rappresentare quanto dovuto. Per risolvere facilmente, possiamo utilizzare il codec oggi più completo: UTF-8.

Per la corretta gestione di un sito unicode è fondamentale che tutti parlino, è proprio il caso di dirlo, la stessa lingua:
- i sorgenti html devono essere salvati nel formato Unicode e nel giusto Codec (con UTF-8 possiamo gestire tutti i caratteri di unicode)
- il browser deve essere informato del fatto che il documento in questione va letto con la codifica UTF-8
- l'eventuale database deve anch'esso essere impostato per accogliere dati in formato UTF-8

Per il salvataggio dei sorgenti, il vostro editor html/php dispone senz'altro dell'apposita opzione. Su Geany ad esempio trovate la voce sotto "Documento /imposta codifica".
Per il browser, dovete inserire nell'<head> del vostro documento html questo meta:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
Per il database, potete settare la modalità UTF-8 come quella di avvio del server. Per far questo, dovete editare il file di configurazione del server (di solito /etc/my.cnf) in questo modo:
[mysqld]
default-character-set=utf8
default-collation=utf8_general_ci
character-set-server=utf8
collation-server=utf8_general_ci
init-connect='SET NAMES utf8'

[client]
default-character-set=utf8

ed ovviamente riavviare il servizio.
Le colonne che contengono valori testuali (char, varchar, text ecc) vanno impostate con la collation utf8_general_ci.

Infine, da php possiamo inviare l'apposito header:
header('Content-Type: text/html; charset=utf-8');

Un paio di nozioni che vi aiuteranno a capire meglio il discorso utf-8:
1) l'essenziale, per il database, è l'avvio in modalità Utf-8. La collation NON è la codifica con cui vengono salvati i dati ma la modalità con cui queste vengono trattate dalle apposite funzioni di confronto. Infatti un diverso set di caratteri comporta un diverso numero e ordine di lettere, ed è a questo che fà riferimento la collation. Infatti le collation terminano di solito con il suffisso _ci o _cs (case insensitive / case sensitive), per indicare se modalità in questione tiene o meno conto della differenza tra caratteri maiuscoli e minuscoli.

2) un esempio davvero esplicativo. Create un file php, salvatelo con codifica utf-8 e inserite questo contenuto:

<?php
    $stringa_1= '½°f§';
    $stringa_2 = 'ciao';
    echo 'la stringa 1 è lunga '.strlen($stringa_1).' caratteri<br>';
    echo 'la stringa 2 è lunga '.strlen($stringa_2).' caratteri<br>';
?>

Lanciate ora il file dal browser, nel vostro localhost (o se non avete una macchina sotto mano, pubblicatelo su internet).
Ecco il risultato:

la stringa 1 è lunga 7 caratteri
la stringa 2 è lunga 4 caratteri

visto? Nonostante le due stringhe contenessero 4 caratteri, la funzione php strlen() ne ha ritornati 7 per la prima stringa.
Contrariamente a quanto pensano in molti, strlen non ritorna il numero di caratteri di una stringa ma la sua grandezza in byte.
Nella seconda stringa, i due dati coincidono perché nella codifica Unicode i caratteri occidentali occupano i primi posti e fondamentalmente ad ogni carattere corrisponde 1 byte. Nella prima stringa invece abbiamo diversi caratteri "strani" che sono multi-byte, per cui a 4 elementi corrispondono in tutto 7 byte.
Tra l'altro il browser ha stampato non la stringa "é lunga" ma "è lunga" perché non abbiamo dato alcuna istruzione (nè un header php, nè un meta tag html) per fargli capire di trattare il contenuto come Unicode e quindi multi-byte.
Ecco ora l'esempio corretto:

<?php
    header('Content-Type: text/html; charset=utf-8');
    $stringa_1= '½°f§';
    $stringa_2 = 'ciao';
    echo 'la stringa 1 è lunga '.strlen(utf8_decode($stringa_1)).' caratteri<br>';
    echo 'la stringa 2 è lunga '.strlen(utf8_decode($stringa_2)).' caratteri<br>';
?>

Vi invito inoltre ad approfondire le funzioni per la gestione dei caratteri multibyte.