Oggi i sondaggi sono quasi onnipresenti sul web e ci sono molti servizi che ti forniranno un sondaggio. Ma cosa succede se vuoi scriverne uno tu stesso? Questo tutorial ti guiderà attraverso i passaggi per creare un semplice sondaggio basato su PHP, inclusa l'impostazione del database, l'elaborazione del voto e la visualizzazione del sondaggio.
Per memorizzare i risultati del sondaggio, verranno memorizzate tre informazioni:
Per questo tutorial, utilizzeremo PDO e SQLite. Se stai lavorando con SQLite3, puoi creare un nuovo database tramite lo strumento della riga di comando; se stai usando una versione precedente, un rapido script PHP farà il trucco. Ecco quello utilizzato per questo tutorial:
setAttribute (PDO :: ATTR_ERRMODE, PDO :: ERRMODE_EXCEPTION); $ dbh-> exec ('CREATE TABLE tally (QID varchar (32) NOT NULL, AID intero NON NULL, voti intero NOT NULL, PRIMARY KEY (QID, AID))'); catch (PDOException $ e) echo "ERRORE !!: $ e"; Uscita; echo "db creato con successo."; ?>
Questo semplice script creerà un database SQLite nella directory in cui viene eseguito. A differenza di mySQL, il database qui è un file flat. Se hai familiarità con SQL, il creare
dovrebbe avere senso per te, anche se l'ultima riga potrebbe essere nuova per alcune persone:
CHIAVE PRIMARIA (QID, AID)
Questo crea a chiave composita per il database. Le voci in entrambe le colonne non devono essere univoche per quella colonna, ma la combinazione delle due deve essere unica.
Prima di iniziare a scrivere qualsiasi PHP, devi decidere come creare il tuo sondaggio in termini di markup. Cercheremo di mantenere il markup il più semantico e semplice possibile. Il tuo sondaggio avrà due aspetti:
Nello scrivere questo HTML, alcune classi saranno incluse per aiutare in seguito con il CSS.
Poiché un sondaggio è principalmente un elenco di risposte, incorporeremo un elenco non ordinato per contenere tali risposte. Per la domanda stessa, useremo un tag intestazione.
È piuttosto semplice, ma non include alcun elemento del modulo. I pulsanti di opzione sono i più appropriati dal momento che stiamo consentendo una sola risposta per sondaggio. Inoltre, useremo il tag label per associare le risposte con il pulsante di opzione appropriato. Ora il nostro modulo HTML sembra più simile a questo:
È un po 'più complesso, ma non troppo male. Ancora un po 'di più da aggiungere. Includeremo un tag fieldset per aprire alcune opzioni di stile e ovviamente abbiamo bisogno di un pulsante di invio!
Per ogni risposta, viene aggiunto un nuovo tag LI e il valore del pulsante radio incrementato. Questo alla fine sarà fatto dal nostro PHP. L'HTML extra è il tag fieldset e il paragrafo racchiuso tra i pulsanti, entrambi utilizzati dal nostro CSS.
L'HTML sarà quasi identico per la visualizzazione della risposta. I tag dell'elemento pubblicitario non conterranno un elemento del modulo e aggiungeremo un div che può essere utilizzato per mostrare la percentuale di voti che ha ricevuto la risposta. Ecco come apparirà:
Sì, è uno stile in linea che vedi lì. Questo stile verrà generato dal nostro PHP in base all'attuale percentuale di ogni singola risposta. Ecco cosa abbiamo finora:
L'HTML che abbiamo creato nell'ultimo passaggio non era molto interessante. Vediamo se possiamo aggiustarlo un po '. Utilizzeremo la meravigliosa libreria CSS3 PIE (progressiva Internet Explorer) in modo da ottenere un aspetto simile su tutti i browser. Per far funzionare correttamente questa libreria, ci sono numerosi casi in cui è necessario applicare una posizione relativa agli elementi. Puoi leggere tutti i dettagli sul sito web della biblioteca.
Utilizzeremo il tag form come nostro contenitore. Avrà degli angoli gradevoli e arrotondati e un po 'di ombra. Gli stili sotto specificano anche una larghezza e un riempimento.
form.webPoll background: #ededed; comportamento: url (PIE.php); border: 1px solid #bebebe; -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; -moz-box-shadow: # 666 0 2px 3px; -webkit-box-shadow: # 666 0 2px 3px; box-shadow: # 666 0 2px 3px; margine: 10px 0 10px 8px; padding: 6px; position: relative; larghezza: 246px;
La linea chiave qui è l'attributo del comportamento. Questo verrà ignorato dai browser non IE e aggiungerà la funzionalità CSS3 a IE6-8.
Ancora brutto, ma un miglioramento notevole.
Successivamente, creeremo un bel riquadro attorno alle risposte e useremo un po 'di illusione per far apparire il bordo di un pixel. Questo viene fatto colorando il bordo più esterno (il fieldset) dello stesso colore dell'interno, e quindi usando il tag lista non ordinata come nostro vero bordo. Ecco il CSS:
form.webPoll fieldset background: #FCFAFC; comportamento: url (PIE.php); border: 1px solid #FCFAFC; -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; margin: 0; padding: 0; position: relative; form.webPoll ul behavior: url (PIE.php); border: 2px #bebebe solid; -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; font-family: Verdana; font-size: 10px; list-style-type: none; margin: 0; imbottitura: 10px 0; position: relative;
Quindi dobbiamo aggiungere un po 'di CSS per migliorare le nostre opzioni.
form.webPoll li margin: 0 16px; overflow: auto; imbottitura: 4px 0 6px; posizione: relativa; form.webPoll input position: absolute; top: 4px; * in alto: 0; a sinistra: 0; margine: 0; padding: 0; label.poll_active float: right; width: 90%;
Potresti chiedere perché stiamo usando il posizionamento assoluto sugli input e l'etichetta mobile. La ragione è semplice: risposte su più righe. Se una risposta alla tua domanda di sondaggio è lunga, vuoi che il pulsante di opzione assomigli a un proiettile su una lista non ordinata: sospeso. Ciò manterrà il testo da avvolgere attorno ad esso se si tratta di più righe.
C'è anche uno stile di targeting per IE specificamente con * hack per far sì che i pulsanti si allineino correttamente in IE6-8.
Abbiamo anche bisogno di modificare la barra usata per mostrare i risultati. Lo aggiungeremo ora:
form.webPoll .result background: # d81b21; background: -webkit-gradient (lineare, in alto a sinistra, in basso a sinistra, da (# ff8080), a (# aa1317)); sfondo: -moz-linear-gradient (in alto, # ff8080, # aa1317); -pie-background: linear-gradient (# ff8080, # aa1317); bordo: 1px rosso solido; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; clear: both; colore: #EFEFEF; padding-left: 2px; comportamento: url ('PIE.php');
C'è un altro nuovo attributo qui: -pie-background, che ci permette, in congiunzione con la libreria PIE, di usare sfondi sfumati in IE. Ci sono ancora alcuni tocchi da aggiungere.
Un H4 predefinito potrebbe non essere quello che stai cercando, quindi aggiungiamo un po 'di stile.
form.webPoll h4 color: # 444; famiglia di font: Georgia, serif; font-size: 19px; font-weight: 400; line-height: 1.4em; margine: 6px 4px 12px; padding: 0;
E io non sono un grande fan dei pulsanti predefiniti, quindi useremo uno sprite CSS per animarlo un po '.
.buttons margin: 8px 0 1px; padding: 0; text-align: right; larghezza: 122px; .vote background: url (res / vote.png) ripeti scorrimento 0 0 trasparente; confine: medio nessuno; altezza: 40px; text-trattino: -9999em; larghezza: 122px; .vote: hover background-position: 0 -41px; cursor: pointer;
Che mi dici di IE6? Non supporta la psudo-classe hover! Possiamo lasciare quegli utenti fuori al freddo (vedranno ancora lo stato predefinito del pulsante) o possiamo usare un'altra deliziosa libreria con licenza GPL, Qualunque cosa: hover.
Per ovviare a qualche stranezza di IE6, alcuni elementi devono far scattare qualcosa chiamato "HasLayout". Il modo più semplice per farlo è impostare una proprietà di zoom per questi elementi. La proprietà viene ignorata dai browser non IE.
form.webPoll ul, li / * // Rendi felice IE6 // * / zoom: 1;
Noterai anche che ci sono dei confini tra ogni domanda. Questo è stato fatto con una classe aggiuntiva sui tag LI che specificano un bordo. La classe verrà assegnata a tutti tranne l'ultimo elemento dallo script PHP.
Il file CSS completato è contenuto nel download.
Ora è il momento di creare il PHP per generare sondaggi, mostrare risultati e gestire i voti. Mi piacerebbe continuare a utilizzare lo script nel modo più semplice possibile, quindi sto pianificando l'utilizzo in anticipo. Per creare un sondaggio in una particolare posizione in una pagina, devi solo utilizzare il seguente PHP:
$ a = new webPoll (array ('Quali argomenti ti piacerebbe saperne di più?', 'HTML e CSS', 'JavaScript', 'JS Frameworks (jQuery, ecc.)', 'Ruby / Ruby on Rails', ' PHP ',' mySQL '));
Questo è tutto. Passerai un array al costruttore che contiene la domanda seguita dalle risposte. Per tenere traccia delle domande nel database, creeremo un hash MD5 della domanda da utilizzare come identificativo.
Ci sono alcuni dati che saranno necessari per ogni sondaggio; ne conserveremo alcune in proprietà di classe. Dovremo memorizzare la domanda e le risposte, l'HTML di base, l'identificativo della domanda e alcune informazioni su come disegnare le barre dei risultati. Ecco l'inizio:
class webPoll # rende alcune cose più leggibili in seguito const POLL = true; const VOTES = false; # numero di pixel per 1% sulle barre del display public $ scale = 2; # lo stesso sondaggio public $ question = "; public $ answers = array (); # HTML private $ header = '\ n "; private $ button = ''; # identificativo domanda privato $ md5 = ";
Le costanti iniziali saranno utilizzate in uno dei metodi per renderlo più leggibile, quindi è più facile sapere cosa sta succedendo.
Prendi nota dell'input nascosto che è stato aggiunto qui. Questo è l'identificativo della domanda utilizzato per memorizzare le informazioni nel database. Tutti i valori nel codice HTML circondati da segni di percentuale verranno sostituiti.
Dato che è già stato deciso che il sondaggio sarà realizzato creando un oggetto, esaminiamo il metodo __construct.
funzione pubblica __construct ($ params) $ this-> question = array_shift ($ params); $ this-> answers = $ params; $ this-> md5 = md5 ($ this-> question); $ this-> header = str_replace ('% src%', $ _SERVER ['SCRIPT_NAME'], $ this-> header); $ this-> header = str_replace ('% qid%', $ this-> md5, $ this-> header); $ this-> header = str_replace ('% question%', $ this-> question, $ this-> header); # l'utente ha ancora votato? isset ($ _ COOKIE [$ this-> md5])? $ this-> poll (self :: VOTES): $ this-> poll (self :: POLL);
Nella prima riga, separiamo la domanda dallo stack di array con array_shift e la memorizziamo in una proprietà. Conserviamo anche le domande, lasciandole come una matrice. Creiamo anche qui l'identificativo della domanda, creando un hash MD5 della domanda stessa.
Le prossime tre linee eseguono alcune sostituzioni sull'HTML. Il primo imposta la nostra azione modulo per puntare alla pagina che il sondaggio è uno. Il secondo mette il nostro identificatore di domanda in un campo modulo nascosto. Il terzo pone la nostra domanda nell'HTML.
Nella riga finale del costruttore controlliamo se l'utente ha votato questo particolare sondaggio, e se lo ha, mostriamo i voti. Se non lo ha, mostriamo il sondaggio.
Sia la generazione del sondaggio che la generazione dei risultati sono operazioni molto simili. Per mantenere il nostro codice ASCIUTTO, suddividiamo la creazione in tre metodi. Il principale è "sondaggio".
sondaggio di funzione privata ($ show_poll) $ replace = $ show_poll? $ this-> button: "; $ this-> footer = str_replace ('% button%', $ replace, $ this-> footer); # la funzione statica non ha accesso alla variabile di istanza se (! $ show_poll) $ results = webPoll :: getData ($ this-> md5); $ voti = array_sum ($ results); for ($ x = 0; $ xrisposte); $ x ++) $ this-> center. = $ show_poll? $ this-> pollLine ($ x): $ this-> voteLine ($ this-> risposte [$ x], $ risultati [$ x], $ voti); echo $ this-> header, $ this-> center, $ this-> footer;
Ecco la ripartizione di ciò che sta succedendo in questa funzione:
righe 2 e 3: Abbiamo solo bisogno di un pulsante di voto se l'utente non ha votato. Qui determiniamo se utilizzeremo il pulsante HTML o meno, quindi inseriremo l'HTML o sostituiremo il% button% placeholder con una stringa vuota.
righe 6 - 8: Se non stiamo mostrando il sondaggio, ovviamente abbiamo bisogno dei risultati, quindi qui andiamo a prenderli. Calcoliamo anche i voti totali espressi per utilizzarli in seguito nella determinazione delle percentuali.
righe 11 - 12: Questo genera i tag LI nel nostro HTML. A seconda se stiamo mostrando il sondaggio o i risultati, generiamo HTML diversi. Questa generazione di HTML è passata a due funzioni:
riga 15: Semplicemente scarica i dati nella pagina.
Questo è un metodo molto semplice, che prende come argomento l'indice corrente della risposta.
funzione privata pollLine ($ x) isset ($ this-> risponde [$ x + 1])? $ class = 'bordered': $ class = "; return"
Controlla se c'è una risposta dopo quella corrente sulla sua prima riga, e se c'è, applica una classe di confine con quel tag LI. L'ultima risposta non otterrà questa classe, permettendoci di raggiungere l'effetto visivo desiderato.
Questo metodo sta ottenendo 3 parametri passati:
Con queste informazioni, è possibile produrre i tag LI per i risultati delle votazioni.
funzione privata voteLine ($ answer, $ result, $ votes) $ result = isset ($ result)? $ risultato: 0; $ percent = round (($ result / $ voti) * 100); $ width = $ percent * $ this-> scale; ritorno "
Poiché è possibile che non ci siano voti per un'opzione, lascerà effettivamente $ result unset. Se rileviamo questo gli daremo un valore predefinito di 0 voti.
Successivamente, determiniamo quale percentuale dei voti l'opzione ha e, infine, utilizziamo la proprietà della scala per determinare la larghezza, in pixel, che dovrebbe essere la barra dei risultati. Quindi alla fine restituiamo l'HTML che contiene tutte queste informazioni.
Se si guarda indietro un po ', vedremo che chiamiamo il metodo getData () che è definito come un metodo statico nella classe. Perché statico? Perché se decidessimo di migliorare questo sondaggio in seguito, rendendolo basato su AJAX, vorremmo accedere a quel metodo senza creare oggetti. Ecco il metodo:
funzione statica getData ($ question_id) prova $ dbh = nuovo PDO ('sqlite: voting.db'); $ dbh-> setAttribute (PDO :: ATTR_ERRMODE, PDO :: ERRMODE_EXCEPTION); $ STH = $ dbh-> prepare ('SELECT AID, voti FROM tally WHERE QID =?'); $ Sth-> execute (array ($ question_id)); catch (PDOException $ e) # Errore nel recupero dei dati, basta inviare un set di dati vuoto array di risposta (0); while ($ row = $ STH-> fetch ()) $ results [$ row ['AID']] = $ row ['votes']; restituire $ risultati;
L'ID della domanda viene passato al metodo e restituirà un array contenente l'ID della risposta e il numero di voti che la risposta ha. Se una risposta non ha voti, non avrà una voce nell'array, che abbiamo già trattato nel metodo voteLine ().
Poiché gli errori di database nei sondaggi Web sono particolarmente tragici, stiamo semplicemente restituendo un array vuoto se si verifica uno. L'utente otterrà 0 voti per ogni risultato. In un ambiente di produzione potresti voler registrare questo errore in un file o inviare all'amministratore un'email.
Aggiungeremo un secondo metodo statico alla classe e questo gestirà i voti in entrata. I voti verranno conteggiati solo se l'utente non ha votato prima (come determinato da un cookie) e una volta che l'utente ha votato, imposteremo un cookie che indica questo.
In questo tipo di applicazione Web, è quasi impossibile interrompere più voti senza escludere alcuni utenti legittimi. L'impostazione di un cookie è solo una precauzione di base.
Questo è uno dei metodi più complessi nella nostra classe webPoll e lo esamineremo in tre parti.
funzione statica vote () if (! isset ($ _ POST ['QID']) ||! isset ($ _ POST ['AID']) || isset ($ _ COOKIE [$ _ POST ['QID']])) ritorno;
Una chiamata al metodo vote () sarà nella parte superiore della nostra pagina PHP, quindi la prima cosa che vogliamo fare è decidere se c'è un voto da elaborare o meno. L'affermazione sopra è come la determiniamo. Ecco cosa dice:
Se qualcuno di questi è vero, non dobbiamo elaborare un voto e lasciamo il metodo.
$ dbh = nuovo PDO ('sqlite: voting.db'); $ dbh-> setAttribute (PDO :: ATTR_ERRMODE, PDO :: ERRMODE_EXCEPTION); prova $ sth = $ dbh-> prepare ("INSERIRE valori di conteggio (QID, AID, voti) (: QID,: AID, 1)"); $ Sth-> execute (array ($ _ POST [ 'QID'], $ _ POST [ 'AID'])); catch (PDOException $ e) codice di errore # 23000 significa che la chiave esiste già, quindi AGGIORNA! if ($ e-> getCode () == 23000) try $ sth = $ dbh-> prepare ("UPDATE tally SET voti = voti + 1 WHERE QID =: QID AND AID =: AID"); $ Sth-> execute (array ($ _ POST [ 'QID'], $ _ POST [ 'AID'])); catch (PDOException $ e) $ this-> db_error ($ e-> getMessage ()); else $ this-> db_error ($ e-> getMessage ());
Questo sembra molto più complicato di quanto lo sia davvero. Quello che succede qui è controllare se una determinata risposta ha ottenuto un voto prima. Se non lo è, creiamo un nuovo record per quella risposta e diamo un voto. Se è così, aggiorniamo il record esistente. Quindi, come decide cosa fare?
Magia delle eccezioni DOP.
Ricorda che all'inizio abbiamo creato la nostra chiave primaria a più colonne? Quando proviamo a inserire un record nella tabella che corrisponde a una coppia QID / AID esistente, viene generata un'eccezione e in particolare il codice di eccezione è 23000 (chiave duplicata).
Se l'inserto genera un'eccezione, controlleremo il codice di eccezione e, se corrisponde a 23000, tenteremo invece di aggiornare il record. Naturalmente se l'inserimento fallisce per un motivo diverso, o anche l'aggiornamento fallisce, inviamo semplicemente una chiamata a un metodo chiamato db_error () che fa solo eco a un messaggio di errore generico. Come prima, un ambiente di produzione registra questo errore e / o notifica l'amministratore.
Infine, la fine del metodo:
# entry in $ _COOKIE per significare che l'utente ha votato, se ha if ($ sth-> rowCount () == 1) setcookie ($ _ POST ['QID'], 1, time () + 60 * 60 * 24 * 365); $ _COOKIE [$ _ POST ['QID']] = 1;
Usando rowCount () possiamo verificare che abbiamo aggiornato o inserito un voto. Se un voto è stato registrato con successo, impostiamo un cookie che lo indichi, utilizzando l'identificativo della domanda come nome del cookie.
Oltre ad impostare il cookie, popoliamo il super-global $ _COOKIE, quindi quando il sondaggio viene visualizzato, mostra le risposte piuttosto che presentare nuovamente il sondaggio.
Abbiamo scritto il PHP, configurato CSS e HTML, ora è il momento di mettere tutto in uso. In questo esempio, inseriremo tutto in una pagina altrimenti vuota. Nella parte superiore della pagina, inserisci quanto segue:
È importante che questa sia la parte superiore della pagina, prima di qualsiasi HTML. Perché? Perché se c'è un voto da elaborare, un cookie può essere scritto e non è possibile scrivere i cookie dopo che è stato inviato qualcos'altro. La chiamata al metodo statico vote () restituisce se non ci sono i dati POST corretti da elaborare.
Successivamente, includeremo tutti gli stili che abbiamo scritto come foglio di stile separato. Inoltre, includeremo uno stile particolare solo per IE che è stato menzionato in precedenza per abilitare il: hover psudo-class.
Nel BODY della tua pagina HTML, ti inserirai nel seguente PHP per inserire i sondaggi:
$ a = new webPoll (array ('Quali argomenti ti piacerebbe saperne di più?', 'HTML e CSS', 'JavaScript', 'JS Frameworks (jQuery, ecc.)', 'Ruby / Ruby on Rails', ' PHP ',' mySQL ')); $ b = new webPoll (array ('Qual è la tua domanda?', 'Don' t have one ',' Why? ',' When? ',' Where? '));
Questo è tutto! Grazie per aver letto. Qualsiasi pensiero, domanda o suggerimento?