Stefano Rodighiero
Perl Template Toolkit
http://www.perl.it/documenti/articoli/2007/02/perl-template-t.html
© Perl Mongers Italia. Tutti i diritti riservati.

Tra gli sviluppatori Perl circola una battuta scherzosa secondo la quale una delle tappe fisse dello studio del linguaggio è la realizzazione di un sistema di templating fatto in casa. Sono certo che si tratta di una battuta diffusa anche presso altri gruppi di programmatori, per lo meno tra coloro che usano linguaggi adatti allo sviluppo di applicazioni web.

Chi nella sua vita ha scritto almeno un CGI non può che trovarsi d'accordo: scrivere software nel quale codice applicativo e codice HTML si mescolano porta ad avere programmi poco scalabili, difficili da manutenere, soggetti ad errori e, particolare secondo me da non trascurare, brutti. La soluzione è semplice, almeno se ci si limita ad enunciarla: separare il codice applicativo dal codice che si occupa della presentazione dei contenuti, e adoperare un altro pezzo di software, chiamato sistema di templating, per far sì che questi due aspetti dell'applicazione possano parlarsi. I vantaggi sono molteplici:

  • Se le due "anime" del programma sono separate, allora se ne possono occupare persone diverse con competenze diverse: il programmatore, e solo il programmatore, toccherà il codice applicativo, mentre il web designer (o il programmatore addetto al frontend) si occuperà solo della parte HTML. Non si può verificare il caso, quindi, di un web designer che inserisce bug in un progetto cercando di apportare modifiche alla grafica di una pagina. O viceversa.
  • Il codice applicativo, svincolato dalla parte di programma che gestisce la presentazione, può essere più agevolmente strutturato in moduli ed eventualmente oggetti, e di conseguenza può essere più facilmente testato.
  • Per la stessa ragione, è più facile riutilizzare il codice già scritto e testato per realizzare un'altra applicazione Web.

Cattive pratiche

Ma per poter apprezzare appieno i vantaggi dell'approccio che andiamo ad esaminare, bisogna prima immergersi nel mare di svantaggi che l'alternativa reca con sè. Studieremo un piccolo esempio, percorrendone un plausibile ciclo di vita.

Supponiamo di essere nel bel mezzo della realizzazione di una applicazione web - una rivista online, ad esempio - e di voler aggiungere alla pagina un riepilogo degli ultimi dieci articoli inseriti. Il codice potrebbe presentarsi in questo modo (“il margine è troppo piccolo per contenere anche la gestione degli errori”, come diceva quel tale):

sub fetch_and_print_last_articles
{
    my $n = shift;

    my $output = "";
    my $query = qq{ select * from articles order by date desc limit $n };
    my $sth = $dbh->prepare( $query );
    $sth->execute();

    $output .= "<tr>";
    while( my $row  = $sth->fetchrow_hashref()) {
        $output .= "<td>$row->{ titolo } $row->{ autore }</td>";
    }
    $output .= "</tr>";

    return $output;
}

Nel programma principale, o nella subroutine che si occupa di generare la pagina, potrebbe poi comparire qualcosa del genere:

print_header();
print_title();
fetch_and_print_last_articles( 10 );

e così via...

Sembra un metodo poco astuto? Anche a me, ma quella che voglio mostrare è proprio la cattiva pratica, evidenziando in che modo essa preclude, o rende molto difficili, modifiche e miglioramenti futuri.

Il prossimo passo consiste nel provare a piegare questo codice a nuove esigenze. Un paio di esempi, assolutamente non accademici.

Si vuole modificare la resa estetica dell'elenco di articoli: in particolare, si decide che le tabelle sono vecchiume da abbandonare, e si vuole riorganizzare il tutto con magie CSS. L'unico modo per risolvere il problema è intervenire in fetch_and_print_last_articles(): non solo, dovrà farlo qualcuno che non solo conosce i CSS, ma che è anche in grado di capire un ciclo while, che conosca l'operatore di concatenazione e i meccanismi Perl di interpolazione nelle stringhe. Eppure, nella sua definizione, sembrava un problema di competenza del grafico: se non altro, era una bella speranza.

