Configurazione avanzata di SWFAddress

SWFAddress è un’ottima libreria per il deep linking di applicazioni Flash e AJAX.

Nella sua configurazione di default il sistema è configurato per rilevare la presenza sulla pagina del codice di tracciamento di Google Analytics: quindi il tracciamento delle pagine interne avviene automaticamente una volta inserito il codice di Analytics.

Per utilizzare SWFAddress con altri servizi di statistiche è necessario come segue:

SWFAddress.setTracker(funzioneDiTracciamento);

In questo modo ad ogni cambiamento di URL verrà richiamata funzioneDiTracciamento con l’URL attuale come parametro.

In alcuni casi la funzione di tracciamento richiede dei parametri diversi dalla semplice URL. Il caso che ho affrontato è quello di ShinyStat la cui funzione di tracciamento è

ssxl('PAG=http://www.mysite.com/pagname')

Il problema viene facilmente aggirato creando una funzione ad hoc:

function shinyTracker(p) {
  ssxl('PAG='+p);
}
SWFAddress.setTracker(shinyTracker);

Buon deep-linking!

Primi passi con CodeIgniter (parte 3)

Il Model è la parte dell’applicazione che si occupa di gestire i dati; nella maggior parte dei casi si tratta di dati che vengono salvati su database. Il controller farà uso dei metodi disponibili nella classe model per ricevere i dati di cui ha bisogno.

Nella nostra applicazione di gestione di magazzino, possiamo immaginare di avere una tabella che cataloghi tutto il contenuto del magazzino. La tabella, molto semplicemente potrebbe essere:

CREATE TABLE `oggetti` (
`id` int(11) NOT NULL auto_increment,
`nome` varchar(50) collate utf8_unicode_ci NOT NULL,
`scaffale` int(11) NOT NULL,
`quantita` int(11) NOT NULL,
UNIQUE KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Il modello corrispondente, quindi, potrebbe essere:

class Oggetti extends Model {
  var $nome;
  var $scaffale;
  var $quantita;

  function Oggetti () {
    parent::Model();
  }

  function mostra_tutti () {
    // estrae tutti gli elementi dal database
  }

  function mostra_scaffale ($id_scaffale) {
    // estrae gli elementi filtrandoli per scaffale
  }

  // più i soliti metodi crea, modifica, cancella,...
  function crea ($nome, $scaffale, $quantita) { }
  function modifica ($id, $nome, $scaffale, $quantita) { }
  function cancella ($id) { }
}

Quindi in buona sostanza una classe che implementi i classici metodi CRUD più altri metodi d’utilità.

Per interrogare il DB, CodeIgniter fornisce una versione del pattern Active Record che semplifica la creazione di query e ci permette di scrivere codice indipendente dal tipo di database usato (attualmente i driver disponibili sono mssql, mysql, mysqli, oci8, odbc, postgres e sqlite).

La classe ActiveRecord fornisce metodi per la selezione, la modifica, l’inserimento e la cancellazione di dati. Inoltre sono supportate le funzioni più comuni (sum, avg…), le join, le transazioni e molto altro.

A questo punto possiamo entrare più nel dettaglio delle nostre funzioni e fare qualche esempio pratico:

  function mostra_tutti () {
    $out = array();
    $this->db->select('nome, scaffale, quantita');
    $this->db->order_by('nome');
    $query = $this->db->get('oggetti');
    foreach ($query->result() as $row) {
      $out[] = $row;
    }
    return $out;
  }

Per semplificare la sintassi è anche possibile utilizzare il chaining dei metodi:

$query = $this->db->select('nome, scaffale, quantita')
              ->order_by('nome')
              ->get('oggetti');

Per quanto riguarda la modifica e l’inserimento invece basta passare ai metodi insert() e update() un oggetto o un array di valori. In questo caso passeremo l’oggetto $this, ma potremmo anche creare un array od un oggetto ad hoc.

  function crea ($nome, $scaffale, $quantita) {
    $this->nome = $nome;
    $this->scaffale = $scaffale;
    $this->quantita = $quantita;
    $this->db->insert('oggetti', $this);
  }
 function modifica ($id, $nome, $scaffale, $quantita) {
    $this->nome = $nome;
    $this->scaffale = $scaffale;
    $this->quantita = $quantita;
    $this->db->where('id', $id);
    $this->db->update('oggetti', $this);
  }

Molto semplicemente la cancellazione sarà:

  function cancella ($id) {
    $this->db->where('id', $id);
    $this->db->delete('oggetti');
  }

Rimando come al solito alla guida per un ulteriore approfondimento della classe Database e dell’ActiveRecord. Inoltre consiglio di dare anche un’occhiata al meccanismo di Caching di CodeIgniter che può alleggerire di molto il carico sul database.

A questo punto siamo pronti per il lato di presentazione della nostra applicazione: la view, che affronterò nella prossima lezione.

Primi passi con CodeIgniter (parte 2)

Il manuale di CodeIgniter definisce il controller così:

A Controller is simply a class file that is named in a way that can be associated with a URI.

In realtà il controller nel paradigma MVC è quello che si occupa di gestire l’input e l’output dell’utente creando una sorta di “ponte” tra model e view. In effetti il controller in CodeIgniter è entrambe queste cose.

Immaginiamo di dover scrivere un’applicazione per la gesitione di un magazzino. Scriveremo allora una classe controller chiamata Magazzino simile a questa:

class Magazzino extends Controller {
  function elenco() {
    // elenca tutto il contenuto del magazzino
  }

  function scaffale($codice_scaffale) {
    // elenca il contenuto di un determinato scaffale del magazzino
  }
}

Salvando questa classe nella cartella system/application/controller/magazzino.php automaticamente CodeIgniter renderà disponibile l’output dei due metodi che abbiamo scritto rispettivamente agli indirizzi: misito.com/index.php/magazzino/elenco e miosito.com/index.php/magazzino/scaffale/a12.

In particolare nel secondo caso passerà alla funzione scaffale il codice scaffale ‘a12′.

Ovviamente si possono passare più parametri alle funzioni che ne hanno bisogno continuando ad aggiungerli separati da /. Si può anche migliorare la leggibilità degli indirizzi rimuovendo “index.php” con un htaccess simile a:

RewriteEngine on
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]

