Eh si, devo dire che Pino ( utente di FlepStudio ) ha avuto una bella idea...ed io che mi scervello sempre per trovare nuovi argomenti da affiancare ai miei tutorials :)
Questo articolo vuole essere un tutorial per creare un contatore visite in Flash CS3 utilizzando l' ausilio di PHP e XML .
Oltre a visualizzare il numero delle visite, viene immagazzinata la data e ora di accesso dell' utente in un file XML.
Durante il caricamento e dialogo col server ho aggiunto una piccola animazione di numeri casuali fino a che la risposta del server è andata a buon fine.
Vediamo come funziona...
Ecco il contatore:
Creo un FLA che salvo con nome ' main.fla ' al cui interno:
- una MovieClip con nome istanza ' contatore_mc '
- un campo di testo dinamico con nome ' contatore_txt ' all' interno di contatore_mc
Creo la Document Class, un file AS che salvo con nome ' Contatore.as ', impelementata in questo modo:
Code:
package
{
import flash.display.MovieClip;
import flash.net.URLLoader;
import flash.net.URLVariables;
import flash.net.URLRequest;
import flash.net.URLRequestMethod;
import flash.net.URLLoaderDataFormat;
import flash.text.TextField;
import flash.display.SimpleButton;
import flash.events.*;
public class Contatore extends MovieClip
{
private var loader:URLLoader;
private var xml:LoadingXML;
private var richiedi_data:RichiediData;
public static var numero_visite_array:Array;
public static var data_array:Array;
public var tempo:int;
private var numeroVisita:Number;
public function Contatore()
{
init();
attivaEffettoConteggio();
caricaXML();
}
private function init():void
{
stage.frameRate=31;
numero_visite_array=new Array();
data_array=new Array();
}
private function caricaXML():void
{
xml=new LoadingXML(this);
}
private function addListeners(d:IEventDispatcher):void
{
d.addEventListener(Event.COMPLETE,completato);
}
private function completato(e:Event):void
{
var vars:URLVariables=new URLVariables(e.target.data);
if(vars.ok)
{
visualizzaContatore();
}
}
public function recuperaData():void
{
richiedi_data=new RichiediData(this);
}
public function inviaDati():void
{
var variables:URLVariables=new URLVariables();
numeroVisita=Number(numero_visite_array[numero_visite_array.length-1])+1;
variables.Visite=numeroVisita;
variables.data=getData();
var richiesta:URLRequest=new URLRequest();
//cambiare url al file PHP
richiesta.url='http://www.flepstudio.org/utilita/Contatore/aggiungiVisita.php';
richiesta.method=URLRequestMethod.POST;
richiesta.data=variables;
loader=new URLLoader();
loader.dataFormat=URLLoaderDataFormat.VARIABLES;
addListeners(loader);
try
{
loader.load(richiesta);
}
catch (error:Error)
{
trace('Unable to load requested document.');
}
}
private function getData():String
{
var millisecondi_server:Number=tempo*1000;
var d:Date=new Date();
d.setTime(millisecondi_server);
return ('accesso: '+d.toDateString()+d.toLocaleTimeString());
}
private function attivaEffettoConteggio():void
{
contatore_mc.addEventListener(Event.ENTER_FRAME,gira);
}
private function gira(e:Event):void
{
var num1:int=prendiNumeroRandom();
var num2:int=prendiNumeroRandom();
var num3:int=prendiNumeroRandom();
var num4:int=prendiNumeroRandom();
var num5:int=prendiNumeroRandom();
var num6:int=prendiNumeroRandom();
var num7:int=prendiNumeroRandom();
var num8:int=prendiNumeroRandom();
contatore_mc.contatore_txt.text=num1.toString()+num2.toString()+num3.toString()
+num4.toString()+num5.toString()+num6.toString()+num7.toString()+num8.toString();
}
private function prendiNumeroRandom():int
{
var n:int=Math.random()*10;
return n;
}
private function visualizzaContatore():void
{
contatore_mc.removeEventListener(Event.ENTER_FRAME,gira);
contatore_mc.contatore_txt.text=(numeroVisita).toString();
}
}
}
Creo una classe LoadingXML per caricare il file XML, un file AS che salvo con nome ' LoadingXML ', implementata così:
Code:
package
{
import flash.display.Loader;
import flash.display.MovieClip;
import flash.events.*;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.xml.*;
public class LoadingXML extends MovieClip
{
private var Root:MovieClip;
public function LoadingXML(m:MovieClip)
{
Root=m;
loadXML();
}
private function loadXML():void
{
var loader:URLLoader=new URLLoader();
loader.addEventListener(Event.COMPLETE,finito);
//cambiare url al file XML
var request:URLRequest=new URLRequest
('http://www.flepstudio.org/utilita/Contatore/contatore.xml?cachebuster='
+new Date().getTime());
try
{
loader.load(request);
}
catch(error:Error)
{
trace('Unable to load requested document.');
}
}
private function finito(event:Event):void
{
var loader:URLLoader=URLLoader(event.target);
var result:XML=new XML(loader.data);
var myXML:XMLDocument=new XMLDocument();
myXML.ignoreWhite=true;
myXML.parseXML(result.toXMLString());
var node:XMLNode=myXML.firstChild;
var n:int=int(node.childNodes.length);
for(var i:int=0;i < n;i++)
{
Contatore.numero_visite_array.push(node.childNodes[i].attributes['Visite']);
Contatore.data_array.push(node.childNodes[i].attributes['data']);
}
Root.recuperaData();
}
}
}
Creo una classe RichiediData per recuperare il tempo locale dal server, un file AS che salvo con nome ' RichiediData.as ', implementata in questo modo:
Code:
package
{
import flash.display.MovieClip;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLVariables;
import flash.net.navigateToURL;
import flash.events.*;
public class RichiediData extends MovieClip
{
private var Root:MovieClip;
public function RichiediData(m:MovieClip)
{
Root=m;
callServer();
}
private function callServer():void
{
var richiesta:URLRequest=new URLRequest();
//cambiare url al file PHP
richiesta.url='http://www.flepstudio.org/utilita/Contatore/gettime.php';
var loader:URLLoader=new URLLoader();
addListeners(loader);
try
{
loader.load(richiesta);
}
catch (error:Error)
{
trace('Unable to load requested document.');
}
}
private function addListeners(d:IEventDispatcher):void
{
d.addEventListener(Event.COMPLETE,completato);
}
private function completato(e:Event):void
{
var loader:URLLoader=URLLoader(e.target);
var vars:URLVariables=new URLVariables(loader.data);
Root.tempo=vars.time;
Root.inviaDati();
}
}
}
Questo è lo script gettime.php:
PHP Code:
<?php
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
echo "time=" . time();
?>
Questo è lo script aggiungiVisita.php:
PHP Code:
<?php
$ok = 1;
$file = "contatore.xml";
$depth = array();
function startElement($parser, $name, $attrs)
{
global $depth;
if(!empty($attrs))
$depth[] = $attrs;
}
function endElement($parser, $name)
{
global $depth;
$depth[$parser]--;
}
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false);
xml_set_element_handler($xml_parser, "startElement", "endElement");
if (!($fp = fopen($file, "r"))) {
$ok = 0;
die("could not open XML input");
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
$ok = 0;
}
}
xml_parser_free($xml_parser);
///get_variabiles
$nr = count($depth);
$nr++;
$depth[$nr]['Visite'] = $_POST['Visite'];
$depth[$nr]['data'] = $_POST['data'];
$content=('<?xml version="1.0" encoding="UTF-8"'.'?'.'>'."\n");
$content .= "<users>"."\n";
foreach($depth as $key => $value)
{
if(strlen($value['Visite'])>0)
{
$content .= '<item Visite="'.$value['Visite'].'" data="'.$value['data'].'" ></item>'."\n";
}
}
$content .= "</users>"."\n";
if(!($file_handle = fopen($file,'w')))
{
$ok = 0;
}
echo 'ok='.$ok;
fwrite($file_handle,$content);
fclose($file_handle);
?>
Clicca quì per vedere il file XML.
Analizziamo Actionscript.
Classe Contenitore.as
Proprietà:
un' istanza della classe Loader
private var loader:URLLoader;
un'istanza della mia classe LoadingXML
private var xml:LoadingXML;
un' istanza della mia classe RichiediData
private var richiedi_data:RichiediData;
un' istanza della classe Array, in cui inserirò i numeri degli accessi per recuperare l' ultimo ( statica perchè richiamabile da LoadingXML.as senza dover istanziare ancora Contatore.as )
public static var numero_visite_array:Array;
un' istanza della classe Array, in cui inserirò le date degli accessi ( statica perchè richiamabile da LoadingXML.as senza dover istanziare ancora Contatore.as )
public static var data_array:Array;
un' istanza numerica in cui inserirò i secondi che lo script gettime.php mi restituisce
public var tempo:int;
una variabile numerica in cui inserirò il valore dell' ultimo accesso
private var numeroVisita:Number;
Metodi
init();
imposto la velocità del frame rate
stage.frameRate=31;
inizializzo i due Array
numero_visite_array=new Array();
data_array=new Array();
attivaEffettoConteggio();
aggiungo un intervallo ENTER_FRAME che chiama la funzione/metodo gira() tante volte al secondo quanto è il valore del frame rate
contatore_mc.addEventListener(Event.ENTER_FRAME,gi ra);
gira();
creo 8 variabili numeriche e assegno un valore numerico casuale da 0 a 10 ( escluso ) che viene restituito dal metodo prendiNumeroRandom()
var num1:int=prendiNumeroRandom();
var num2:int=prendiNumeroRandom();
var num3:int=prendiNumeroRandom();
var num4:int=prendiNumeroRandom();
var num5:int=prendiNumeroRandom();
var num6:int=prendiNumeroRandom();
var num7:int=prendiNumeroRandom();
var num8:int=prendiNumeroRandom();
assegno del testo al campo di testo ' contatore_txt ' ( che è all' interno di contatore_mc ) con i valori concatenati a stringa delle 8 variabili numeriche
contatore_mc.contatore_txt.text=num1.toString()+nu m2.toString()+num3.toString()
+num4.toString()+num5.toString()+num6.toString()+n um7.toString()+num8.toString();
prendiNumeroRandom():int;
questa funzione restituisce un numero intero da 0 a 9 ( compreso )
creo una variabile numerica che ospita il valore casuale
var n:int=Math.random()*10;
restituisco lavariabile numerica
return n;
caricaXML();
istanzio la mia classe LoadingXML passandogli il valore della root ( che è la Document Class...appunto Contatore.as e quindi ' this ' ) che caricherà il file XML ( vedremo come )
xml=new LoadingXML(this);
inviaDati();
questo metodo verrà chiamato dalla classe LoadingXML.as al termine del caricamento del file XML
istanzio la classe URLVariables che conterrà le variabili da passare allo script aggiungiVisita.php
var variables:URLVariables=new URLVariables();
assegno alla variabile numeroVisita il valore dell' ultimo indice dell' Array ' numero_visite_array ' più uno
numeroVisita=Number(numero_visite_array[numero_visite_array.length-1])+1;
all'istanza URLVariables assegno 2 proprietà che sono i valori di numeroVisita e di un valore stringa che mi restituisce il metodo getData() ( che vedremo )
variables.Visite=numeroVisita;
variables.data=getData();
istanzio la classe URLRequest che farà la richiesta http dello script aggiungiVisita.php
var richiesta:URLRequest=new URLRequest();
assegno alla proprieà url della classe URLRequest l' url completo del file aggiungiVisita.php
richiesta.url='http://www.flepstudio.org/utilita/Contatore/aggiungiVisita.php';
dico a URLRequest di inviare le variabili ( variables.Visite e variables.data ) utilizzando il metodo POST
richiesta.method=URLRequestMethod.POST;
assegno alla proprietà data di URLRequest il valore di URLVariables
richiesta.data=variables;
istanzio la classe Loader di Flash
loader=new URLLoader();
formatto la stringa da passare allo script aggiungiVisita.php
loader.dataFormat=URLLoaderDataFormat.VARIABLES;
aggiungo i listeners necessari passandogli l' istanza della classe Loader
addListeners(loader);
chiamo lo script aggiungiVisita.php
try
{
loader.load(richiesta);
}
catch (error:Error)
{
trace('Unable to load requested document.');
}
addListeners(d:IEventDispatcher);
aggiungo un listener in ascolto solo dell' evento che segnala la fine del dialogo con lo script aggiungiVisita.php
d.addEventListener(Event.COMPLETE,completato);
completato(e:Event);
una volta che i dati sono stati inviati a aggiungiVisita.php e il php ha restituito il valore
creo una nuova istanza URLVariables e gli passo il valore dei dati di chi ha dispacciato l' evento ( loader, quindi e.target.data)
var vars:URLVariables=new URLVariables(e.target.data);
lo script aggiungiVisita.php restituisce un valore ( zero oppure uno ), uno se la scrittura del file XML è andata a buon fine e quindi come sappiamo, il valore uno in lato Boolean è visto come un ' true ' e quindi chiamo il metodo visualizzaContatore()
if(vars.ok)
{
visualizzaContatore();
}
visualizzaContatore();
fermo l' intervallo ENTER_FRAME
contatore_mc.removeEventListener(Event.ENTER_FRAME ,gira);
assegno al campo di testo ' contatore_txt ' il valore in stringa della variabile numeroVisita
contatore_mc.contatore_txt.text=(numeroVisita).toS tring();
getData():String
questo restituisce i valori di una nuova istanza della classe Date di Flash in formato stringa
creo una variabile numerica che ospita il valore dei millisecondi ( tempo, che sono i secondi restituiti da getitime.php, moltiplicato mille )
var millisecondi_server:Number=tempo*1000;
istanzio la classe Date
var d:Date=new Date();
dico a date la nuova data passandogli il valore in millisecondi
d.setTime(millisecondi_server);
restituisco la nuova data in formato stringa
return ('accesso: '+d.toDateString()+d.toLocaleTimeString());
Classe LoadingXML.as
Proprietà
una istanza della classe MovieClip che è la Document Class che passa se stessa al momento in cui istanzia LoadingXML
private var Root:MovieClip;
Metodi
loadXML();
vedi articolo come caricare un file XML esterno
finito();
una volta caricato l' XML assegno i valori agli array ' numero_visite_array ' e ' data_array ' della classe Contatore.as ( statici )
var n:int=int(node.childNodes.length);
for(var i:int=0;i < n;i++)
{
Contatore.numero_visite_array.push(node.childNodes[i].attributes['Visite']);
Contatore.data_array.push(node.childNodes[i].attributes['data']);
}
chiamo il metodo recuperaData della classe Contatore.as che istanzierà la classe RichiediData.as
Root.recuperaData();
Classe RichiediData.as
Proprietà
una istanza della classe MovieClip che è la Document Class che passa se stessa al momento in cui istanzia LoadingXML
private var Root:MovieClip;
Metodi
callServer();
chiamo lo script gettime.php che mi restituisce il tempo attuale in secondi
var richiesta:URLRequest=new URLRequest();
richiesta.url='http://www.flepstudio.org/utilita/Contatore/gettime.php';
var loader:URLLoader=new URLLoader();
aggiungo un listener
addListeners(loader);
try
{
loader.load(richiesta);
}
catch (error:Error)
{
trace('Unable to load requested document.');
}
addListeners(d:IEventDispatcher);
chiamo il metodo completato() una volta che il dialogo con gettime.php è terminato
d.addEventListener(Event.COMPLETE,completato);
completato(e:Event);
chiamo il metodo inviaDati() della classe Contatore.as che chiamerà lo script aggiungiVisita.php
var loader:URLLoader=URLLoader(e.target);
var vars:URLVariables=new URLVariables(loader.data);
Root.tempo=vars.time;
Root.inviaDati();
In sostanza:
- carico contenitore.xml
- recupero data e ora dal server
- invio i dati a aggiungiVisita.php che scrive il nuovo XML
- visualizzo il conteggio attuale
Allego i files sorgente:
Bookmarks