Altro problema: si scopre che la lista degli ultimi 10 articoli serve anche in un altro contesto: in questo caso ci sono due alternative. Si può copiare l'intera procedura e cambiarle nome e connotati, con lo svantaggio che ora bisogna mantenere due query e routine che hanno a che fare con la tabella “article”.

Oppure si può praticare una “operazione chirurgica”, separando tra loro la parte che preleva i dati dal DB e la parte che presenta i dati in forma HTML (con tabelle o CSS, a seconda). Il risultato potrebbe essere il seguente:

sub fetch_last_articles
{
    my $n = shift;

    my $output = "";
    my $query = qq{ select * from articles order by date desc limit $n };
    my $sth = $dbh->prepare( $query );
    $sth->execute();

    return $sth->fetchall_arrayref( {} );
}

sub print_last_articles
{
    my $articles = shift;

    my $output = "";

    $output .= "<tr>";
    foreach my $article ( @$articles ) {
        $output .= "<td>$article->{ titolo } $article->{ titolo }</td>";
    }
    $output .= "</tr>";

    return $output;
}

Potremo quindi scrivere:

my $articles = fetch_last_articles( 10 );
print_last_articles( $articles );

Siamo sulla strada giusta. Il codice applicativo è chiaramente separato da quello che governa la rappresentazione. Per quanto riguarda quest'ultimo, rimane il problema che è scritto in Perl, anziché in qualche linguaggio più vicino a quelli normalmente di competenza di grafici e “addetti al web”. I sistemi di templating servono a risolvere in maniera sistematica le questioni che abbiamo tratteggiato: incoraggiano (o forzano) la separazione tra logica e rappresentazione, e forniscono un linguaggio specifico e semplificato per la produzione dei contenuti. Torniamo a Template Toolkit.

Template Toolkit

Nel 1996 Andy Wardley, futuro autore di Template Toolkit, si trovò a dover fronteggiare i problemi appena esposti. Al tempo non c'erano molti sistemi di templating, quindi intraprendere la strada dello sviluppo di un sistema nuovo non era visto come un peccato capitale (in altri termini, non circolavano ancora battute scherzose). La soluzione che prese forma si chiamava Text::MetaText. Per usare le parole di Wardley: "[Text::MetaText era] il prototipo, quello che avevamo sempre progettato di buttare via". L'esperienza maturata durante la realizzazione di Text::MetaText ha consentito nel 1998 di cominciare a sviluppare Template Toolkit, che si è evoluto fino ad oggi, grazie anche al contributo della community Perl, diventando uno dei sistemi più potenti, efficaci e diffusi.

Se ritenete che l'idea di usare un sistema di templating sia buona, vale la pena di prenderlo in esame e di provarlo. Permette di gestire in maniera trasparente qualunque tipo di dato (scalari, liste, hash, oggetti, riferimenti a codice), ha una architettura a plugin che ne amplia le possibilità e consente agli sviluppatori di interfacciare al sistema stesso i propri moduli personali, dispone di un sistema di compilazione e caching dei template che ne aumenta la velocità e l'efficienza. Può naturalmente essere usato con mod_perl, eventualmente avvalendosi di Apache::Template, un'interfaccia per Template Toolkit che permette ad Apache di servire direttamente file tt2. Template Toolkit, come vedremo, può essere usato come uno strumento stand-alone, ma diventa particolarmente potente se a farne uso è uno sviluppatore Perl: troverà infatti un sacco di strumenti per aumentare la propria produttività e la rapidità d'uso di questo sistema.

