Ajax (xAjax), Smarty e PHP

xAjax
Il motore per template che preferisco in assoluto e che utilizzo da tempo è Smarty.
In questi ultimi anni, negli applicativi sviluppati, ho iniziato ad integrare anche la tecnologia Ajax utilizzando come formato di scambio dati XML. Questo sistema rende alcune funzionalità molto più user-friendly e performanti. Ajax infatti permette di elaborare dati da una pagina web senza che questa venga rigenerata (leggi Iniziare con Ajax).
Da qualche mese ero alla ricerca di una classe PHP per Ajax e ne ho provate diverse senza trovarne una “in grado di integrarsi bene” con Smarty. Cercavo una classe che lasciasse il codice abbastanza pulito pur rimanendo molto flessibile.

In settimana ho letto un articolo nel quale si discuteva proprio di Ajax e Smarty. La classe PHP che maggiormente si presta ad essere integrata con Smarty sembra essere Xajax.

La soluzione che ho adottato infatti mi soddisfa parecchio e il codice risulta molto pulito e ordinato. Per valutare le performance è ancora presto ma per ora sembra essere abbastanza veloce.
Vediamo ora come integrare velocemente Xajax in Smarty.

Nell’esempio realizziamo una pagina web in cui è presente un campo di testo (text) attraverso il quale è possibile ricercare il nome di un’azienda. Inseriti più di 3 caratteri Ajax effettua la ricerca nel database e restituisce i risultati trovati riempiendo una combo che si sostituisce al campo di testo iniziale.

Ho scaricato l’ultima versione di Xajax e ho copiato i file php nella directory /include e quelli javascript in /javascripts in questo modo:

/include/Xajax/*.php
/javascripts/xajax_js/*.js

Ora consideriamo di avere il file index.php che carica il template index.tpl, nel quale è presente una richiesta Ajax.

index.php:

$smarty = new Smarty; // inizializzo Smarty class
// includo Xajax
require_once('Xajax/xajax.inc.php');
$xajax = new xajax();
/* debug */
// $xajax->debugOn();
// $xajax->statusMessagesOn();
/* debug */
// le funzioni che utilizzo sono tutte nel file
ajax-function.php !! $xajax->registerExternalFunction("searchAzienda","ajax-function.php",XAJAX_POST);
// process requests, creo javascript e lo passo al template
$xajax->processRequests();
$smarty->assign('xajax_javascript', $xajax->getJavascript("javascripts"));
// display template
$smarty->display('index.tpl');

Di solito utilizzo un header.tpl esterno e incluso nel template index.tpl (tramite framework). In questo è necessario inserire tra i tag head la seguente variabile:

{$xajax_javascript}

Sempre in index.tpl ho il codice del form che utilizza Ajax:

<label for="azienda">Azienda:</label>
<div id="select_azienda_link">
<input id="search_field" type="text" name="search" value="Cerca azienda..." size="25" maxlength="40" onblur="xajax_searchAzienda(this.value)" onfocus="this.value=''" />
</div>
<div id="select_azienda" style="display:none;">
<select id="combo_azienda" name="azienda">
<option value="">--</option>
</select>
<a href="javascript:void(0);" title="Nuova ricerca azienda" onclick="toggleDisplay('select_azienda');">RESET</a>
</div>

La funzione toggleDisplay visualizza o meno il div select_azienda.
Nel file ajax-function.php avrò la mia funzione che gestisce il caricamento dei dati della combo azienda in questo modo:

/*===============================*\
Function: searchAzienda
Purpose: Cerca aziende e abilita combo con risultati
Input: $search
Output: string (XML)
\*===============================*/
function searchAzienda($search)
{
// Instantiate the xajaxResponse object
$objResponse = new xajaxResponse();
// verifico se la stringa di ricerca è lunga almeno 3 caratteri
if( strlen($search) < 3 )
{
// testo risposta
$txt_response = "Inserire almeno 3 caratteri!";
$objResponse->addAssign("search_field", "value", $txt_response);
} else {
// set query
$sql = "SELECT iduser, ragsoc FROM users WHERE ragsoc LIKE '%".$search."%' ORDER BY ragsoc";
$array_az = db_all_in_ONE_array($sql,"iduser"); // tutti i record in un array con chiave iduser
if (count($array_az) > 0)
{
// disabilito visualizzazione campo di ricerca
$objResponse->addScript("document.getElementById('select_azienda_link').style.display='none';");
// abilito visualizzazione combo e tasto RESET
$objResponse->addScript("document.getElementById('select_azienda').style.display='block';");
// abilito e pulisco la combo
$objResponse->addScript("document.getElementById('combo_azienda').disabled = false;");
$objResponse->addScript("document.getElementById('combo_azienda').options.length = 0;");
// riempio la combo con i risultati, prima riga vuota di default
$objResponse->addScript("addOption('combo_azienda','Elenco risultati...','');");
foreach ($array_az as $iduser => $ragsoc)
{
// sistemo ragsoc se troppo lungo...
$ragsoc = substr($ragsoc, 0, 40);
$objResponse->addScript("addOption('combo_azienda','".$ragsoc."','".$iduser."');");
}
} else {
// testo risposta
$txt_response = "Nessun risultato trovato.";
$objResponse->addAssign("search_field", "value", $txt_response);
}
}
// close connection db
db_close();
//return the xajaxResponse object
return $objResponse->getXML();
}

E il gioco è fatto!