Crearea unui sondaj Web cu PHP

Sondajele sunt aproape omniprezente pe web astăzi și există o mulțime de servicii care vă vor oferi un sondaj de opinie. Dar dacă vrei să-ți scrii unul singur? Acest tutorial vă va ajuta să parcurgeți pașii pentru a crea un simplu sondaj bazat pe PHP, inclusiv configurarea bazei de date, procesarea voturilor și afișarea sondajului.


Pasul 1: Planificați și creați baza de date

Pentru a stoca rezultatele sondajului, vom stoca trei informații:

  • Un identificator de întrebare
  • Un identificator de răspuns
  • Numărul de voturi obținut de o pereche de întrebări / răspunsuri

Pentru acest tutorial, vom folosi PDO și SQLite. Dacă lucrați cu SQLite3, puteți crea o nouă bază de date prin intermediul instrumentului de linie de comandă; dacă utilizați o versiune mai veche, un script PHP rapid va face truc. Iată cea folosită pentru acest tutorial:

setAttribute (DOP :: ATTR_ERRMODE, DOP :: ERRMODE_EXCEPTION); $ dbh-> exec ('CREATE TABLE match (QID varchar (32) NOT NULL, AID integer NOT NULL, voturi întreg NU NULL, KEY PRIMARY (QID, AID)));  captură (PDOException $ e) echo "EROARE !!: $ e"; Ieșire;  echo "db a fost creat cu succes."; ?>

Acest script simplu va crea o bază de date SQLite în directorul pe care îl rulați. Spre deosebire de MySQL, baza de date aici este un fișier plat. Dacă sunteți familiarizat cu SQL, crea ar trebui să aibă sens pentru dvs., deși ultima linie poate fi nouă pentru unii oameni:

TASTĂ PRIMARĂ (QID, AID)

Aceasta creează o cheia compozită pentru baza de date. Intrările în oricare dintre coloane nu trebuie să fie unice pentru coloana respectivă, dar combinația celor două trebuie să fie unică.


Pasul 2: Designul HTML al sondajului

Înainte de a începe să scrieți orice PHP, trebuie să decideți cum să vă creați sondajul în ceea ce privește marcarea. Vom încerca să păstrăm marcajul cât mai semantic și mai simplu posibil. Sondajul dvs. va avea două aspecte:

  • Întrebare care așteaptă să fie răspuns
  • Rezultatele actuale ale sondajului

În scris acest HTML, unele clase vor fi incluse pentru a ajuta cu CSS mai târziu.

Vizualizare sondaj

Deoarece un sondaj este în primul rând o listă de răspunsuri, vom include o listă neordonată pentru a conține aceste răspunsuri. Pentru întrebarea însăși, vom folosi o etichetă de titlu.

Ce întrebare ați dori să întrebați?

  • Răspundeți aici
  • Un alt raspuns aici

Este destul de simplu, dar nu include elemente de formă. Butoanele radio sunt cele mai potrivite, deoarece permitem doar un răspuns pentru fiecare sondaj. De asemenea, vom folosi eticheta de etichetă pentru a asocia răspunsurile cu butonul radio corespunzător. Acum formularul nostru HTML arata mai degraba asa:

Ce întrebare ați dori să întrebați?

E ceva mai complex, dar nu prea rău. Încă ceva mai mult de adăugat. Vom include o etichetă cu set de câmpuri pentru a deschide câteva opțiuni de stil și, bineînțeles, avem nevoie de un buton de trimitere!

Ce întrebare ați dori să întrebați?

Pentru fiecare răspuns, se adaugă o nouă etichetă LI, iar valoarea butonului radio crește. Acest lucru se va face în cele din urmă prin PHP. HTML-ul suplimentar este eticheta setului de câmp și paragraful este înfășurat în jurul butonului - ambele vor fi utilizate de CSS-ul nostru.

Răspundeți la Vizualizare

Codul HTML va fi aproape identic pentru vizualizarea răspunsului. Elementele de element de linie nu vor conține un element de formular și vom adăuga un div care poate fi folosit pentru a arăta procentajul de voturi care au primit răspunsul. Iată cum va arăta asta:

  • Da, acesta este un stil inline pe care îl vezi acolo. Acest stil va fi generat de PHP bazându-ne pe procentul actual al fiecărui răspuns individual. Iata ce avem pana acum:


    Pasul 3: Stilul Formularului

    HTML-ul pe care l-am creat în ultimul pas nu a fost foarte atractiv. Să vedem dacă putem rezolva asta puțin. Vom folosi minunata bibliotecă CSS3 PIE (progresiv Internet Explorer), astfel încât să putem obține un aspect similar în toate browserele. Pentru a face această bibliotecă să funcționeze corect, există numeroase cazuri în care trebuie să aplicați o poziție relativă elementelor. Puteți citi toate detaliile de pe site-ul bibliotecii.

    Stilul etichetei de formular

    Vom folosi eticheta de formular ca container. Va avea colțuri frumoase, rotunjite și un pic de umbră. Stilurile de mai jos specifică și o lățime și o umplutură.

    form.webPoll background: #ededed; comportament: url (PIE.php); frontieră: 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; Poziția: relativă; lățime: 246px; 

    Linia cheie aici este atributul de comportament. Acest lucru va fi ignorat de browserele non-IE și va adăuga funcționalitatea CSS3 la IE6-8.

    Încă urât, dar o îmbunătățire notabilă.

    Trimiteți răspunsurile

    Apoi, vom crea o cutie drăguță în jurul răspunsurilor și vom folosi un pic de iluzie pentru a face frontiera să arate cu un pixel. Aceasta se realizează prin colorarea celei mai exterioare frontiere (setul de câmpuri) la aceeași culoare cu interiorul și apoi prin utilizarea etichetei neordonate ca frontieră reală. Iată CSS:

    form.webPolful câmpului background: #FCFAFC; comportament: url (PIE.php); frontieră: 1px solid #FCFAFC; -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; margin: 0; padding: 0; Poziția: relativă;  form.webPoll ul comportament: 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; padding: 10px 0; Poziția: relativă; 

    Stilul răspunsurilor

    Apoi trebuie să adăugăm un mic CSS pentru a face opțiunile să arate mai bine.

    form.webPoll li margine: 0 16px; overflow: auto; umplutura: 4px 0 6px; poziție: relativă;  form.webImpul de intrare position: absolute; top: 4px; * sus: 0; stânga: 0; marja: 0; padding: 0;  label.poll_active float: right; lățime: 90%; 

    S-ar putea să întrebați de ce folosim poziția absolută pe intrări și plutiți eticheta. Motivul este simplu: răspunsuri multi-linie. Dacă răspunsul la întrebarea dvs. de sondaj este lung, doriți ca butonul radio să arate ca un glonț pe o listă neordonată - agățată. Acest lucru va păstra textul înfășurat în jurul acestuia dacă este mai multe linii.

    Există, de asemenea, un stil care vizează IE specific cu * hack pentru a determina butoanele să se alinieze corect în IE6-8.

    De asemenea, trebuie să stilim bara utilizată pentru a afișa rezultatele. Vom adăuga acum:

    form.webPoll .result background: # d81b21; fundal: -webkit-gradient (liniar, partea stângă sus, partea stângă jos, de la (# ff8080), la (# aa1317)); fundal: -moz-linear-gradient (sus, # ff8080, # aa1317); - fundal-fundal: gradient linear (# ff8080, # aa1317); margine: 1 pix solid roșu; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; clar: ambele; Culoare: #efefef; padding-left: 2px; comportament: url ("PIE.php"); 

    Există un alt atribut nou aici: -pie-background, care ne permite, împreună cu biblioteca PIE, să folosim fundaluri gradient în IE. Mai există încă câteva detalii pe care să le adăugați.

    Întrebare și buton

    Este posibil ca un H4 implicit să nu fie ceea ce căutați, deci să adăugăm un stil pentru asta.

    form.webPoll h4 culoare: # 444; font-familie: Georgia, serif; font-size: 19px; font-weight: 400; line-height: 1.4em; margine: 6px 4px 12px; padding: 0; 

    Și nu sunt un mare fan al butoanelor implicite, așa că vom folosi un sprite CSS pentru a-l livra puțin.

    .butoane margin: 8px 0 1px; padding: 0; text-align: dreapta; lățime: 122px;  .vote background: url (res / vote.png) repetați defilați 0 0 transparent; frontieră: nici una mijlocie; înălțime: 40px; text-liniuță: -9999em; lățime: 122px;  .vote: hover background-position: 0 -41px; cursor: pointer; 

    Cum rămâne cu IE6? Nu suportă clasa psihologică a hover! Putem lăsa fie acei utilizatori în frig (ei vor vedea încă starea implicită a butonului), fie putem folosi o altă bibliotecă licențiată GPL, oricare ar fi: hover.

    Ultimele biți

    Pentru a acomoda unele quirks IE6, anumite elemente trebuie să aibă ceva numit "HasLayout" declanșat. Cel mai simplu mod de a face acest lucru este să setați o proprietate de zoom pentru aceste elemente. Proprietatea este ignorată de browserele non-IE.

    form.webPoll ul, li / * // Face IE6 fericit // * / zoom: 1; 

    De asemenea, veți observa că între fiecare întrebare există granițe. Acest lucru a fost făcut cu o clasă suplimentară pe etichetele LI care specifică o margine. Clasa va fi atribuită tuturor, cu excepția ultimului element, de scriptul PHP.

    Fișierul CSS completat este conținut în descărcare.


    Pasul 4: Creați o clasă PHP - Decideți pe interfață

    Acum este momentul să creați PHP pentru a genera sondaje, a arăta rezultatele și a gestiona voturile. Aș dori să continuăm să folosim scenariul cât mai simplu posibil, deci intenționez să îl folosesc înainte de timp. Pentru a crea un sondaj într-un anumit loc dintr-o pagină, veți folosi următorul PHP:

    $ a = un nou webPoll (array ("Ce subiecte doriți să aflați mai multe despre?", "HTML & CSS", "JavaScript", "JS Frameworks (jQuery etc) PHP ',' mySQL '));

    Asta e. Veți trece un constructor care conține întrebarea urmată de răspunsuri. Pentru a urmări întrebările din baza de date, vom crea un hash al MD5 al întrebării care va fi utilizat ca identificator.


    Pasul 5: Decideți asupra proprietăților clasei

    Există anumite date care vor fi necesare fiecărui sondaj; vom stoca câteva dintre acestea în proprietățile clasei. Va trebui să stocăm întrebarea și răspunsurile, codul de bază HTML, identificatorul întrebării și câteva informații despre cum să desenezi barele de rezultate. Iată începutul:

    clasa webPoll # face unele lucruri mai ușor de citit mai târziu const POLL = true; const VOTES = false; # numărul de pixeli pentru 1% pe barele de afișare public scale $ = 2; # sondajul public public $ question = "; public $ answer = array (); # HTML private $ header = '

    %întrebare%

      „; privat $ center = "; privat $ footer =" \ n
    % Butonul% \ n
    \ n "; privat $ button = '

    „; # identificator de întrebare privat $ md5 = ";

    Constantele inițiale vor fi folosite într-una din metode pentru ao face mai ușor de citit, astfel încât să fie mai ușor să știi ce se întâmplă.

    Luați notă de intrarea ascunsă adăugată aici. Acesta este identificatorul de întrebare utilizat pentru stocarea informațiilor în baza de date. Toate valorile din HTML înconjurate de semne procentuale vor fi înlocuite.


    Pasul 6: Creați sondaj HTML sau răspunsuri

    Deoarece a fost deja decis că sondajul va fi realizat prin crearea unui obiect, să examinăm metoda __construct.

    funcția publică __construct ($ params) $ this-> question = array_shift ($ params); $ this-> answers = $ params; $ this-> md5 = md5 ($ aceasta-> întrebare); $ 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); # a votat utilizatorul încă? esteset ($ _ COOKIE [$ this-> md5])? $ this-> poll (auto :: VOTĂ): $ this-> poll (self :: POLL); 

    În prima linie, coajăm întrebarea de pe stivă de array cu array_shift și stocăm-o într-o proprietate. De asemenea, stocăm întrebările, lăsându-le ca o matrice. De asemenea, creăm identificatorul de întrebări aici, făcând un hash de md5 al întrebării în sine.

    Următoarele trei linii efectuează unele înlocuiri pe HTML. Primul face acțiunea formularului nostru pentru a indica pagina pe care o face sondajul. Cel de-al doilea pune identificatorul întrebării noastre într-un câmp de formă ascunsă. Al treilea pune întrebarea noastră în HTML.

    În linia finală a constructorului verificăm dacă utilizatorul a votat acest sondaj special și, dacă el are, vom arăta voturile. Dacă nu, arătăm sondajul.


    Pasul 7: Generați sondajul

    Atât generarea sondajului cât și generarea rezultatelor sunt operații foarte asemănătoare. Pentru a ne păstra codul DRY, rupem creația în trei metode. Principalul este "sondajul".

    funcția privată ($ show_poll) $ replace = $ show_poll? $ this->: "$ this-> footer = str_replace ('% button%', $ replace, $ this-> footer); funcția statică nu are acces la variabila instanță dacă (! $ show_poll) $ results = webPoll :: getData ($ this-> md5); $ voturi = array_sum ($ rezultate); pentru ($ x = 0; $ xrăspunsuri); $ x + +) $ this-> center = = $ show_poll? $ this-> pollLine ($ x): $ this-> voteLine ($ acest-> răspunsuri [$ x], $ results [$ x], $ votes);  echo $ this-> header, $ this-> center, $ this-> footer; 

    Iată defalcarea a ceea ce se întâmplă în această funcție:

    linii 2 și 3: Avem nevoie doar de un buton de vot dacă utilizatorul nu a votat. Aici vom determina dacă vom folosi butonul HTML sau nu și apoi inserați codul HTML sau înlocuiți substituentul cu butonul% cu un șir gol.

    liniile 6 - 8: Dacă nu arătăm sondajul, avem evident nevoie de rezultate, deci iată-i să-i luăm. De asemenea, calculăm numărul total de voturi exprimate pentru a fi utilizate ulterior pentru a determina procentele.

    linii 11-12: Aceasta generează etichetele LI în HTML. În funcție de afișarea sondajului sau a rezultatelor, generăm HTML diferite. Această generație HTML este transferată în două funcții:

    • pollLine
    • voteLine

    linia 15: Pur și simplu elimină datele pe pagină.


    Pasul 8: Metoda pollLine ()

    Aceasta este o metodă foarte simplă, care ia indicele curent al răspunsului ca argument.

    funcția privată pollLine ($ x) isset ($ this-> answers [$ x + 1])? $ class = 'margine': $ class = "; return" 
  • ";

    Verifică dacă există un răspuns după cel curent pe prima sa linie și dacă există, aplică o clasă de etichetă LI mărginită. Ultimul răspuns nu va primi această clasă, permițându-ne să realizăm efectul vizual dorit.


    Pasul 9: Metoda voteLine ()

    Această metodă obține 3 parametri trecuți în ea:

    • $ answer: răspunsul la întrebare pentru această linie
    • $ result: Numărul de voturi obținut de această opțiune
    • $ voturi: Numărul total de voturi exprimate în acest sondaj

    Cu aceste informații, pot fi produse etichetele LI pentru rezultatele votării.

    funcția privată de votLine ($ answer, $ result, $ votes) $ rezultat = isset ($ rezultat)? $ rezultat: 0; $ procent = rotund (($ rezultat / $ voturi) * 100); $ width = $% * $ this-> scale; întoarcere " 
  • $ Procente%
  • ";

    Din moment ce este posibil să nu existe voturi pentru o opțiune, aceasta va lăsa în mod efectiv rezultatul $ unset. Dacă detectăm acest lucru, îi vom da o valoare implicită de 0 voturi.

    Apoi, vom determina ce procent din voturi a obținut opțiunea și, în sfârșit, vom folosi proprietatea scalei pentru a determina lățimea, în pixeli, că bara de rezultate ar trebui să fie. Apoi vom returna în cele din urmă HTML conținând toate aceste informații.


    Pasul 10: Scrieți metoda getData ()

    Dacă te uiți înapoi puțin, vei vedea că numim metoda getData () care este definită ca o metodă statică în clasă. De ce static? Pentru că dacă decidem să îmbunătățim mai târziu acest sondaj, făcându-l bazat pe AJAX, vom dori accesul la această metodă fără crearea de obiecte. Iată metoda:

    funcția statică getData ($ question_id) try $ dbh = nou DOP ('sqlite: vote.db'); $ dbh-> setAttribute (DOP :: ATTR_ERRMODE, DOP :: ERRMODE_EXCEPTION); $ STH = $ dbh-> prepare ('SELECT AID, votează FROM WHERE QID =?'); $ STH-> execute (array ($ question_id));  captură (PDOException $ e) # Eroare la obținerea datelor, trimiteți pur și simplu setul de date returnat (0);  în timp ce ($ row = $ STH-> fetch ()) $ rezultate [$ row ['AID']] = $ rând ['voturi'];  returnează rezultatele $; 

    Codul de întrebare este transmis în metodă și va returna un tablou care conține ID-ul răspunsului și numărul de voturi care au răspuns. Dacă un răspuns nu are voturi, acesta nu va avea o intrare în matrice, pe care am tratat-o ​​deja în metoda voteLine ().

    Deoarece erorile bazei de date din sondajele web sunt deosebit de tragice, vom reveni pur și simplu la o matrice goală dacă se întâmplă una. Utilizatorul va primi 0 voturi pentru fiecare rezultat. Într-un mediu de producție, este posibil să doriți să înregistrați această eroare într-un fișier sau să trimiteți un e-mail administratorului.


    Pasul 11: Efectuarea unei votări

    Vom adăuga o a doua metodă statică la clasă, iar aceasta va rezolva voturile primite. Voturile vor fi luate în considerare doar dacă utilizatorul nu a votat înainte (așa cum a fost determinat de un cookie) și odată ce utilizatorul a votat vom seta un cookie indicând acest lucru.

    În acest tip de aplicație web, este aproape imposibil să opriți voturile multiple fără a exclude niște utilizatori legitimi. Setarea unui cookie este doar o măsură de precauție de bază.

    Aceasta este una dintre metodele mai complexe din clasa noastră webPoll și vom examina acest lucru în trei părți.

    ($ _ POST ['AID']) || isset ($ _ COOKIE [$ _ POST ['QID']]))  întoarcere; 

    O metodă de apel la vot () va fi în partea de sus a paginii noastre de PHP, deci primul lucru pe care vrem să-l facem este să decideți dacă există un vot de procesat sau nu. Declarația de mai sus este modul în care determinăm acest lucru. Iată ce spune:

    • Dacă nu există identificator de întrebări în datele noastre POST (SAU !!)
    • Dacă nu există Identificator de răspuns în datele POST (OR !!)
    • Dacă a fost setat un modul cookie care deja corespunde Identificatorului de Întrebări

    Dacă oricare dintre acestea este adevărat, nu trebuie să procesăm un vot și lăsăm această metodă.

    $ dbh = nou DOP ('sqlite: vote.db'); $ dbh-> setAttribute (DOP :: ATTR_ERRMODE, DOP :: ERRMODE_EXCEPTION); încercați $ sth = $ dbh-> prepare ("INSERT INTO tally (QID, AID, voturi) valori (: QID,: AID, 1)"); $ Sth-> execute (array ($ _POST [ 'QID'], $ _POST [ 'AID']));  captură (PDOException $ e) cod de eroare # 23000 înseamnă că cheia există deja, deci UPDATE! dacă $ e-> getCode () == 23000) încercați $ sth = $ dbh-> prepare ("UPDATE tally SET vot = vot + 1 WHERE QID =: QID AND AID =: AID"); $ Sth-> execute (array ($ _POST [ 'QID'], $ _POST [ 'AID']));  captură (PDOException $ e) $ this-> db_error ($ e-> getMessage ());  altceva $ this-> db_error ($ e-> getMessage ()); 

    Acest lucru pare mult mai complicat atunci este într-adevăr. Ce se întâmplă aici este să verificăm dacă un anumit răspuns a obținut un vot înainte. Dacă nu am creat o înregistrare nouă pentru răspunsul respectiv și i-am da un vot. Dacă există, actualizăm înregistrarea existentă. Deci cum se hotărăște ce să facă?

    PDO magic excepție.

    Amintiți-vă de la început că am creat cheia primară multi-coloană? Atunci când încercăm să inserăm o înregistrare în tabel care corespunde unei perechi existente de QID / AID, se aruncă o excepție și, în special, codul de excepție este 23000 (cheia duplicat).

    Dacă inserția aruncă o excepție, vom verifica codul de excepție și dacă se potrivește cu 23000, vom încerca să actualizăm înregistrarea. Desigur, dacă insertul nu reușește din alt motiv sau dacă actualizarea eșuează, vom emite un apel la o metodă numită db_error () care echoiază un mesaj de eroare generic. Ca și înainte, un mediu de producție ar înregistra această eroare și / sau va notifica administratorul.

    În sfârșit, sfârșitul metodei:

     # entry in $ _COOKIE pentru a indica utilizatorul a votat, daca are daca ($ sth-> rowCount () == 1) setcookie ($ _ POST ['QID'], 1, timp () + 60 * 60 * 24 * 365); $ _COOKIE [$ _ POST ['QID']] = 1; 

    Folosind rowCount () putem verifica dacă am actualizat sau am introdus un vot. Dacă un vot a fost înregistrat cu succes, setăm un cookie indicând la fel de mult, folosind identificatorul întrebării drept numele cookie-ului.

    În plus față de setarea cookie-ului, vom popula $ _COOKIE super-global, astfel că atunci când sondajul se afișează, acesta afișează răspunsuri mai degrabă decât prezentând din nou sondajul.


    Pasul 12: pune totul în acțiune

    Am scris PHP, am creat CSS și HTML, acum este momentul să le folosim. În acest exemplu, vom renunța totul la o pagină care este altfel necompletată. În partea de sus a paginii, introduceți următoarele:

    Este important ca aceasta să fie chiar partea de sus a paginii, înainte de orice cod HTML. De ce? Deoarece dacă există un vot de procesat, un cookie poate fi scris și nu puteți scrie cookie-uri după ce ați trimis altceva. Apelul la votul metodei statice () se întoarce dacă nu sunt procesate datele POST corecte.

    Apoi, vom include toate stilurile pe care le-am scris ca o foaie de stiluri separate. De asemenea, vom include un anumit stil doar pentru IE care a fost menționat mai devreme pentru a permite: hover psudo-class.

     

    În BODY al paginii dvs. HTML, veți renunța la următorul PHP pentru a insera sondajele:

    $ a = un nou webPoll (array ("Ce subiecte doriți să aflați mai multe despre?", "HTML & CSS", "JavaScript", "JS Frameworks (jQuery etc) PHP ',' mySQL ')); $ b = nou webPoll (array ("Care este întrebarea dvs.", "Nu aveți unul", "De ce?", "Când?", "Unde?"));

    Asta e! Vă mulțumim pentru lectură. Orice gânduri, întrebări sau sugestii?

    Cod