Può essere usato, in vari modi, per la realizzazione di applicazioni web, ma non è detto che non possa rivelarsi utile anche in altri contesti. Template Toolkit dispone di una documentazione estesa e ben organizzata e, come è consueto per i progetti Open Source, di una mailing list nella quale si può chiedere aiuto direttamente ai suoi autori. O'Reilly l'anno scorso ha inoltre pubblicato un libro su Template Toolkit, scritto proprio da Andy Wardley insieme a Darren Chamberlain e Dave Cross.

Concetti di base

Come abbiamo detto, l'idea chiave dei sistemi di templating è separare il codice applicativo dal codice che riguarda la presentazione. Costruiamo un semplicissimo esempio per far vedere cosa vuol dire; cominciamo con un omaggio alla abitudine di imparare un linguaggio o un nuovo tool salutando "il resto dell'universo". Per iniziare creiamo un file chiamato salve.tt2 (tt2 come "Template Toolkit 2", ovviamente):

Salve, [% mondo %]!

D'ora in poi all'interno dei tag e ci saranno sempre direttive al Template Toolkit: fateci l'occhio. In questo caso stiamo chiedendo di mettere al posto della direttiva il contenuto della variabile mondo. Per provare questo semplice template costruiamo un piccolo script Perl:

#!/usr/bin/perl

use strict;
use warnings;

use Template;

my $template = Template->new();

$template->process( 'salve.tt2', 
                    { mondo => 'Repubblica del Perl' } 
                  );

Lo script istanzia un oggetto di classe Template e invoca il metodo process(), al quale viene passato il nome del file contenente il template e un riferimento all'hash table che contiene le variabili visibili al template, con i rispettivi contenuti.

$ perl salve.pl
Salve, Repubblica del Perl!

Si può passare al template qualunque tipo di dato Perl. Costruiamo un esempio più esteso, questa volta partendo dallo script Perl che richiamerà il template:

#!/usr/bin/perl

use strict;
use warnings;

use Template;
use Text::Morse;

my $template = new Template();

$template->process( 'miscellanea.tt2', {
    array   => [ qw/Mercurio Venere Terra Marte
                    Giove Saturno Urano Nettuno Plutone/ ],
    hash    => { Mercurio => 427,
                 Venere   => 480 
               },
    codice  => sub {
                   my $c = shift;
                   return $c * 9 / 5 + 32.0;
               },
    oggetto => Text::Morse->new()
} ) || die $template->error;

