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.
Pentru a stoca rezultatele sondajului, vom stoca trei informații:
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ă.
Î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:
În scris acest HTML, unele clase vor fi incluse pentru a ajuta cu CSS mai târziu.
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.
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:
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!
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.
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:
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.
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ă.
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ă;
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.
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.
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.
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.
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 = '\ 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.
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.
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:
linia 15: Pur și simplu elimină datele pe pagină.
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.
Această metodă obține 3 parametri trecuți în ea:
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 "
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.
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.
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ă 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.
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?