Ma non basta, perchè CodeIgniter ci permette anche di organizzare i controller in cartelle e sottocartelle o di definire nuove regole di “routing” aggiungendo regole al file system/application/config/routes.php.

Per queste ed altre funzioni avanzate, rimando alla guida ufficiale di CodeIgniter, in particolare alla pagina Controllers e URI Routing.

Alla prossima lezione, in cui parleremo del Model.

Primi passi con CodeIgniter (parte 1)

Dopo aver usato per molto tempo il mio “Cesare“, ho deciso che era ora di cambiare aria, e di provare una soluzione che mi consentisse di lavorare anche in gruppo con altri sviluppatori.

Ho dato un’occhiata ai framework più usati ultimamente e ovviamente sono rimasto affascinato da CakePHP. L’uso del pattern MVC e della filosofia “convention over configuration” mi sembravano molto interessanti. Dopo averlo usato un pò, proprio a causa di quest’ultima scelta, ho deciso di cambiare strada e di provare qualcosa che promettesse di meno dal punto di vista di rapidità di sviluppo, ma che mi permettesse qualche libertà in più.

E così sono approdato a CodeIgniter, anche questo un ottimo esempio di implementazione del paradigma MVC, ma in più molto più libero da convenzioni di Cake. In più è semplicissimo da utilizzare (la curva di apprendimento di Cake è molto più ripida), è leggero (anche in termini di kB), funziona anche con PHP4.

Per iniziare a lavorare con CI, è sufficiente:

  1. scaricarlo
  2. estrarre i contenuti del file zippato sulla root o in una cartella del proprio server
  3. modificare i file di configurazione che si trovano nella cartella system/application/config e in particolare config.php (la variabile $config['base_url']) e database.php (per la connessione al DB)

A questo punto tutto è pronto per scrivere il primo controller, argomento che afferonterò nella prossima lezione!

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 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:

  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 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.

Thanks to…

I wish to thank the following website for featuring and linking basmatitree.net: (in no particular order)

Il mio primo tema per WordPress

Dopo qualche settimana di lavoro, finalmente rilascio il mio primo tema per WordPress…

La caratteristica principale è il modo in cui vengono visualizzati i post in homepage: il primo occupa una colonna, mentre quelli successivi sono disposti su tre colonne.

Le sidebars sono 4 e sono disposte in fondo alla pagina.

Il tema supporta i widget, 2 livelli di “drop-down” menù e fa uso estensivo di tooltips per visualizzare un maggior numero di informazioni in poco spazio.

Scarica BT01 - Red Ceramic

Screenshot di BT01

FlashMessage jQuery plugin

Questo è il mio primo plugin per jQuery, anche questo ovviamente in beta! Serve sostanzialmente a far apparire in overlay sulla pagina uno (o più) messaggi e a farli sparire dopo qualche istante. Il tutto chiaramente ispirato a Humanized Messages for jQuery.

Vedi la demo oppure scarica il codice.

La parte meno convincente è ovviamente il posizionamento del blocco che contiene il messaggio. Per ora è centrato orizzontalmente e al 20% dal top verticalmente.

Nella prossima versione cercherò di posizionare il messaggio in maniera più opportuna, innanzi tutto tenendo conto dell’eventuale scroll verticale della pagina.

“Cesare” PHP Framework

Cesare è un framework per la creazione di siti in PHP.
Il codice è stato scritto da me e da Marco Suadoni nell’arco di più di un anno, quando eravamo colleghi presso kmstudio.
Cesare si basa sui concetti di semplicità e di modularità che a mio parere sono alla base di qualsiasi software valido.
Da qualche tempo abbiamo rilasciato il framework su licenza GPL. È scaricabile all’indirizzo http://code.google.com/p/cesare/.
Sebbene ancora in beta, e sicuramente ancora pieno di bugs, il framework è stato utilizzato con successo per la costruzione di un numero imprecisato di siti… direi più di una 40ina!
Scaricate il codice, miglioratelo, criticatelo… non fate morire Cesare!

Su questo blog presto pubblicherò degli esempi e dei tutorial su come usarlo.