Come si può vedere ci siamo sbizzarriti: abbiamo passato un array, un hash, una procedura e addirittura un oggetto (in questo caso un'istanza di Text::Morse, un modulo scaricabile e installabile da CPAN che implementa una classe di codifica e decodifica del codice Morse). Il lettore più esperto si sarà accorto che tutto viene passato come riferimento. Sarà Template Toolkit a fare la cosa giusta per ciascun tipo di dato quando cercheremo di usarlo all'interno del template:

I pianeti del sistema solare sono i seguenti:
[% FOREACH planet = array %][% planet %] [% END %]
Ci si lamenta del caldo in estate, ma per sentirsi freschi
basterebbe pensare che la temperatura è di [% hash.Mercurio %]
gradi Celsius su Mercurio, e di [% hash.Venere %] su
Venere, pari rispettivamente a [% codice( hash.Mercurio ) %] 
e [% codice( hash.Venere ) %] gradi Fahrenheit.
Forse con il linguaggio giusto si può riuscire a
comunicare con gli alieni:
[% FOREACH line = oggetto.Encode( 'Ciao, spazio profondo!' ) %]
[% line %]
[% END %]

Organizzare logicamente i template

Se l'astrazione rappresenta una delle tecniche più potenti per gestire la complessità di un problema, non si vede perché non si dovrebbe applicare la stessa idea alla realizzazione di template. Così come un programma è organizzato in procedure ed eventualmente oggetti che modellano i processi e le entità del dominio applicativo, anche i template possono essere strutturati in maniera tale da modellare la struttura dei documenti che dobbiamo generare.

In effetti Template Toolkit mette a disposizione costrutti linguistici per organizzare logicamente i vari elementi che compongono i template. In tutti gli esempi che seguono verrà mostrato solo il template: lo script Perl pilota sarà di volta in volta del tutto analogo ad uno di quelli visti precedentemente.

Il metodo più semplice per importare il contenuto di altri file all'interno del template (e quindi all'interno dell'output) è l'uso della direttiva INSERT: essa si limita ad inserire carattere per carattere il contenuto del file specificato, senza interpretare le direttive Template Toolkit eventualmente presenti in esso. Se invece si vuole fare in modo che il contenuto del file sia trattato come codice Template Toolkit e il risultato inserito nell'output (che è la cosa che si vuole fare di solito), allora si deve usare INCLUDE oppure PROCESS: entrambi permettono di passare parametri al template chiamato.

La possibilità di organizzazione non si limita all'inserimento di file esterni. Si può usare la direttiva BLOCK per costruire vere e proprie procedure parametriche, il cui output è un blocco di testo.

[% BLOCK riga %]
<tr style="color: [% colore %]"><td>[% testo %]</td></tr>   
[% END %]
<table>
[% FOREACH n = nomi %]
[% PROCESS riga 
           testo  = n 
           colore = 'white' 
%]
[% END %]
</table>

Con i costrutti visti fino a questo punto si può già cominciare a fare delle cose utili, ad esempio delle pagine web:

[% INCLUDE header.tt2
           titolo = 'Il titolo della pagina' 
%]
<strong>Questo è il testo della pagina</strong>
[% INCLUDE footer.tt2 %]

I file header.tt2 e footer.tt2 contengono l'apertura e la chiusura fissa di un file HTML (se fate esperimenti scrivendo dei CGI, ricordate di scrivere da qualche parte anche l'header opportuno). Esiste in realtà un metodo più semplice: visto che la necessità di costruire un involucro attorno a dei contenuti è comune a molti task, Template Toolkit mette a disposizione un costrutto più evoluto (e più efficiente, visto che richiede la lettura di un solo file di template). Usiamolo per realizzare la stessa pagina di prima:

