LEZIONE IV - Prova pratica di invio dati in XML
Nella lezione precedente abbiamo visto come è possibile inviare dei dati strutturati come documento XML da PHP verso JS, facendo in modo di utilizzare questi dati come oggetti JS.
Vi ricordo che a fine pagina trovere i link per scaricare l'esempio completo e per vederlo all'opera online.
Nell'esempio pratico che vedremo in questa lezione, aggiorneremo una lista di messaggi lasciati dagli utenti (come una chat), visualizzando gli ultimi 15 in ordine di inserimento.
Per operare con questo esempio, dobbiamo prima di tutto crearci una tabella dentro il nostro database, tabella che chiameremo
ajax_messaggio:
CREATE TABLE ajax_messaggio (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT ,
utente VARCHAR( 30 ) NOT NULL ,
messaggio VARCHAR( 100 ) NOT NULL ,
dataora TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL ,
PRIMARY KEY ( id ) ,
INDEX ( dataora )
) TYPE = MYISAM CHARACTER SET utf8 COLLATE utf8_bin;
Ora che abbiamo creato la nostra tabella nel DB, procediamo con la stesura de codice PHP che si preoccuperà di generare il documento XML per quando avviene la richiesta della lista messaggi, e inserirà i messaggi in DB quando qualcuno inserisce un nuovo messaggio. Nell'esempio pratico questa pagina l'ho chiamata
chat.php.
La pagina conterrà la connessione al database e dovrà effettuare 2 operazioni diverse:
- inserimento in database
- selezione dal database
A questo punto quando una pagina deve effettuare più di una operazione opto sempre per uno switch:
switch ( $_POST['act'] ) {
case 'aggiungi':
...
break;
case 'messaggi':
...
break
}
A noi non interessa l'inserimento (potete comunque vederlo scaricandovi lo ZIP di esempio), ma bensì la parte della selezione che genera il documento XML; verrà fatta una query nella nostra tabella che ci permetterà di estrarre i nostri messaggi. Nell'esempio ho estratto solo gli ultimi 15 messaggi, ma voi potete decidere di visualizzarne di più o di meno, nel seguente modo:
$q = " select * from ajax_messaggio";
$q .= " order by dataora desc";
$q .= " limit 15";
Addesso che abbiamo ottenuto i dati, provvederemo a generare il documento XML che dobbiamo inviare al JS che ha richiesto i dati, quindi procederemo nel ciclare i dati della query e a scrivere il nostro XML:
while ( $w = @mysql_fetch_assoc( $r ) ) {
$_xml .= "<record>";
$_xml .= "<utente><![CDATA[" . utf8_encode($w['utente']) . "]]></utente>";
$_xml .= "<messaggio><![CDATA[" . utf8_encode( stripslashes($w['messaggio']) ) . "]]></messaggio>";
$_xml .= "<dataora><![CDATA[" . utf8_encode($w['dataora']) . "]]></dataora>";
$_xml .= "</record>";
}
A questo punto otterremo un documento XML molto simil a quello visto nella lezione precedente, ovvero un contenitore con tanti sottogruppi che contengono i dati. Ora questo documento verrà trasmesso al nostro JS che lo interpreterà e stamperà di conseguenza i dati; vediamo quindi nel dettaglio come si comporta in nostro JS.
La parte relativa alla connessione l'abbiamo vista già più volte quindi la tralasciamo, a parte il seguente punto dove viene richiamata la funzione che stampa i messaggi nelle finestra della chat e dove viene inserito il timeout di "refresh" della finestra stessa:
messaggi( httpRequest.responseXML );
setTimeout( "refresh_chat()", 10000 );
Ho optato per un funzione di stampa dei risultati solo per tenere il codice più pulito e leggibile, ma nessuno ci vieta di inserire il codice direttamente nella richiesta
XMLHttpRequest.
L'unica parte "nuova" della connessione è la parte
var param = 'act=aggiungi';
param += '&utente=' + escape(utente);
param += '&messaggio=' + escape(messaggio);
httpRequest.send( param );
dove vengono preparati i dati da inviare alla nostra pagina PHP. Il modo di legare i dati è come quando viene composta una URL con parametri, poi la funzione
send() codifica i dati per l'invio in modalità POST e poi li invia.
Vediamo ora la funzione che cerchèò di spiegarvi nei vari punti così ci addentriamo anche nella generazione dinamica di oggetti:
imposto una variabile con l'oggetto chat, cioè il DIV che conterrà i nostri messaggi e elimino tutto il suo contenuto poichè andrò a scrivere i nuovi messaggi. Dato che l'utente non si accorge delle connessioni di "refresh" che vengono fatte, vedrà solamente apparire dei nuovi messaggi in testa agli altri; a questo punto non serve gestire solo l'aggiunta di un mesaggio e l'eventuale rimozione del 16^ messaggio che diventerebbe molto più complesso da gestire, mi limito solo a scrivere e basta:
var chat = document.getElementById('chat');
chat.innerHTML = '';
Già vista nella lezione precedente, estraggo tutti i gruppi "padre" contenenti i dati veri e propri:
var record = xml.getElementsByTagName('record');
Ora ciclo tutti i record contenuti nel documento XML e stampo i relativi messaggi all'interno della finestra chat. Come abbiamo visto in precenza, il documento XML viene visto come un documento HTML quindi possiamo estrarre il suo contenuto come se fosse tale:
for ( var i = 0; i < record.length; i++ ) {
var utente = record[i].getElementsByTagName('utente')[0].firstChild.nodeValue;
var messaggio = record[i].getElementsByTagName('messaggio')[0].firstChild.nodeValue;
var dataora = record[i].getElementsByTagName('dataora')[0].firstChild.nodeValue;
La cosa più semplice è copiare il codice e riutilizzarlo nelle proprie pagine, ma copiare senza capire prima o poi ci porta a non capire quello che stiamo facendo e procedere sempre e solo a tentativi. Vediamo come funziona l'oggetto che abbiamo estratto sopra (uno dei 3, tanto la tecnica è la stessa); prendiamo
utente.
Nel nostro documento XML l'elemento è scritto come:
<record>
<utente>...</utente>
...
</record>
quindi
record[i]. è il gruppo
i che stiamo leggento; nell'oggetto che racchiude tutto (il nostro record) estraiamo tutti gli elementi
utente con l'istruzione
getElementsByTagName('utente'); dato che l'istruzione restituisce un array di elementi, a noi basta il primo (perchè è anche l'unico), quindi aggiungiamo la dicitura
[0]. Ora abbiamo un nuovo oggetto che è praticamente
<utente>...</utente> e di questo noi dobbiamo prelevare il primo elemento (definito nodo), poichè anche un semplice testo per DOM è un elemento del nodo, quindi utilizziamo
.firstChild e con l'ultima istruzione
.nodeValue prendiamo il valore di questo nodo. Quindi per leggere una delle righe sopra dobbiamo partire sempre da destra verso sinistra (come i Giapponesi); se traducessimo tale riga in italiano sarebbe
estrai il valore del primo figlio del primo elemento utente dell'oggetto record i.
Ora che abbiamo i nostri dati iniziamo a creare gli elementi di quello che verrà visualizzato, prima di tutto il contenitore DIV che conterrà tutti gli elementi del messaggio
var div = document.createElement('div');
div.className = 'mex';
chat.appendChild( div );
poi il contenitore DIV che contiene il nome utente e la data di invio del messaggio (che verrà posizionato dentro il contenitore sopra)
var usr = document.createElement('div');
usr.className = 'r' + (i%2) + ' sin';
usr.innerHTML = utente + '<br><span>' + dataora + '</span>';
div.appendChild( usr );
e per finire il contenitore DIV che contiene il testo del messaggio (sempre posizionato dentro il contenitore sopra)
var msg = document.createElement('div');
msg.className = 'r' + (i%2) + ' des';
msg.innerHTML = messaggio;
div.appendChild( msg );
}
Per chi non conoscesse la dicitura
(i%2), con questa operazione ottengo il resto di una divisione (es. 1:2=0 con resto 1; 3:2=1 con resto 1) che nel nostro caso, considerando che la variabile
i inizia con 0 e si incrementerà di 1 per ogni messaggio, sarà alternativamente 0 e 1. In questo modo il primo messaggio avrà classe "r0", il secondo "r1", il terzo "r0", il quarto "r1" e via così fino all'ultimo messaggio. Questa tecnica ci pemette di differenziare le vari righe creando un alternanza di colori per facilitare la lettura.
Il codice completo da vedere e provare e l'esempio on-line per testarlo direttamente:
Scarica il file ZIP con il codice
Prova il funzionamento on-line
Vi ricordo che se volete testare il codice sul vostro PC dovete aver installato: web-server (Apache o simili), motore PHP e database MySQL.
Inoltre dovrete configurare la connessione al database su queste righe:
$sql = mysql_connect( 'server', 'username', 'password' );
mysql_select_db('database');
Alla prossima lezione!