Smarty 3: 7 novità che non vedrete l’ora di usare

21/07/10
Di: postato alle: 10:44
Filed under: Programmazione — Tag:, , , — @ 10:44

Smarty-logoPer chi non lo conoscesse Smarty è uno dei più diffusi e potenti template engine disponibili per PHP.

Uso Smarty da più di 8 anni in qualsiasi progetto PHP debba sviluppare ed ha sempre compiuto il suo dovere alla grande, ma ha anche senza dubbio alcuni piccoli difetti che, seppur non rivelandosi mai bloccanti, rovinano un software altrimenti vicino alla perfezione.

Fin dalle prime versioni di sviluppo sto provando a utilizzare la versione 3 di Smarty che lentamente sta finalmente per raggiungere il suo primo rilascio stabile (è da poco uscita la RC3). Vediamo alcuni aspetti per cui varrà la pena fare l’upgrade di versione.

1. Riscrittura completa con un vero Lexer

Per questa nuova versione gli sviluppatori hanno deciso di riscrivere in maniera quasi completa il motore che effettua l’interpretazione del linguaggio e facendolo hanno implementato un vero e proprio lexer come quelli usati da molti linguaggi di programmazione, che gli garantisce molta più flessibilità internamente. Anche se per gli utilizzatori finali non sembra una novità degna di nota, questa riscrittura consente a smarty di superare molti limiti tecnici che si erano venuti a presentare nel corso degli anni nella versione precedente e sarà quindi interessante seguirne gli sviluppi futuri.

2. Addio tag {literal}/{ldelim}/{rdelim}

Se siete utilizzatori abituali di Smarty conoscerete sicuramente questi tag, che servono a poter utilizzare all’interno dei template le parentesi graffe senza chiamare in causa Smarty.

In smarty 2 se avessimo voluto stampare una funzione javascript all’interno del template di una pagina html avremmo dovuto ricorrere al tag literal o ai tag ldelim e rdelim:

<h1>In Smarty 2</h1>
<script type="text/javascript">
{literal}
function esempio() {
  alert('OK');
}
{/literal}
function esempio2() {ldelim}
  alert('OK');
{rdelim}
</script>

Come vedete fanno schifo entrambe le versioni, anche se di fatto questo non è mai stato un problema.

In Smarty 3 invece è possibile scrivere semplicemente:

<h1>In Smarty 3</h1>
<script type="text/javascript">
function esempio() {
  alert('OK');
}
</script>

Magia? Semplicemente il nuovo parser “capisce” che essendo la parentesi graffa isolata (è seguita da un a-capo, ma anche uno spazio avrebbe avuto lo stesso effetto), non deve essere interpretata come tag smarty.

Sebbene ci potrebbero essere ancora casi in cui questi sgraditi tag possano tornare utili, nella maggior parte dei casi non ci serviranno più.

3. Nuovo {foreach $array as $key=>$value}

Una delle sintassi peggiori di smarty 2 era il suo incomprensibile ciclo {foreach from=$array item=value} o l’alternativa per array con indici numerici {section}.

Finalmente è possibile usare:

{foreach $array as $key=>$value}
  <div>Chiave: {$key}</div>
  <div>Valore: {$value}</div>
{/foreach}

e per questo voglio dire solo una cosa agli sviluppatori: Grazie!

PS: c’è anche un tag {while CONDIZIONE}{/while}

4. Razionalizzati assegnamenti di variabili

Sapete qual’è un altro tag smarty che non sopporto e che finalmente posso smettere di usare? Il tag {assign}.

Finora se avessi voluto assegnare una variabile in smarty avrei dovuto fare così questa cosa orribile:

{assign name=var value="Mia variabile"}

Ora, sempre grazie al nuovo parser, si può assegnare una variabile semplicemente così:

{$var="Mia variabile"}
{$x=0}
{$x++}

Semplicemente fantastico!

5. Interpretazione variabili in stringhe con virgolette-doppie

Finora abbiamo visto modifiche di sintassi che rendono sicuramente più elegante il codice ma credo che questa novità le batte tutte.

Finalmente utilizzando le stringhe a virgolette doppie è possibile inserire variabili al loro interno e farle interpretare da smarty. Inoltre l’interprete è in grado di analizzare anche espressioni complesse, come calcoli matematici, rendendosi superiore al parser nativo del PHP.

{include file="blog_post.tpl" title="Post #{$postid}"}

{$x=2}
<div>{"x*3 = {$x*3}"|strtoupper}</div> <!-- X*3 = 6 -->

6. {if $var is in $array}

Nuovo comodo tag per verificare la presenza di un valore in un array. Meglio della sintassi originale del PHP usando in_array(), anche se a questo punto “is” mi sembra superfluo e avrei accorciato ancora in {if $var in $array} come in altri linguaggi…

7. Ereditarietà dei template

Eccoci alla “killer feature” di Smarty 3.

E’ ora possibile creare dei template che ereditano da altri template, vediamo un esempio pratico del funzionamento:

base.tpl

<html>
<head>
  <title>Prova</title>
</head>
<body>

{block name="body"}
  Questo sito è realizzato con smarty 3
{/block}

</body>
</html>

homepage.tpl

{extends file="base.tpl"}

{block name="body"}
<h1>{$smarty.block.parent}</h1>
<div>
  E realizzarlo è stato divertente.
</div>
{/block}

