In questo articolo affronteremo un argomento di grande attualità: andremo alla scoperta dei QR Codes e vedremo come crearceli da soli attraverso il servizio Google Chart API e PHP.
Cosa sono i QR Codes
I QR codes sono dei codici a barre bidimensionali di forma quadrata pensati per essere letti e decodificati velocemente, caratteristica da cui prendono il nome: Quick Response.
Essendo sviluppati per essere decodificati velocemente, i QR Codes vengono utilizzati soprattutto per memorizzare informazioni (come la url di una pagina web o di una app, oppure un numero di telefono) che devono essere lette tramite dispositivi mobili (smartphone), i quali sono generalmente provvisti di software che ne permettono una facile decodifica.
Qui sotto vediamo un esempio pratico dell’uso dei QR codes, ne abbiamo, infatti, inserito uno contenente il link alla home-page di Mr.Webmaster. In questo modo, qualora l’articolo venisse stampato, sarà possibile accedere velocemente a questo sito web attraverso un qualsiasi dispositivo dodato di un interprete di QR Codes.
Altra caratteristica importante di questi codici è la robustezza. Infatti anche se danneggiati (si pensi, ad esempio, a delle macchie sulla pagina stampata) grazie al codice Reed-Solomon si è in grado di recuperare fino al 30% dell’informazione contenuta nel QR Code compromesso.
Vediamo, in questa tabella, i quattro livelli di correzione errori disponibili per i QR Codes e la relativa capacità di recupero:
Livello | % di dati recuperabili |
---|---|
L | 7% |
M | 15% |
Q | 25% |
H | 30% |
Capacità di memorizzazione
I QR codes possono contenere fino a 7.089 caratteri numerici, oppure fino a 4.296 caratteri alfanumerici. Essendo codici di forma quadrata hanno un numero uguale di righe e colonne, e proprio dal loro numero dipende la capacità di memorizzazione del QR Code. Il numero di righe e colonne di un QR Code viene identificato dalla sua version. Le version vanno da 1 a 40, e l’incremento di una version comporta l’aggiunta di 4 righe e 4 colonne, si parte da 21 per arrivare a 177. Quindi un QR Code di version 1 è un quadrato formato da 21 righe e 21 colonne con capacità di memorizzazione fino a 25 caratteri alfanumerici, mentre un QR Code di version 40 ha 177 righe e 177 colonne e capacità di memorizzazione massima.
Capacità di memorizzazione per alcune version:
Version | Righe x Colonne | Livello correzione dell’errore | Massimo numero di caratteri | |||
---|---|---|---|---|---|---|
Numerico | Alfanumerico | Binario | Kanji | |||
1 | 21×21 | L | 41 | 25 | 17 | 10 |
M | 34 | 20 | 14 | 8 | ||
Q | 27 | 16 | 11 | 7 | ||
H | 17 | 10 | 7 | 4 | ||
2 | 25×25 | L | 77 | 47 | 32 | 20 |
M | 63 | 38 | 26 | 16 | ||
Q | 48 | 29 | 20 | 12 | ||
H | 34 | 20 | 14 | 8 | ||
10 | 57×57 | L | 652 | 395 | 271 | 167 |
M | 513 | 311 | 213 | 131 | ||
Q | 364 | 221 | 151 | 93 | ||
H | 288 | 174 | 119 | 74 | ||
40 | 177×177 | L | 7,089 | 4,296 | 2,953 | 1,817 |
M | 5,596 | 3,391 | 2,331 | 1,435 | ||
Q | 3,993 | 2,420 | 1,663 | 1,024 | ||
H | 3,057 | 1,852 | 1,273 | 784 |
La capacità di memorizzazione di un QR Code dipende esclusivamente dalla sua versione e dal livello di correzione dell’errore (più il livello è basso e maggiore è la quantità di dati immagazzinabili), non dalla sua dimensione in pixel.
QR Code con Google Chart Api
Le Google Chart Api è una API messa a disposizione da Google che restituisce una immagine contenente un grafico in risposta a una richiesta fatta tramite GET o POST. Ci sono diversi tipi di grafici che si possono creare attraverso questa API, ma noi ci concentreremo esclusivamente sui grafici di tipo QR Code.
La url alla quale fare le richieste per ottenere un grafico è https://chart.googleapis.com/chart a cui vanno aggiunti i parametri necessari, che nel nostro caso sono:
- cht: Tipo di grafico, nel nostro caso cht=qr
- chs: Dimensioni dell’immagine nel formato larghezza x altezza
- chl: I dati da inserire nel nostro QR Code in codifica UTF-8
Con questi tre parametri siamo già in grado di creare il nostro QR Code, ma volendo abbiamo la possibilità di usare altri due parametri opzionali:
- choe: Codifica del grafico, i possibili valori sono: UTF-8 (Default), Shift_JIS, ISO-8859-1. Si consiglia di lasciare UTF-8 se non in caso di esigenze particolari.
- chld: Livello di correzione dell’errore: L (default), M, Q, H
La version del QR Code viene determinata automaticamente dall’API, che tiene in considerazione il numero di caratteri e il livello di correzione dell’errore selezionato. Bisogna tenere presente però che uno smartphone, normalmente, riesce a leggere solo QR Code fino alla version 4.
Un esempio di richiesta per la generazione di un QR Code è https://chart.googleapis.com/chart?cht=qr&chl=Hello+world&chs=200×200
QR Code con PHP e metodo GET
Vediamo ora come ottenere un QR Code attraverso una GET fatta in PHP. Iniziamo definendo la classe QRCode che come buona prassi vuole troviamo nel file qrcode.class.php:
<?php
class QRCode {
//tipo di chart
private static $_CHT = "qr";
//url della Google Chart Api
private static $_API_URL = "http://chart.apis.google.com/chart";
}
?>
Come possiamo vedere abbiamo definito solo due costanti che definiscono il tipo di grafico e la url base delle API. Aggiungiamo ora il metodo getQrCodeUrl per costruire la url completa per creare un QRCode:
public function getQrCodeUrl($data,$width,$height,$encoding=false,$correctionLevel=false) {
//faccio encoding dei dati
$data = urlencode($data);
//creo la url con i parametri obbligatori
$url = QRCode::$_API_URL . "?cht=". QRCode::$_CHT
. "&chl=" . $data
. "&chs=" . $width . "x" . $height;
//controllo i parametri opzionali
if($encoding){
$url .= "&choe=" . $encoding;
}
if($correctionLevel){
$url .= "&chld=" . $correctionLevel;
}
return $url;
}
Il metodo è molto semplice e si occupa di costruire una url attraverso i dati forniti, occupandosi anche di fare l’econding dei dati nel caso vengano inseriti caratteri non ASCII.
Ora possiamo testare la nostra classe attraverso questo codice di esempio che genera un tag <img> avente come parametro src la url costruita dinamicamente dal metodo getQrCodeUrl:
<?php
//includo la liberia
require_once 'qrcode.class.php';
//instanzio l'oggetto QRCode
$qrcode = new QRCode();
//renderizzo l'immagine
echo '<img alt="ciao" src="' . $qrcode->getQrCodeUrl("ciao",100,100,"UTF-8","H") . '" />';
?>
QR Code con PHP e metodo POST
Le richieste GET hanno un limite di 2Kb sulla lunghezza totale, quindi se vogliamo creare un QR Code che contenga più di 2Kb di dati la GET non ci è d’aiuto. In questi casi bisogna usare il metodo POST. Aggiungiamo quindi un metodo getQrCodeData alla nostra classe che si occuperà di fare una POST alla API di Google:
public function getQrCodeData($data,$width,$height,$encoding=false,$correctionLevel=false){
//faccio encoding dei dati
$data = urlencode($data);
// creo un'array con i parametri obbligatori
$parameterList = array(
'cht' => QRCode::$_CHT,
'chs' => $width . "x" . $height,
'chl' => $data);
//controllo i parametri opzionali
if($encoding){
$parameterList['choe'] = $encoding;
}
if($correctionLevel){
$parameterList['chld'] = $correctionLevel;
}
//creo il contenuto della post
$content = http_build_query($parameterList);
//creo il context
$context = stream_context_create(array('http' => array('method' => 'POST', 'content' => $content)));
//apro la connessione
$fp = fopen(QRCode::$_API_URL, 'r', false, $context);
//recupero i dati
$response = stream_get_contents($fp);
return $response;
}
Il metodo è molto simile al precedente e crea una lista di parametri che vanno a formare il contenuto della POST, vengono poi usate le funzioni fopen e stream_get_contents rispettivamente per fare la POST e per recuperare lo stream di dati dell’immagine. Per inserire l’immagine in una nostra pagina basta encodare i dati in BASE 64 e inserirli in un tag img in questo modo:
echo '<img src="data:image/png;base64,' . base64_encode($qrcode->getQrCodeData("ciao",100,100,"UTF-8","H")) . '" />';
Conclusioni
Le Google Chart Api sono molto potenti e molto facili da usare, quindi sono ideali per la generazione di QR Codes (non solo attraverso PHP).
Un’altra libreria interessante (ovviamente non è l’unica in circolazione) la si può trovare in questa pagina PHP QR Code. Scritta interamente in PHP e offre molte funzionalità tra cui la possibilità di usare una cache, ma si è deciso di non tenerla in considerazione poiché a mio avviso è poco e mal documentata.
Sotto vediamo uno screenshot della nostra pagina di esempio e il codice completo di questo articolo.
Segue il codice completo della nostra classe qrcode.class.php:
<?php
class QRCode{
//tipo di chart
private static $_CHT = "qr";
//url della Google Chart Api
private static $_API_URL = "http://chart.apis.google.com/chart";
//crea un qr code via GET
public function getQrCodeUrl($data,$width,$height,$encoding=false,$correctionLevel=false){
//faccio encoding dei dati
$data = urlencode($data);
//creo la url con i parametri obbligatori
$url = QRCode::$_API_URL . "?cht=". QRCode::$_CHT
. "&chl=" . $data
. "&chs=" . $width . "x" . $height;
//controllo i parametri opzionali
if($encoding){
$url .= "&choe=" . $encoding;
}
if($correctionLevel){
$url .= "&chld=" . $correctionLevel;
}
return $url;
}
//crea un qr code via POST
public function getQrCodeData($data,$width,$height,$encoding=false,$correctionLevel=false){
//faccio encoding dei dati
$data = urlencode($data);
// creo un'array con i parametri obbligatori
$parameterList = array(
'cht' => QRCode::$_CHT,
'chs' => $width . "x" . $height,
'chl' => $data);
//controllo i parametri opzionali
if($encoding){
$parameterList['choe'] = $encoding;
}
if($correctionLevel){
$parameterList['chld'] = $correctionLevel;
}
//creo il contenuto della post
$content = http_build_query($parameterList);
//creo il context
$context = stream_context_create(array('http' => array('method' => 'POST', 'content' => $content)));
//apro la connessione
$fp = fopen(QRCode::$_API_URL, 'r', false, $context);
//recupero i dati
$response = stream_get_contents($fp);
return $response;
}
}
?>
Segue, infine, il semplice codice che produce l’output (utilizzando, ovviamente, l’apposita classe):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test QR Code</title>
</head>
<h1>Test QR Code</h1>
<?php
//includo la liberia
require_once 'qrcode.class.php';
//instanzio l'oggetto QRCode
$qrcode = new QRCode();
//renderizzo l'immagine (metodo GET)
echo '<h2>GET MODE</h2>';
echo '<img alt="ciao" src="' . $qrcode->getQrCodeUrl("ciao",100,100,"UTF-8","H") . '" />';
//encodo i dati ricevuti dalla POST
echo '<h2>POST MODE</h2>';
echo '<img src="data:image/png;base64,' . base64_encode($qrcode->getQrCodeData("ciao",100,100,"UTF-8","H")) . '" />';
?>
</html>