Realizzare un concorso sul Web in PHP: PHP e Mysql – parte 2/3
Posted on novembre 5, 2011
Filed Under Appunti di Php | Leave a Comment
Nell’articolo vedremo come realizzare praticamente il sistema studiato nella prima parte, mettendo in piedi le funzionalita’ indicate per permettere agli utenti di partecipare e vincere i premi messi a disposizione dal concorso su Internet.Una volta che l’utente arriva sul minisito creato ad hoc per l’iniziativa, dovra’ compilare un modulo che possiamo prevedere contenga questi campi tutti obbligatori ad eccezione della newsletter:
- nome
- cognome
- telefono
- provincia
- email
- newsletter
- privacy
Guidare l’utente e’ molto consigliato e lo aiuta ad evitare errori oltre che ad avere dati puliti sul database che potranno essere usati piu’ agilmente. Ad esempio, avere un menu’ a tendina per le province italiane (che sono ben definite), guida l’utente nella scelta obbligata e presentera’ nel database valori puliti, altrimenti potremo trovarci la provincia GR ma anche Grosseto o valori errati tipo Groseto.
Inoltre, qualora commettesse degli errori (es. non ha compilato alcuni campi obbligatori) e’ bene evidenziare l’errore e portare l’attenzione dell’utente nel punto ove ha commesso l’errore.
Una volta confermati i dati, il sistema verifica se sono stati rispettati i vincoli e procedera’ a farlo partecipare al concorso vero e proprio.
Nella parte centrale del concorso, qualora non sia espressamente richiesto, (Es.: vogliamo sapere cosa hanno risposto, a che punto si sono interrotti gli utenti che non hanno completato tutti gli step etc. etc.) non e’ necessario interferire con tecniche di programmazione. E’ quindi possibile fare la prima parte in HTML base con della buona grafica e sbizzarrirsi con animazioni in Flash o Flex nella parte centrale del concorso, per poi terminare con una parte in HTML e buona grafica.
Qualora fosse richiesto, e’ possibile far dialogare Flash con PHP in modo da avere anche la pagina dove e’ presente il modulo, dove inserire i dati in Flash. Sviluppare tutto il sistema in Flash potrebbe causare delle problematiche tecniche che se non ben gestite da sviluppatori Flash e PHP di skill piuttosto elevati; porterebbero al blocco del sistema, fughe di dati, o far lamentar gli utenti del concorso, nuocendo gravemente all’immagine dell’azienda che lo ha promosso anche per cause non direttamente imputabili alla funzionalita’ del sistema ma all’utente stesso. Un esempio può essere la caduta della connessione con l’swf che continua a girare visto che e’ stato gia’ scaricato sul pc dell’utente, con conseguente lamentela dell’utente sulla pagina Facebook dove viene promosso il concorso.
E’ bene quindi dotare il minisito di almeno un sistema (mail diretta, form di contatti, recapiti telefonici, live chat, risposte tecniche su Facebook qualora il concorso venga promosso tramite questo canale etc.) che permetta all’utente di rivolgersi all’assistenza per risolvere eventuali problematiche che potrebbero capitare o per aiutarlo a partecipare al concorso.
Una volta chiarite le dinamiche di funzionamento possiamo strutturare il database e la conseguente programmazione. Partiamo dalla struttura del database che conterra’ i campi dedicati ad accogliere i dati ed alcuni campi che ci serviranno per ragioni tecniche di sviluppo.
CREATE TABLE IF NOT EXISTS `cnc_utenti` (
`key_con` int(11) NOT NULL AUTO_INCREMENT,
`nome` varchar(80) NOT NULL,
`cognome` varchar(80) NOT NULL,
`telefono` varchar(120) NOT NULL,
`provincia` varchar(80) NOT NULL,
`email` varchar(120) NOT NULL,
`newsletter` enum(‘no’,'si’) NOT NULL DEFAULT ‘no’,
`numero_premi` int(11) NOT NULL,
`premio` enum(‘no’,'si’) NOT NULL DEFAULT ‘no’,
`data_giocata` date NOT NULL,
`ora_giocata` time NOT NULL,
PRIMARY KEY (`key_con`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Come vediamo ci sono dei campi aggiuntivi, in particolare:
- key_con il campo chiave primaria della tabella;
- data ed ora della giocata;
- numero_premi che conterra’ il numero dei premi consegnabili;
- premio che indichera’ se l’utente ha vinto o perso.
Andremo subito ad inserire un nuovo record con nel campo numero la scritta ‘premi’, nel campo numero_premi il numero massimo di premi consegnabili ed una data antecedente al concorso che conosciamo solo noi sviluppatori:
INSERT INTO `test`.`cnc_utenti` (`key_con`, `nome`, `cognome`, `telefono`, `provincia`, `email`, `newsletter`, `numero_premi`, `premio`, `data_giocata`, `ora_giocata`) VALUES (NULL, ”, ”, ‘premi’, ”, ”, ‘no’, ’3′, ‘no’, ’2011-10-23′, ’17:51′);
Eccoci pronti con la base di dati del concorso. Andiamo adesso a sviluppare il codice che permettera’ all’utente di registrarsi, rispondere alle domande e scoprire se ha vinto.
La prima pagina conterra’ il form dove l’utente potra’ inserire i propri dati che possiamo chiamare index.php e sara’ cosi’ fatta:
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<title>Concorso – BITuBIT</title>
</head>
<body onload=”document.modulo_login.nome.focus();”>
<script>
function inviaFormLogin()
{
var nome = document.modulo_login.nome.value;
var trattamentoDati = document.modulo_login.privacy.checked;
if ((nome == “”) || (nome == “undefined”)) {
alert(“Inserisci il tuo nome”);
document.modulo_login.nome.focus();
return false;
}
else if (!trattamentoDati) {
alert (‘Per proseguire occorre concedere il trattamento dei dati personali.’);
return false;
}
else
{
document.modulo_login.action = “inviaDati.php”;
document.modulo_login.submit();
}
}
</script>
<form method=”post” name=”modulo_login” onSubmit=”inviaFormLogin(); return false;”>
Nome: <input name=”nome” maxlength=”80″ value=”" /><br />
Cognome: <input name=”cognome” maxlength=”80″ value=”" /><br />
Telefono: <input name=”telefono” maxlength=”120″ value=”" /><br />
Provincia: <input name=”provincia” maxlength=”80″ value=”" /><br />
Email: <input name=”email” maxlength=”120″ value=”" /><br />
Newsletter: SI <input type=”radio” name=”nl” value=”si” checked=”checked” /> – NO <input type=”radio” name=”nl” value=”no” /> — Accetto l’utilizzo dei dati per fini commerciali sia da parte dell’azienda che da parte di terzi cui l’azienda vorra’ concedere i dati inseriti dall’utente. etc. etc.<br />
Privacy: <input type=”checkbox” name=”privacy” value=”si” /> Accetto tutti i termini del regolamento che e’ possibile leggere <a href=”#” title=”Regolamento”>cliccando qui</a> etc. etc.<br />
<input type=”submit” name=”invia_dati” value=”Partecipa >>” />
</form>
</body>
</html>
La pagina e’ fatta in modo che il cursorse venga posizionato al caricamento, (onLoad) subito sul campo nome del form per invitare l’utente a compilare il form.
Nella pagina e’ presente un controllo su alcuni campi, in particolare nome e privacy. Per rispettare il regolamento il controllo va esteso a tutti i campi obbligatori richiesti, per evitare che l’utente non completi tutti i campi obbligatori per distrazione o dolo.
Uno dei problemi di questo modulo e’ il fatto di non aver nessun tipo di controllo nei dati inseriti; se da un lato il classico captcha code evita questo tipo di problemi, dall’altro scoraggia l’utente nella compilazione. E’ conveniente inventarsi dei metodi validi ma meno intrusivi che evitino il mancato superamento a banali test di sicurezza che questo modulo non potrebbe superare se cosi’ presentato.
Una volta confermati i dati essi potranno essere processati dal sistema, in particolare dovremo creare una pagina chiamata messaggi.php cosi’ fatta:
<?php
if (!isset($messaggio))
$messaggio = “Accesso diretto non consentito.”;
?>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<title>Standard – BITuBIT</title>
<meta name=”robots” content=”noindex, follow” />
</head>
<body>
<?php echo($messaggio); ?>
</body>
</html>
La pagina semplicemente stampa ogni tipo di messaggio che gli viene passatto o, se richiamata direttamente, mostra un messaggio standard.
L’altra pagina contiene i dati che dovranno essere processati che chiameremo inviaDati.php e sara’ cosi’ fatta:
<?php
session_start();
// Connessione al datbaase…
$dbhost = ‘localhost’;
$dbusername = ‘root’; // Inserisci Utente del DB
$dbpasswd = ”; // Inserisci Psw dell’utente che accede al DB
$database_name = ‘test’; // Inserisci Nome del DB
$tbl_prefix = “cnc_”; // prefix delle tabelle.
$docRoot = “http://127.0.0.1/test/”; // Dove parte la struttura del sito…
$connection = @mysql_connect(“$dbhost”,”$dbusername”,”$dbpasswd”);
if (!$connection)
{
$messaggio = “<b>Impossibile collegarsi al server.</b><br><br>Per tornare in home page <a href=’”.$docRoot.”‘>clicca qui</a>”;
include(“messaggi.php”);
die();
}
$db = @mysql_select_db($database_name, $connection);
if (!$db)
{
$messaggio = “<b>Impossibile selezionare il database.</b><br><br>Per tornare in home page <a href=’”.$docRoot.”‘>clicca qui</a>”;
include(“messaggi.php”);
die();
}
// Dati dal form…
isset($_POST['nome']) ? $nome = mysql_real_escape_string($_POST['nome']) : $nome = “”;
isset($_POST['cognome']) ? $cognome = mysql_real_escape_string($_POST['cognome']) : $cognome = “”;
isset($_POST['telefono']) ? $tel = mysql_real_escape_string($_POST['telefono']) : $tel = “”;
isset($_POST['email']) ? $email = mysql_real_escape_string($_POST['email']) : $email = “”;
isset($_POST['provincia']) ? $prov = mysql_real_escape_string($_POST['provincia']) : $prov = “”;
isset($_POST['nl']) ? $nl = mysql_real_escape_string($_POST['nl']) : $nl = “”;
if (strlen($nome) == 0)
{
$messaggio = “Nessun nome presente. Ti invitiamo a verificare i dati: <a href=’index.php’>clicca qui</a>”;
include(“messaggi.php”);
die();
}
// Verifico se l’utente ha gia’ giocato (controllo la mail)…
$nomeTabella = $tbl_prefix.”utenti”;
$queryDoppioni = “SELECT * FROM $nomeTabella WHERE email = ‘$email’”;
$sqlDoppioni = @mysql_query($queryDoppioni);
if (($sqlDoppioni) AND (mysql_num_rows($sqlDoppioni) == 0))
{
// Memorizzi i dati nel database…
$query = “INSERT INTO $nomeTabella (nome, cognome, telefono, provincia, email, newsletter, data_giocata, ora_giocata) VALUES (‘$nome’, ‘$cognome’, ‘$tel’, ‘$prov’, ‘$email’, ‘$nl’, NOW(), NOW())”;
$sql = @mysql_query($query);
if ($sql)
{
$_SESSION['idSess'] = mysql_insert_id();
include(“step2.php”);
die();
}
else
{
$messaggio = “Impossibile memorizzare i dati. Per riprovare: <a href=’index.php’>clicca qui</a>”;
include(“messaggi.php”);
die();
}
}
else
{
// La query va a buon fine o meno ?…
if ($sqlDoppioni)
{
$messaggio = “Ci risulta che lei abbia gia’ giocato. Qualora ritenga che ci stiamo sbagliando la invitiamo a contattare l’assistenza. Per riprovare: <a href=’index.php’>clicchi qui</a>”;
include(“messaggi.php”);
die();
}
else
{
$messaggio = “Non e’ possibile completare la verifica dei dati. La invitiamo a riprovare: <a href=’index.php’>cliccando qui</a>”;
include(“messaggi.php”);
die();
}
}
?>
Nella pagina, come si vede, vengono trattati alcuni casi di errore tipici (mancata connessione al database, passaggio dati non corretto, esecuzioni di query non corretto, utente che rigioca). Altre tematiche di sicurezza vanno assolutamente affrontate perche’ la linearita’ del concorso venga rispettata. In tutti i casi di errore si cerca di diminuire il tasso di abbandono dell’utente riportandolo alla schermata dove verificare i dati inseriti per potergli permettere di giocare correttamente.
Una volta che i dati sono stati memorizzati correttamente, l’utente viene introdotto al gioco. Andremo a formulare una sola domanda per arrivare subito alla parte finale supponendo che le parti intermedie non interessano al cliente e che quindi vengano salvate. Ecco il codice della pagina relativa alla domanda (step2.php):
<?php
if (!isset($_SESSION['idSess']))
{
session_start();
if (!($_SESSION['idSess']))
{
$messaggio = “Impossibile accedere alla domanda.”;
include(“messaggi.php”);
die();
}
}
?>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<title>Gioco – BITuBIT</title>
</head>
<body>
<script>
function inviaFormGioco()
{
var val = 0;
for( i = 0; i < document.modulo_gioco.domanda.length; i++ )
{
if( document.modulo_gioco.domanda[i].checked == true )
val = document.modulo_gioco.domanda[i].value;
}
if (val == 0)
{
alert(‘Ti invitiamo a rispondere alla domanda’);
return false;
}
else
{
document.modulo_gioco.action = “finale.php”;
document.modulo_gioco.submit();
}
}
</script>
<form method=”post” name=”modulo_gioco” onSubmit=”inviaFormGioco(); return false;”>
Quale animale trovi in fattoria ?<br />
<input type=”radio” name=”domanda” value=”gatto” />Il gatto<br />
<input type=”radio” name=”domanda” value=”stella_marina” />La stella marina<br />
<input type=”radio” name=”domanda” value=”rinoceronte” />Il rinoceronte<br />
<input type=”submit” name=”invia_dati” value=”Rispondi >>” />
</form>
</body>
</html>
L’url della pagina che contiene la domanda non viene visto a video ma viene richiamato dalla pagina dove vengono memorizzati i dati. La sicurezza della pagina e’ obbligatoria. Cowe si vede e’ previsto un meccanismo per il quale solo se esiste una determinata variabile di sessione permettera’ l’accesso.
Viene inoltre verificato che l’utente risponda alla domanda con una delle risposte possibili, dopodiche’ lo proietta all’esito il cui codice sara’ il seguente (finale.php):
<?php
session_start();
if (!isset($_SESSION['idSess']))
{
$messaggio = “Impossibile accedere all’esito.”;
include(“messaggi.php”);
die();
}
// Connessione al datbaase…
$dbhost = ‘localhost’;
$dbusername = ‘root’; // Inserisci Utente del DB
$dbpasswd = ”; // Inserisci Psw dell’utente che accede al DB
$database_name = ‘test’; // Inserisci Nome del DB
$tbl_prefix = “cnc_”; // prefix delle tabelle.
$docRoot = “http://127.0.0.1/test/”; // Dove parte la struttura del sito…
$connection = @mysql_connect(“$dbhost”,”$dbusername”,”$dbpasswd”);
if (!$connection)
{
$messaggio = “<b>Impossibile collegarsi al server.</b><br><br>Per tornare in home page <a href=’”.$docRoot.”‘>clicca qui</a>”;
include(“messaggi.php”);
die();
}
$db = @mysql_select_db($database_name, $connection);
if (!$db)
{
$messaggio = “<b>Impossibile selezionare il database.</b><br><br>Per tornare in home page <a href=’”.$docRoot.”‘>clicca qui</a>”;
include(“messaggi.php”);
die();
}
$dataGiocata = “2011-10-23″; // Da personalizzare!!!
$id = mysql_real_escape_string($_SESSION['idSess']);
// Verifico che il contatto non abbia gia’ giocato (ogni contatto partecipa una volta)…
$nomeTabella = $tbl_prefix.”utenti”;
$queryPartecipa = “SELECT * FROM $nomeTabella WHERE key_con = ‘$id’”;
$sqlPartecipa = @mysql_query($queryPartecipa);
if (($sqlPartecipa) AND (mysql_num_rows($sqlPartecipa)>0))
{
$datiPartecipa = mysql_fetch_array($sqlPartecipa);
$nomeConcorrente = $datiPartecipa['nome'];
$email = $datiPartecipa['email'];
}
else
{
$messaggio = “Tentativo di accesso ad un contatto non valido.”;
include(“messaggi.php”);
die();
}
// Random di vincita….
$vinto = “NO”;
$queryChance = “SELECT * FROM $nomeTabella WHERE telefono = ‘premi’ AND data_giocata=’$dataGiocata’”;
$sqlChance = @mysql_query($queryChance);
if (($sqlChance) AND (mysql_num_rows($sqlChance)>0))
{
$dati = mysql_fetch_array($sqlChance);
$premiDisponibili = $dati['numero_premi'];
$idPremi = $dati['key_con'];
// Ho premi disponibili ? ….
if ($premiDisponibili>0)
{
// Random di vincita…
$numRand = rand(60,80);
if ($numRand == 69)
{
$premiDisponibili–;
$vinto = “SI”;
// Aggiorno il numero di premi
$updChance = “UPDATE $nomeTabella SET numero_premi = ‘$premiDisponibili’ WHERE key_con = ‘$idPremi’”;
$sqlUpdChance = @mysql_query($updChance);
}
}
}
if ($vinto == “SI”)
{
// Confermo la vincita all’utente…
$updChance = “UPDATE $nomeTabella SET premio = ‘si’ WHERE key_con = ‘$id’”;
$sqlUpdChance = @mysql_query($updChance);
// Invio mail…
$mittente = “info@bitubit.it”;
$fromName = “BITuBIT”;
$oggetto = “BITuBIT – Conferma vincita”;
$msgMail = “Gentile “.ucfirst(strtolower($nomeConcorrente)).”,<br>siamo felici di comunicarti che hai vinto<br><br><a href=’http://www.bitubit.it’ target=’_blank’>BITuBIT staff</a>”;
$resultMail = mail($email,$oggetto,$msgMail);
if(!$resultMail)
{
$messaggio .= “<br><br>Messaggio non inviato”;
$messaggio .= “Errori: ” . $mail->ErrorInfo;
$messaggio .= “<meta http-equiv=’refresh’ content=’5;url=index.php’>”;
}
else
{
$messaggio .= “<br><br>Informazioni inviate correttamente.<br><br>Sara’ nostra cura inviarti la documentazione per esigere il premio.”;
$messaggio .= “<meta http-equiv=’refresh’ content=’15;url=index.php’>”;
}
include(“messaggi.php”);
}
else
{
$messaggio = “Mi spiace non hai vinto!”;
include(“messaggi.php”);
}
session_destroy();
?>
Analizzando il codice si nota quanto segue:
- si accede alla pagina solo se esiste la variabile di sessione che identifica in modo unico l’utente;
- si verifica se l’utente esiste e si preleva il suo indirizzo mail ed il suo nome per usarli qualora vinca;
- si verifica la presenza di premi (Obs.: va personalizzata la query in base alla variabile $dataGiocata!);
- qualora ci siano premi si fa partire un meccanismo randomico che, qualora faccia uscire un numero scelto dallo sviluppatore (nel nostro caso il 69), premi l’utente. In base al range di numeri, aumentano (meno numeri disponibili) o diminuiscono (piu’ numeri disponibili) le probabilita’ di vincita.
- qualora l’utente vinca, si aggiorna la tabella diminuendo il numero di premi disponibili;
- se l’utente vince si memorizza la vincita e si comunica sia a video che via mail la vincita all’utente (Obs.: Vanno personalizzati tutti i messaggi ed i dati della mail in base al concorso);
- qualora l’utente non abbia vinto glielo si comunica a video.
- impedisco all’utente di rigiocare semplicemente rinfrescando (F5 o CTRL+F5) la pagina relativa all’esito distruggendo la sessione.
Qualora l’utente vinca e’ consigliato mettere in CCN (Copia Carbone Nascosta) il referente del progetto in modo che sia subito informato dell’evento e poter verificare rapidamente le informazioni inserite dall’utente e/o contattarlo per richiedere ulteriori informazioni per esigere il premio.
Chiaramente tutte le schermate del concorso andranno sottoposte ad un processo grafico che permetta all’utente di trovare piacere nel partecipare senza inficiare il funzionamento tecnico.
Una volta terminata la skin grafica di tutti gli step del concorso e’ sempre bene verificare il corretto funzionamento di tutte le dinamiche (vinto, perso, errore, tentativi di hack) onde evitare problemi dopo la messa online, piu’ difficilmente risolvibili, senza un’area di sviluppo analoga a quella live.
Nell’ultima parte della serie di articoli, andremo ad esportare i dati in maniera sicura e leggibile per l’azienda che dovra’ fruire dei contenuti.
Others Script adv
Leave a Reply