Ora visualizzando il template “homepage.tpl”, erediteremo la struttura del template “base.tpl”, ma il blocco di nome “body” sarà sostituito dalla nuova versione specializzata, che potrà comunque accedere al contenuto del blocco originale tramite la variabile {$smarty.block.parent}.

I blocchi possono anche essere annidati e sfruttare l’ereditarietà in questo modo può semplificare molto la complessità delle nostre pagine.

Conclusioni

Ci sono molte altre novità in questa nuova versione, ad esempio tutto il codice è ora ad oggetti e ci sono anche nuove funzionalità relative alla sicurezza, ma quelle degne di nota e che ho trovato più appaganti da usare sono sicuramente queste.

Smarty 3 è in sviluppo da quasi 2 anni credo, ma finalmente il momento del rilascio stabile sembra vicino e comunque posso dire da esperienza diretta che le ultime RC sono già molto stabili e garantiscono che non ci saranno più stravolgimenti di codice ma solo bugfix tra un rilascio e l’altro, quindi se voleste potreste iniziare a utilizzarlo già da subito senza pentirvene.

Post Correlati

6 Commenti »

  1. #1 Miky says:
    08/06/11 16:03

    Ciao
    Complimenti per gli articoli del blog, la gestione avanzata dei CSS è molto interessante.

    Ho scoperto smarty da poco in quanto cercavo proprio un template engine per un progetto in sviluppo, devo dire che ancora non m’è molto chiaro come poter strutturare al meglio i miei file tpl.

    In merito all’ereditarietà dei template (template inheritance) avrei voluto poter strutturare i tpl in questo modo
    base.tpl –> struttura base
    home.tpl –> raggruppa e organizza i tpl aggiuntivi che servono in quella pagina
    .tpl aggiuntivi (menu, slider etc) da includere in home.tpl

    per comodità i tpl aggiuntivi contengono html e chiamate a file js/css quest’ultimi vorrei che finiscano in un certo blocco in base.tpl

    un pò come viene chiesto qui http://stackoverflow.com/questions/4282511/smarty3-block-append-in-included-template

    Purtroppo al momento non si può fare i blocchi inclusi non fanno parte dell’editarietà..

    Quel che voglio chiederti è, per tua esperienza, quale soluzione potrei adottare?
    Devo per forza fare un controllo dei componenti aggiuntivi che mi serviranno a monte tramite php?

    Ciao
    Miky

  2. 09/06/11 10:32

    Ciao Miky, grazie per i complimenti!

    Ti propongo questa soluzione che ho usato in alcuni progetti:

    Definisci una funzione use_css($css), che prende in input il nome di un css e lo inserisce in uno stack.

    Definisci una funzione get_css() che restituisce il/i percorsi dei css da includere, in base allo stack che è stato riempito con varie chiamate a use_css.

    Ripeti stessa cosa con use_js($js) e get_js().

    In base.tpl inserisci un blocco di questo tipo, con le inclusioni generali di css e js:

    {capture “setup”}{block “setup”}
    {use_css(‘reset’)}
    {use_css(‘main’)}
    {use_js(‘mootools-core-1.3′)}
    {use_js(‘mootools-more-1.3.1.1′)}
    {/block}{/capture}

    (il tag capture fa in modo che non venga generato alcun output)

    Più in basso, sempre in base.tpl aggiungi anche:

    <link rel=”stylesheet” href=”/{get_css()}.css” type=”text/css” />

    e

    <script src=”/{get_js()}.js”></script>

    Mentre nei template “interni” (es: home.tpl) inserisci in un qualsiasi punto dei blocchi di questo tipo:

    {block “setup” append}
    {use_css(‘home’)}
    {use_js(‘home’)}
    {/block}

    Nel mio caso questa tecnica ha funzionato bene, spero di essere riuscito a spiegarmi, per entrare in dettaglio dovrei fare un articolo dedicato.

  3. #3 Miky says:
    09/06/11 17:46

    Ciao
    grazie per la risposta

    Credo di aver capito la tua tecnica, ma non mi pare possa funzionare con dei tpl extra di “terzo livello”

    ti spiego la struttura voleva esser questa
    – base.tpl
    — home.tpl
    — extra1.tpl
    — extra2.tpl
    — extra*.tpl

    ogni extra.tpl ha css e js suoi
    facendo il display di home.tpl gli extra.tpl non farebbero parte della catena di ereditarietà quindi non potrei utilizzarci {block “setup” append}

  4. 09/06/11 17:59

    Ok, ora ho capito meglio qual’è il problema.

    In effetti è una tecnica che non funziona. Io in generale tenderei a non includere i css come vorresti fare tu.
    Se cambi css a ogni pagina, sfrutti poco la cache dei browser, quindi preferisco includere qualche css che non viene sfruttato sempre e ingrandire un po’ la risorsa ma sfruttare meglio la cache tra richieste a pagine diverse piuttosto che guadagnare pochi byte.

    Ma se proprio vuoi utilizzarli come dicevi, forse riesci con la tecnica che ti ho descritto prima, ma usando un prefilter invece che dei {block} e delle funzioni. La realizzazione però diventa sicuramente più complicata.

  5. #5 Miky says:
    09/06/11 18:03

    riposto la struttura in quanto mi ha strippato gli spazi

    - base.tpl
    – home.tpl
    — extra1.tpl
    — extra2.tpl
    — extra*.tpl

  6. #6 Miky says:
    10/06/11 17:33

    Ok grazie mi guardo il metodo prefilter e vedo se mi conviene altrimenti includerò anche io css e/o js che potrei non sfruttare

    Ciao

Scrivi un commento