[% WRAPPER HTML_envelope.tt2
           titolo = 'Il titolo della pagina'
%]
<strong>Questo e` il testo della pagina</strong>
[% END %]

HTML_envelope.tt2 potrebbe ad esempio essere fatto così:

<html>
<head>
<title>[% titolo %]</title>
</head>
<body>[% content %]</body>
</html>

content è una variabile che viene passata implicitamente al template: essa rappresenta il contenuto che deve essere posto nell'involucro (o "wrappato", se preferite il neologismo) costituito da HTML_envelope.tt2.

Plugin

Abbiamo visto nei primi esempi che è possibile passare oggetti ad un template, e Template Toolkit provvederà a gestire opportunamente le chiamate ai metodi e l'accesso alle proprietà. Questa può essere una tecnica preziosa per avvalersi dei moduli di CPAN anche all'interno dei Template, ma cosa succede se, ad esempio, il modulo che vogliamo usare non ha un'interfaccia ad oggetti? Si potrebbe decidere di passare le procedure esportate dal modulo come riferimenti a codice, con una tecnica anch'essa già vista, ma Template Toolkit offre un metodo più elegante e maneggevole: la possibilità di scrivere plugin. Con un plugin si può estendere Template Toolkit, incorporando le funzionalità implementate nei propri moduli, oppure mettendo a disposizione dell'utente costrutti ancora più elevati. In effetti sono molteplici i plugin installati di default insieme a Template Toolkit. Vediamo qualche esempio:

  • Template::Plugin::DBI
    Basato su DBI, consente di interrogare database all'interno di un template.
  • Template::Plugin::Table
    Permette di stampare in forma di tabella una lista già passata ad un template.
    Ad esempio:
[% USE table( lista, cols = 3 ) %]
[% FOREACH row = table.rows %]
  [% FOREACH item = row %]
    [% item %]
  [% END %]
[% END %]
  • Template::Plugin::XML::Simple
    Interfaccia a XML::Simple: con un solo comando il contenuto di un file XML viene importato in una struttura dati corrispondente.
  • Template::Plugin::Dumper
    Molto utile in fase di debug, permette di stampare il contenuto di una struttura dati. È analogo a Data::Dumper.

Un caso particolare tra i plugin è rappresentato da Template::Plugin::Filter: si tratta in realtà di una classe base dalla quale partire per implementare i propri filtri, vale a dire procedure che trasformano l'input secondo le regole definite dal programmatore. Ad esempio potreste decidere di scrivere un filtro che consente a chi compone le pagine di usare un piccolo wiki-language, che verrà poi trasformato in HTML nella fase di processing del template. Gli Wiki sono sistemi per la gestione collaborativa di documenti che tipicamente usano un linguaggio meno scomodo di HTML per la redazione delle pagine: è a tale linguaggio che ci riferiamo con il termine wiki-language. Scriviamo dunque un esempio rudimentale per mostrare come funzionano le cose. Per prima cosa è necessario scrivere una classe nella quale verrà implementato il filtro:

package MyFilter::Wiki;

use strict;
use warnings;

use base qw/ Template::Plugin::Filter /;

sub filter
{
    my ($self, $text) = @_;

    $text =~ s{ ^ = \s+ (.*) }
              {<h1>$1</h1>}mgx;
    $text =~ s{ ^ == \s+ (.*) }
              {<h2>$1</h2>}mgx;
    $text =~ s{ \[ (.*) \] }
              {<a href="$1">$1</a>}gx;
        
    return $text;
}

1;

MyFilter::Wiki è figlio della classe Template::Plugin::Filter, e implementa un solo metodo filter() che riceve, oltre ad un riferimento all'oggetto, uno scalare contenente il testo da filtrare. Il resto della procedura applica delle semplici sostituzioni al testo (per maggiore ordine sono state scritte usando la sintassi s{}{} invece di s///) che implementano un abbozzo di sistema per scrivere più rapidamente titoli e sottotitoli in HTML, oltre che una scorciatoia per scrivere link. Naturalmente la procedura filter() si può estendere a piacimento: per esercizio, ad esempio, si potrebbe provare a scaricare da CPAN il modulo Text::WikiFormat e usarlo per arricchire le funzionalità del filtro.

Ecco il template

[% USE Wiki %]
[% FILTER $Wiki %]
= Il titolo della pagina
== Questo è un esempio d'uso dei filtri per Template Toolkit
[http://www.perl.it]
[% END %]

Abbiamo adoperato la direttiva USE, che è il modo per comunicare a Template Toolkit che vogliamo usare un plugin. Implicitamente verrà istanziato un oggetto di classe MyFilter::Wiki, e sarà associato alla variabile $Wiki. Infine, si usa la direttiva FILTER ... END per spiegare a Template Toolkit che tutto quello che si trova in mezzo a questi tag deve essere sottoposto al filtraggio. Concludiamo scrivendo un opportuno programma pilota in Perl. Rispetto a quelli già visti, la differenza è che si deve avere l'accortezza di dire a quale modulo corrisponde il plugin che viene usato nel template. È un'operazione che si compie al momento della creazione dell'oggetto $template, usando la direttiva di configurazione PLUGINS. Il caricamento del modulo funzione come al solito: esso deve essere in un luogo visibile dallo script Perl. Se lo script è, ad esempio, nella directory /home/lorenzo, allora il sorgente del modulo deve stare in /home/lorenzo/MyFilter/Wiki.pm. Ecco lo script:

#!/usr/bin/perl

use strict;
use warnings;

use Template;

my $template = new Template( {
    PLUGINS => { Wiki => 'MyFilter::Wiki' }
} );

$template->process( 'wiki.tt2', undef ) 
    || die $template->error;

Ed ecco l'output generato dal template:

<h1>Il titolo della pagina</h1>
<h2>Questo è un esempio d'uso dei filtri per Template Toolkit</h2>
<a href="http://www.perl.it">http://www.perl.it</a>

tpage e ttree

Finora abbiamo sempre scritto un piccolo script Perl per vedere che cosa producevano i template. In realtà Template Toolkit mette a disposizione un paio di potenti strumenti che possono essere utilizzati al posto di script simili al nostro. tpage e ttree vengono installati contestualmente ai moduli del Template Toolkit, inoltre sono scritti in Perl, cosa che ne facilita di molto l'eventuale modifica. L'utility più semplice è tpage. Usarla per rimpiazzare il primo script usato negli esempi è molto semplice:

tpage --define mondo="Repubblica del Perl" salve.tt2

tpage è solo una scorciatoia all'istanziazione di un oggetto Template, e la descrizione delle sue funzionalità si ferma qui: esso è però il fratellino minore di un altro strumento ben più potente, con il quale si può pensare di costruire e gestire un insieme di documenti anche di dimensioni ragguardevoli: ad esempio i documenti che compongono un sito web. Tale utility si chiama ttree, ed è per Template Toolkit ciò che make rappresenta per linguaggi di programmazione quali C o C++: preso un insieme di template, ttree prende in esame ciascuno dei file sorgenti, creando per ognuno di essi un file corrispondente contenente l'output dell'applicazione di Template Toolkit.

Probabilmente la maniera più semplice per descriverne le funzionalità è usarlo per costruire un semplicissimo sito: ad esempio una homepage. Lo spazio a disposizione consente di descrivere la realizzazione di una home molto piccola: conterrà solo una pagina di benvenuto e un elenco di bookmark. Naturalmente tutte le pagine dovranno essere omogenee quanto a grafica e menu di navigazione.

schema_ttree.png

Vediamo come Template Toolkit permette di facilitare tali operazioni. Per prima cosa dobbiamo configurare ttree secondo i nostri scopi: ttree si aspetta di trovare in un file di configurazione, che noi chiameremo ttreerc, una serie di direttive che ne pilotano il funzionamento. Le prime due sono la directory in cui si possono trovare i sorgenti e quella in cui andranno a finire i risultati del processing.

src  = /home/lorenzo/websrc
dest = /home/lorenzo/public_html

Tutti i file che verranno trovati verranno processati da Template Toolkit, e l'output finirà in file con lo stesso nome però contenuti nella directory /home/lorenzo/public_html. Alcuni file in realtà dovranno essere semplicemente copiati, ad esempio le immagini e i CSS (sempre che non abbiate un motivo per costruire i CSS usando un template). Spieghiamo anche questo a ttree:

copy = \.(jpg|png|css)$

L'espressione regolare rappresenta le estensioni dei file che vogliamo siano soltanto copiati. Analogamente, alcuni file andranno ignorati. Nel nostro caso soltanto il file di configurazione:

ignore = ttreerc

Per quanto detto in precedenza esisteranno anche una serie di file che non rappresentano pagine del sito, bensì i componenti necessari a produrre le singole pagine (ad esempio il wrapper che contiene i preamboli HTML comuni alle pagine, oppure il template che rappresenta il menu di navigazione del sito). Tutti questi elementi staranno in una directory il cui contenuto dovrà essere accessibile da qualunque posizione. Aggiungiamo questa linea al file ttreerc:

lib  = /home/lorenzo/websrc/lib

Visto che sarebbe bello riutilizzare il nostro filtro per generare le pagine, informiamo ttree della directory dove può trovare il modulo, e diciamogli anche il prefisso dei nomi dei package.

perl5lib  = /home/lorenzo/websrc/lib
plugin_base = MyFilter

In questo modo ttree si aspetterà di trovare il file sorgente del modulo, ovvero Wiki.pm, nella directory /home/lorenzo/websrc/lib/MyFilter.

Cominciamo mettendo un paio di file fondamentali in /home/lorenzo/websrc/lib: un
wrapper con le direttive HTML e il menu comune a tutte le pagine del sito:

__wrapper.tt2__
[% USE Wiki %]
<html>
<head>
<title>[% title %]</title>
</head>
<body>
[% INSERT menu.tt2 %]
[% FILTER $Wiki %][% content %][% END %]
</body>
</html>
__menu.tt2__
<a href="index.html">Home</a> || 
<a href="links.html">Links</a>

Notate che d'ora in poi tutte le pagine che usano wrapper.tt2 saranno automaticamente sottoposte al filtro Wiki. Proseguiamo costruendo la pagina di benvenuto del sito. La chiameremo index.html:

[% WRAPPER wrapper.tt2 title = 'Benvenuti!' %]
= Benvenuti nella mia homepage
Sito realizzato grazie a Template Toolkit
[http://www.template-toolkit.com]
[% END %]

Siamo pronti per completare la prima fase dell'esperimento. Lanciamo ttree e vediamo come i file vengono processati e l'output copiato nella directory di destinazione.

ttree -v -f ttree

ttree funziona come make: esecuzioni successive causano il ricalcolo solo delle pagine modificate (purtroppo però ttree non si accorge di modifiche ai template che stanno in lib, in questi casi si deve usare il comando touch su tutti i file candidati all'esportazione).

Un modo per gestire la propria lista di bookmark è scrivere i link in un file HTML e poi usare il wrapper per omologare la pagina alla grafica delle altre presenti sul sito. Un modo molto più furbo, nonché didatticamente più significativo, è invece memorizzare in qualche supporto indipendente dall'HTML i link e i loro commenti, e poi usare Template Toolkit per produrre una pagina opportuna. Ad esempio, grazie al plugin Template::Plugin::DBI è possibile memorizzare la nostra collezione di URL in una tabella, per poi lasciare a Template Toolkit il compito di generare la pagina.

Supponiamo di avere una tabella fatta così:

CREATE TABLE url (
    id int(10) unsigned NOT NULL auto_increment,
    url varchar(200) default NULL,
    description text,
    PRIMARY KEY  (id)
)

Allora un possibile template per gestire la collezione di link della nostra homepage è il seguente.

[% USE DBI( 'dbi:mysql:tt2example', 'utente', 'password' ) %]
[% WRAPPER wrapper.tt2 %]
= La mia collezione di bookmark
    [% FOREACH url = DBI.query( 'select * from url' ) %]
    <p>
    [[% url.url %]]<br />
    [% url.description %]
    </p>
    [% END %]
[% END %]

Si noti l'uso di DBI, e come al solito l'uso delle facilitazioni fornite dal modulo MyFilter::Wiki messo a punto nel precedente paragrafo.

Conclusione

Molteplici aspetti di Template Toolkit sono stati tralasciati o solo accennati: oltre al filtro che abbiamo scritto ce ne sono altri utili e già pronti; oltre ai plugin si possono definire anche metodi virtuali (a questo proposito, consultate la pagina del manuale Template::Manual::VMethods); infine, merita un esame il potente strumento delle viste.

Se Template Toolkit vi è parso versatile, o se vi è parso complicato (spero di no), allora sappiate che è ancora più versatile. O ancora più complicato. Consiglio vivamente di installare il modulo, far funzionare gli esempi ed esplorarne la documentazione.

copertina_50.jpg

Data di pubblicazione: Linux & C., anno 7, numero 50 (2006).

©2006-2007 Linux & C. Tutti i diritti riservati. E' vietata la copia e la riproduzione o ridistribuzione dell'articolo senza l'espresso permesso scritto dell'autore e dell'editore.