Nell'articolo precedente abbiamo terminato l'implementazione del template engine per il framework MVC Taste. Abbiamo discusso il codice analizzando il funzionamento del plug-in di default e della classe base Template
, che verrà utilizzata esplicitamente all'interno dei controller delle nostre applicazioni per poter rindirizzare correttamente i dati calcolati in base alle richieste intercettate dallo script di bootstrap.
In questo articolo vedremo come utilizzare praticamente il template engine, mostrando degli esempi di template funzionanti e concludendo con una semplice implementazione di un controller che utilizza il template engine per il rendering di alcuni dati, che verranno calcolati in base ai parametri inviati al controller stesso.
Alcuni esempi di utilizzo del template engine
Vediamo alcuni esempi di template che utilizzano i tag implementati dal plug-in di default; ogni template inizia con un preprocessore XML che identifica la versione e la codifica utilizzata nella definizione del file.
Se ben ricordate il plug-in di default è registrato ed assegnato all'uri http://php.html.it/taste
, a cui per comodità assegnerò l'alias tpl
. Gli attributi ed i tag definiti dal plug-in di default saranno quindi accessibili tramite questo alias, mentre tutti gli altri tag saranno interpretati come normali tag HTML.
Per prima cosa facciamo un semplice esempio di come utilizzare i gli attributi che modificano il contenuto o il valore stesso di un tag HTML in base al valore della variabile passata come argomento.
<?xml version="1.0" encoding="utf-8" ?> <html xmlns:tpl="http://php.html.it/taste"> <head> <title tal:content="title">Placeholder del titolo</title> </head> <body> <div tal:replace="html_message">Questo tag verrà sostituito dal altro HTML contenuto in html_message</div> </body> </html>
Per eseguire questo template utilizzeremo del semplicissimo codice PHP:
<?php
// include omessi per brevità
$template = new Template("path/to/mytemplate.tpl");
$template->title = "Titolo";
$template->html_message = "<strong>Hello</strong> World";
echo $template->render/();
?>
Che produrrà il seguente output:
<html> <head> <title>Titolo</title> </head> <body> <strong>Hello</strong> World </body> </html>
Per quanto riguarda i tag più complessi comunque il codice rimane sempre molto lineare e compatto; prendiamo per esempio in considerazione un template che include tutti i tag utilizzabili, che utilizzeremo come test per il corretto funzionamento del template engine:
<?xml version="1.0" encoding="utf-8" ?> <html xmlns:tpl="http://php.html.it/taste"> <head> <title>Titolo</title> </head> <body> <ul> <li tpl:repeat="users,user" tpl:content="user.name">User name placeholder</li> </ul> <div tpl:content="content">Contenuto originale</div> <i tpl:replace="replace">Da sostituire</i> <div tpl:omit="">Da omettere</div> <div tpl:condition="true_condition">True</div> <div tpl:condition="false_condition">False</div> <ul> <li tpl:attributes="style: test_style">Anno: $year</li> <li>Mese: $month</li> <li>Giorno: $day</li> </ul> </body> </html>
Questo template utilizza praticamente tutti gli attributi definiti nel plug-in di default; possiamo testarla con il seguente script in modo da controllare se il risultato sia l'HTML richiesto:
<?php // include omessi per brevità $data = array( // Alcune semplici variabili 'year' => date('Y'), 'month' => date('m'), 'day' => date('d'), 'replace' => '<b>Tag sostituito</b>', 'content' => 'Contenuto sostituito', // Test del tag attribute (lo sfondo verrà messo rosso ed il colore del testo bianco) 'test_style' => 'background-color:red; color: white', // Variabili da utilizzare per il test delle condizioni 'true_condition' => true, 'false_condition' => false, // Array contenente altri array che verranno utilizzati per testare il tag repeat 'users' => array( array('name' => 'gabriele farina'), array('name' => 'francesco caccavella'))); $template = new Template("path/to/mytemplate.tpl"); $template->assign($data); echo $template->render(); ?>
Applicando al template i dati di prova contenuti nella variabile $data
, possiamo testare che l'output generato risulti effettivamente come quello che avevamo previsto.
Definizione di un controller ed utilizzo delle view
Abbiamo visto alcuni semplici esempi che dimostrano il funzionamento del template engine in modo indipendente dal framework Taste. Vedremo ora come integrare il tutto all'interno di un semplicissimo controller che avrà come unico scopo quello di visualizzare una lista di parametri passati dal Router installato sul server. Il router passerà in automatico una serie di valori estraendoli dall'URL richiesto in base alle espressioni regolari seguenti:
"^show/?$" => "test.TemplateController.show", "^show/(d{4})/?$" => "test.TemplateController.show", "^show/(d{4})/(d{2})/?$" => "test.TemplateController.show", "^show/(d{4})/(d{2})/(d{2})/?$" => "test.TemplateController.show"
Il controller verrà posizionato all'interno della cartella test
, contenuta a sua volta nella directory di root dei controller.
<?php import('taste.mvc.Request'); import('taste.mvc.Controller'); import('taste.mvc.template.Template'); class TemplateController extends Controller { /** @description: Controller di prova */ public function show(Request $request, $first=null, $second=null, $third=null) { return Template::renderToResponse('test/mytemplate.tpl', array( 'first' => $first, 'second' => $second, 'third' => $third, 'get_params' => array_values($_GET) )); } } ?>
Il controller è molto semplice e si occupa semplicemente di inviare al template i dati provenienti dal Router e quelli inviati via GET alla pagina. Il template mytemplate.tpl
si occuperà invece di visualizzare questi dati all'interno di semplice codice HTML.
<?xml version="1.0" encoding="utf-8" ?> <html xmlns:tpl="http://php.html.it/taste"> <head> <title>Semplice template di test</title> </head> <body> <h3>Parametri passati al controller</h3> <p> <ul> <li><strong>First:</strong> $first</li> <li><strong>Second:</strong> $second</li> <li><strong>Third:</strong> $third</li> </ul> </p> <h3>Valori dei parametri passati in GET</h3> <p> <ul> <li tpl:repeat="get_params,value">$value</li> </ul> </p> </body> </html>
Scrivere e testare un plug-in
L'ultima operazione che risulta interessante provare è la stesura di un plug-in aggiuntivo per il template engine. Il plug-in implementerà un semplicissimo tag ed un semplicissimo attributo: il primo si occuperà di visualizzare la data odierna mentre il secondo aggiungerà un bordo nero all'elemento a cui sarà associato (utilizzando uno stile inline).
<?php require_once 'taste/mvc/template/Scope.php'; require_once 'taste/mvc/template/Template.php'; require_once 'taste/mvc/template/TemplatePlugin.php'; class CustomPlugin extends TemplatePlugin { public function attribute_border(Template $template, Scope $scope, $node, $expression) { $node->setAttribute('style', 'border: 1px solid #000'); $template->evaluateNode($node, $scope); } public function tag_date(Template $template, Scope $scope, $node) { $fragment = $node->ownerDocument->createDocumentFragment(); $fragment->appendXML("<div><strong>Data:</strong>".date("d/m/Y")."</div>"); return $fragment; } } Template::registerPlugin("http://php.html.it/taste/custom_plugin", new CustomPlugin); ?>
Questo plug-in verrà associato all'URI http://php.html.it/taste/custom_plugin
e potrà essere utilizzato all'interno del template tramite questo namespace. Vediamo un semplice esempio conclusivo, in cui testeremo anche il corretto funzionamento del default namespace:
<?xml version="1.0" encoding="utf-8" ?> <html xmlns:tpl="http://php.html.it/taste" xmlns:custom="http://php.html.it/taste/custom_plugin" > <head> <title>Test di un plug-in custom</title> </head> <body> <h3>Data odierna tramite alias</h3> <custom:date /> <h3>Data odierna tramite default namespace</h3> <date xmlns="http://php.html.it/taste/custom_plugin" /> <div custom:border="">Dovrebbe funzionare tutto ;)</div> </body> </html>
Possiamo testare questo template senza alcun parametro, utilizzando il metodo renderToResponse
della classe Template
senza alcun parametro aggiuntivo. L'unico accorgimento necessario è l'inclusione del file contenente la definizione del plug-in prima che la classe Template
venga inizializzata ed utilizzata per il rendering.