Cum de a codifica o listă fun-to-do cu PHP și AJAX

Pentru tutorialul săptămânal Tuts + Premium, vom lucra cu multe tehnologii diferite. În cele din urmă, vom construi o listă de sarcini care vă va permite, sau utilizatorul dvs., să creați, să actualizați și să ștergeți elementele în mod asincron. Pentru a ne îndeplini sarcina, vom folosi funcțiile AJAX ale lui PHP și jQuery. Cred că veți găsi că nu este atât de tare cum ați putea crede inițial. Îți arăt exact cum!

Acest tutorial include un screencast disponibil pentru membrii Tuts + Premium.



Pasul 1: Crearea unei noi baze de date

După cum vă puteți imagina, nu putem salva, șterge și actualiza înregistrările într-un mediu static. Deci, trebuie să creăm o bază de date MySql care să stocheze informațiile.

Dacă utilizați PHPMyAdmin, accesați panoul de control vizitând http: // localhost / phpmyadmin.


În caseta de text "Creați o nouă bază de date", tastați "db" și faceți clic pe "Creați". Apoi, va trebui să creați un tabel. Introduceți "todo" și "3" pentru "numărul de câmpuri".


Crearea coloanelor noastre

Acum trebuie să adăugăm coloanele corespunzătoare.

  • id : id unic pentru a identifica fiecare rând.
  • titlu : Titlul elementului nostru.
  • Descriere : O descriere care detaliază ce trebuie să facem!

Asigurați-vă că opțiunile fiecărui câmp se potrivesc cu cele afișate în imaginea următoare.


Introduceți rândurile de testare

Acum, că am creat baza noastră de date, să adăugăm rapid câteva rânduri de testare. Dați clic pe baza de date "db"; apoi alegeți "Răsfoiți". Veți fi adus la un ecran care listează conținutul fiecărui rând din baza dvs. de date. Evident, această secțiune este goală acum. Alegeți "Inserați" și adăugați câteva coloane. Introduceți ce doriți aici.




Full Screencast



Pasul 2: Clasa Db


Deși nu sunt solicitate prin nici un mijloc, consider că este mai ușor să-mi gestionez funcțiile atunci când le clasificăm într-o clasă. Având în vedere acest lucru, vom crea acum o clasă "Db" care va conține mai multe funcții.

  • __construi : Această funcție rulează automat de îndată ce obiectul este instanțiat.
  • delete_by_id () : Șterge rândul necesar introducând ID-ul unic al rândului.
  • update_by_id () : Actualizează rândul prin trecerea în id-ul său unic.

Deschideți editorul de cod de alegere și creați un nou fișier numit "db.php". În acest document gol, lipiți în următoarele rânduri de cod.

 clasa Db private $ mysql; funcția __construct () $ this-> mysql = nou mysqli ("localhost", "root", "yourPassword", "db") sau mor ("problemă");  // clasa de sfârșit

Pentru a crea o nouă clasă, folosim sintaxa demonstrată mai jos.

 clasa 'myClass' 

Folosind doar codul de mai sus, am creat cu succes o clasă nouă. Încă nu face nimic, dar este totuși o clasă!

__construi()

Metoda __construct () (vorbirea de clasă pentru "funcția") este cunoscută ca o "metodă magică". Acesta va rula imediat după ce o instanță a unei clase este instanțiată. Vom folosi această metodă pentru a face conexiunea noastră inițială la baza de date MySql.

 funcția __construct () $ this-> mysql = nou mysqli ("localhost", "root", "yourPassword", "db") sau mor ("problemă"); 

Dacă nu sunteți familiarizat cu OOP, poate fi ușor descurajator la început. Din fericire, nu este prea greu să înțelegi. Vrem ca conexiunea noastră mysql să fie disponibilă pentru toate metodele din clasa noastră. Având în vedere acest lucru, nu ar fi o idee bună să stocați variabila $ mysql într-o funcție specifică. În schimb, ar trebui să fie o proprietate de clasă.

 privat $ mysql;

Accesarea proprietăților din metode

Într-o metodă, nu putem accesa proprietatea prin tastarea "$ mysql". Trebuie să ne referim mai întâi la obiect.

 $ This-> mysql

Asigurați-vă că luați notă de faptul că, atunci când accesăm o proprietate, putem lăsa semnul dolarului.

mysqli


Este preferabil să folosiți metoda mysql improved (mysqli) mai degrabă decât metoda tradițională mysql_connect când vă conectați la o bază de date. Nu numai că este mai rapidă, dar ne permite, de asemenea, să folosim o abordare OOP.

Când creăm o nouă instanță a clasei mysqli, trebuie să trecem în patru parametri.

  • gazdă : 'gazdă locală'
  • nume de utilizator : rădăcină
  • parola : 'parola Dvs'
  • numele bazei de date : db

Ar trebui să o facă pentru moment. Vom reveni la clasa noastră în cursul acestui tutorial pentru a adăuga noi metode. Amintiți-vă, când creați o nouă instanță a acestei clase ...

 cereți "db.php"; $ db = nou Db ();

... deschidem automat o conexiune la baza noastră de date, grație metodei magice __construct ().

Marcajul


Acum, trebuie să creați marcajul nostru pentru pagina de pornire. Adăugați o nouă pagină la soluția dvs. și salvați-o ca "index.php". Apoi, lipiți în următoarele.

      Lista mea de rezolvat     

Lista mea de rezolvare

  • A face
...
...

Analiză

În capul documentului nostru, mă refer la CDN-ul Google pentru a accesa jQuery. Aceasta este cu ușurință metoda preferată atunci când se utilizează jQuery. Apoi, fac referire la un fișier "scripts.js" pe care îl vom crea ulterior în acest tutorial.

Să revedem rapid ce este pentru fiecare div.

  • recipient : Standard de împachetare div.
  • ul # file : Navigarea noastră. Vom folosi Javascript pentru a adăuga filele suplimentare. Voi explica de ce în curând.
  • principal : Wrap pentru conținutul principal.
  • a face : Tab 1.
  • addNewEntry : Tab 2

Pasul 4: CSS


Acesta nu este un tutorial CSS, per se. Aveți libertatea de a revizui foaia de stil pe care am folosit-o. Este în pachetul de descărcare. Dacă doriți o examinare mai profundă, vizionați ecranul de selecție.


Pasul 5: Preluarea înregistrărilor

Acum, că ne-am conectat la baza de date și am creat markup / CSS, să scriem un cod care va prelua rândurile bazei de date.

În cadrul "todo" div, introduceți următoarele.

 
mysql-> interogare (interogare $); dacă ($ results-> num_rows) în timp ce ($ row = $ results-> fetch_object ()) $ title = $ row-> title; $ description = $ row-> description; $ id = $ rând-> id; echo "
„; $ date = << $ Titlu

descriere $

D E
EOD; echo $ data; echo "
„; // termină în timp ce altceva echo "

Există elemente zero. Adăugați unul acum!

";>>

Analiză

  • Utilizați "cer" pentru a accesa clasa Db.
  • Creați o nouă instanță a clasei Db.
  • Creați o interogare. Aceasta va prelua toate înregistrările din tabelul "todo" și le va sorta într-o ordine ascendentă.
  • Acum trebuie să executăm interogarea noastră. $ DB> mysql-> interogare ($ query). $ db se referă la obiect. $ mysql se referă la clasa mysqli. $ query este o metodă a clasei mysqli care ne permite să trecem printr-o interogare. Aici, trecem prin șirul pe care tocmai l-am creat.
  • $ results-> num_rows va returna numărul total de rânduri retrimise din baza de date. Dacă unul sau mai multe sunt returnate, vom folosi apoi o declarație de timp pentru a trece prin rânduri.
  • Creați o variabilă temporară denumită $ row care se va referi la informații, pentru fiecare iterație. Apoi, creăm trei variabile care se referă la omologii lor din baza de date.
  • Fiecare element va fi înfășurat într-un div cu o clasă de "element".
  • Apoi, folosim heredocs pentru a formata elementul nostru de rezolvat. Heredocs permite o modalitate ușoară și organizată de a combina html și php. Pentru a afla mai multe, asigurați-vă că ați revedit acest ecran.
  • Înfășurați titlul în etichetele h4; descrierea în p tag-uri.
  • Utilizatorul are nevoie de o modalitate de a edita și șterge fiecare element. Deci, am creat două etichete de ancoră care ne vor permite să facem acest lucru. Vom reveni la asta mai târziu.
  • Răspundeți la info despre heredocs și închideți ".item" div.
  • Dacă au fost returnate rânduri de la zero din baza de date, ecoul "Există elemente zero. Adăugați unul acum!".

Sperăm că toate acestea au avut sens. În acest moment, ar trebui să aveți ceva de genul:


Pasul 6: Adăugați un element nou


De asemenea, dorim ca utilizatorul să aibă capacitatea de a insera noi înregistrări. Să creați un formular care să permită acest lucru.

 

Adăugați o intrare nouă

Acesta este formularul dvs. standard de tip "run-of-the-mill". Am adăugat intrări pentru titlu și descriere. Când se face clic pe butonul de trimitere, informațiile introduse vor fi postate în "addItem.php". Să creăm acea pagină acum.


Pasul 7: AddItem.php

Creați un document nou și salvați-l ca "addItem.php". Inserați în următorul cod:

 mysql-> prepare ($ interogare)) $ stmt-> bind_param ('ss', $ _POST ['title'], $ _POST ['descriere']); $ Stmt-> execute (); header ("locație: index.php");  altfel mori ($ db-> mysql-> error); 
  • Consultați clasa noastră db.
  • Instanțiați clasa.
  • Dacă există butonul de trimitere cu numele "addEntry", executați următorul cod.
  • Creați o interogare nouă. Veți observa că folosesc semnele de întrebare ca valori. Este metoda preferată de a folosi declarațiile pregătite atunci când actualizăm baza noastră de date. Este o modalitate excelentă de a vă proteja împotriva injecției de tip sql.
  • Pregătiți variabila mysql prin trecerea în interogarea pe care tocmai am creat-o.
  • Dacă a fost pregătit cu succes, legați parametrii corespunzători. Primul parametru solicită tipurile de date pentru fiecare element. Am folosit "s" pentru a se referi la "șir". Cei doi parametri captează valorile titlurilor și descrierilor din matricea superplă globală POST.
  • Executați declarația.
  • În cele din urmă, redirecționați utilizatorul înapoi la pagina de pornire.

Pasul 7: Actualizați elementele


Folosind capabilitățile AJAX ale jQuery, permiteți utilizatorului să actualizeze fiecare element fără postback. Creați un fișier nou într-un director "js", și numiți-l "scripts.js". Rețineți că am menționat deja acest fișier în marcajul nostru.

 $ (functie () $ ('. editEntry') click (function () var $ this = $ (this); var oldText = $ this.parent () ($) () () () () () () () () () () ).adăuga('„); $ ('newDescription'). blur (function () var newText = $ (this) .val (); $ .ajax (type: 'POST', url: 'updateEntry.php' '+ newText +' & id = '+ id, succes: functie (rezultate) $ this.parent () parent (). ); return false; ); );

Dacă veți reveni la marcajul nostru pe index.php, veți vedea:

 
D E

Decodarea fiecărei linii

 $ ('. editEntry') faceți clic pe (funcția () 

Folosind jQuery, trebuie să ascultăm când se face clic pe eticheta de ancorare cu o clasă de "editEntry".

 var $ this = $ (acest lucru);

Apoi, caching-ul $ (acest lucru) - care se referă la eticheta de ancorare la care a fost făcut clic.

 var oldText = $ this.parent () parent () găsiți ('p') text ();

Trebuie să stocăm descrierea originală. Spunem etichetei ancorei pentru a găsi div divorât și căuta eticheta p - care conține textul descrierii. Am apucat această valoare folosind "text ()".

 var id = $ this.parent () parinte () find ('# id') val ();

Pentru a actualiza rândul corect din baza noastră de date, trebuie să știu ce este acel id de rând specific. Dacă vă referiți din nou la codul dvs., veți vedea un câmp de intrare ascuns care conține această valoare.

 

Încă o dată, folosim "găsi" pentru a accesa această intrare ascunsă și apoi apucați valoarea acesteia.

 $ This.parent (). Părinte (). Găsește ( 'p'). Gol (). Append (“„);

Acum, trebuie să permitem utilizatorului să introducă o nouă descriere. De aceea au făcut clic pe "Editare intrare", nu-i așa !? Găsim eticheta descriere P, goliți-o și apoi adăugăm o textare. Utilizăm "empty ()" pentru a ne asigura că scapăm de tot textul; nu mai este nevoie. Valoarea acestei textarea va fi egală cu textul vechi - ca o comoditate.


 $ ('. newDescription'). blur (funcția () 

Găsiți această nouă textare, iar atunci când utilizatorul părăsește caseta de text, executați o funcție.

 var newText = $ (acest) .val ();

Capturează noul text pe care îl introduc utilizatorii în această textare.

 $ .ajax (tip: 'POST', url: 'updateEntry.php', date: 'description =' + newText + '& id =' + id, succes: function (results) $ this.parent ()) .find ('p'), gol (), append (newText),);

Apelați funcția .ajax și treceți câțiva parametri. Tipul va fi "POST". Adresa URL de acces este "updateEntry.php". Datele care trec la această pagină sunt textul nou introdus de utilizator și idul unic din acel rând din baza de date. Când actualizarea este efectuată cu succes, executați o funcție și actualizați vechiul text cu textul nou!

 return false;

Returnați falsul pentru a vă asigura că dați clic pe eticheta de ancorare nu direcționează utilizatorul în altă parte.


Pasul 7b: PHP

Amintiți-vă că am apelat pagina noastră de "updateEntry" PHP cu jQuery, dar nu am creat-o! Să facem asta acum. Creați o pagină nouă numită "updateEntry.php" și lipiți-o în următoarele.

 update_by_id ($ _ POST ['id'], $ _POST ['descriere']); ?>

Ca și înainte, ne referim la clasa db și apoi o instanțiăm. Apoi, creăm o nouă variabilă, numită răspuns $, și o facem egală cu ceea ce este returnat din metoda "update_by_id ()". Nu am creat încă această metodă. Acum este un moment bun pentru a face acest lucru.

Adăugarea unei noi metode la clasa noastră

Reveniți la pagina dvs. db.php și adăugați o nouă metodă în partea de jos.

 funcția update_by_id ($ id, $ description) $ query = "UPDATE todo SET descriere =? WHERE id =? LIMIT 1"; dacă ($ stmt = $ this-> mysql-> prepare ($ interogare)) $ stmt-> bind_param ('si', $ description, $ id); $ Stmt-> execute (); întoarceți o treabă bună! La curent'; 

Această metodă acceptă doi parametri: id-ul și descrierea elementului. Deci, atunci când numim această metodă, trebuie să ne amintim să treci în acești doi parametri! Începem prin crearea interogării: actualizăm tabelul "todo" și schimbăm descrierea în ceea ce este transmis - dar actualizăm doar rândul în care id-ul este egal cu parametrul trecut.

Ca și ultima oară, vom folosi declarații pregătite pentru a ne actualiza baza de date. Este cel mai sigur mod! Pregătiți interogarea noastră, legați parametrii (șir și întreg, sau "si") și executați. Vom întoarce un șir generic, dar într-adevăr nu este necesar deloc. Actualizarea noastră ar trebui să funcționeze perfect!


Pasul 8: Ștergeți elementele


Să creați, de asemenea, un mod frumos asincron pentru ca utilizatorul să șterge intrările. Când fac clic pe butonul de ștergere pentru un element, vom elimina div și actualizăm baza de date pentru a reflecta ștergerea. Deschideți fișierul javascript și adăugați următoarele:

 // Șterge eticheta de ancora a făcut clic pe $ ('a.deleteEntryAnchor'). Faceți clic pe (function () var thisparam = $ (this); Așteptați ... '); $ .ajax (type:' GET ', url: thisparam.attr (' href '), succes: function (results) thisparam.parent ;) return false;);

Decodarea

 $ ('a.deleteEntryAnchor') faceți clic pe (funcția () 

Când se face clic pe eticheta de ancorare cu o clasă de "deleteEntryAnchor", executați o funcție.

 var thisparam = $ (aceasta);

Cache $ (acest lucru) ca acest param.

 parola (), găsiți ('p') text ('Vă rugăm așteptați ...');

Modificați textul descrierii la "Vă rugăm așteptați". Trebuie să facem acest lucru pentru a oferi utilizatorilor feedback, doar în cazul în care durează mai mult decât se aștepta.

 $ .ajax (tip: 'GET', url: thisparam.attr ('href'), succes: function (results) thisparam.parent

La fel ca și ultima oară, trecem în câțiva parametri care accesează "delete.php". În loc să hardcodez pagina în valoarea urlului, accesez attr ('href') - care este egală cu 'delete.php? Id = $ id'.

 D

Nu avem nevoie de un parametru "DATA", deoarece toate informațiile adecvate se găsesc în termenul de interogare al urlului. Odată ce ștergerea este efectuată cu succes, găsim parola ".item" div, și se estompează încet.

Delete.php

Am apelat pagina noastră de ștergere cu jQuery, dar nu am creat încă PHP. Creați noua pagină și adăugați următorul cod.

 delete_by_id ($ _ GET [ 'id']); antet ("Locație: index.php");

Ar trebui să fii obișnuit cu aceste proceduri până acum. Creați o nouă instanță a clasei noastre și apelați metoda "delete_by_id". După ce a fost finalizată cu succes, redirecționați utilizatorul înapoi la "index.php". După cum probabil ați ghicit, trebuie să creați o nouă metodă în cadrul clasei db. Reveniți la db.php și adăugați noua funcție.

Delete_by_id () Metodă

 funcția delete_by_id ($ id) $ query = "DELETE din todo WHERE id = $ id"; $ result = $ this-> mysql-> interogare ($ query) sau să moară ("a existat o problemă, omule."); dacă ($ rezultat) returnează 'yay!'; 

Această metodă va accepta un parametru - id-ul. Amintiți-vă: pentru a actualiza un rând, trebuie să cunoaștem ID-ul unic al rândului. În caz contrar, va actualiza fiecare rând. Ștergem toate rândurile din tabel, unde id-ul este egal cu cel trecut. Deoarece fiecare rând are propriul id unic, numai unul va fi afectat. Apoi, transmitem această interogare obiectului mysql. Încă o dată, returnarea este inutilă; este doar pentru distracție.


Pasul 9: Extra jQuery

Am terminat munca noastră PHP! Ultimul pas este să adăugați un pic de jQuery pentru a face ca totul să funcționeze puțin mai bine. În partea de sus a fișierului dvs. Javascript, imediat după metoda document.ready, adăugați următorul cod:

 // Nu afișați fila addNewEntry când pagina se încarcă. $ ('# addNewEntry'). css ('afișare', 'none'); // Folosim jQuery pentru a crea filele. Dacă Javascript este dezactivat, acestea nu vor funcționa. Având în vedere acest lucru, ar trebui să adăugăm filele noastre, astfel încât să nu apară dacă sunt dezactivate. $ ( '# File'). Adăugați (“
  • Articol nou
  • „); // Ascundeți descrierea pentru fiecare element de rezolvat. Afișați numai eticheta h4 pentru fiecare dintre ele. $ ( 'Div.item'), copii () nu ( 'h4') ascunde ()...; // Întregul element div este clicabil. Pentru a oferi acest feedback, schimbăm cursorul mouse-ului. // Când se face clic pe div, vom comuta afișarea de la vizibil la ascuns de fiecare dată când este făcut clic. // Totuși, atunci când utilizatorul face clic pe butonul "actualizare", div va fi închis atunci când face clic în interiorul textarea // pentru a edita descrierea. Acest cod detectează dacă țintă a clicului a fost textarea. Dacă a fost, // nu facem nimic. $ ('div.item') css ('cursor', 'pointer') faceți clic (funcția (e) if (! $ (e.target). copii () nu ('h4') slideToggle (); $ (this) .copii ('h4') toggleClass ('expandDown');

    Am comentat fiecare pas destul de bine. Deci, mă voi abține să mă repet. Ultimul fișier scripts.js ar trebui să arate așa.

     $ ('addNewEntry')) css ('display', 'none'); // Folosim jQuery pentru a crea filele noastre Dacă Javascript este dezactivat, acestea nu vor funcționa .. Considerând // acest lucru, ar trebui să adăugăm filele noastre, astfel încât să nu apară dacă sunt dezactivate $ ('# tabs') append ('
  • Articol nou
  • „); // Ascundeți descrierea pentru fiecare element de rezolvat. Afișați numai eticheta h4 pentru fiecare dintre ele. $ ( 'Div.item'), copii () nu ( 'h4') ascunde ()...; // Întregul element div este clicabil. Pentru a oferi acest feedback, schimbăm cursorul mouse-ului. // Când se face clic pe div, vom comuta afișarea de la vizibil la ascuns de fiecare dată când este făcut clic. // Totuși, atunci când utilizatorul face clic pe butonul "actualizare", div va fi închis atunci când face clic în interiorul textarea // pentru a edita descrierea. Acest cod detectează dacă țintă a clicului a fost textarea. Dacă a fost, // nu facem nimic. $ ('div.item') css ('cursor', 'pointer') faceți clic (funcția (e) if (! $ (e.target). copii () nu ('h4') slideToggle (); $ (this) .copii ('h4') toggleClass ('expandDown'); // adauga fisierul de element nou click pe $ ('# tabs li'). click (function () $ ('# tabs li'). dacă '$' (')' ('id') == 'newitem_tab') $ (' ('display', 'block'); else $ ('# addNewEntry') css (' return false;); $ ('# todo div: first') copii ('h4') addClass ('expandDown'). // Șterge eticheta de ancora a făcut clic pe $ ('a.deleteEntryAnchor'). Faceți clic pe (function () var thisparam = $ (this); Așteptați ... '); $ .ajax (type:' GET ', url: thisparam.attr (' href '), succes: function (results) thisparam.parent ;) return false;); // Editați un element asincron $ ('. EditEntry'). Faceți clic pe (funcția () var $ this = $ (this); var oldText = $ this.parent () parent (). ('id:' + id); $ this.parent () parent () a găsi ('# id' () .find ( 'p'). gol (). append (“„); $ ('newDescription'). blur (function () var newText = $ (this) .val (); $ .ajax (type: 'POST', url: 'updateEntry.php' '+ newText +' & id = '+ id, succes: functie (rezultate) $ this.parent () parent (). ); return false; ); );

    Pasul 10: Așteaptă! aspectul este ciudat în IE6.

    Nu o putem numi încă o zi! Această distracție Internet Explorer 6 provoacă câteva probleme de aspect.


    1. Png-urile de fundal sunt de 24 de biți. IE6 nu susține acest lucru. Va trebui să importem un script pentru a rezolva problema.
    2. Fila de navigare nu apare în fața corectă.
    3. Fiecare div.item nu se afișează corect atunci când este extins.
    4. Butoanele noastre de editare și ștergere sunt prea departe spre dreapta divului nostru.

    Soluția

    Deși ne-ar plăcea, nu putem ignora acest browser încă. Din fericire, veți descoperi că majoritatea problemelor IE6 pot fi rezolvate destul de ușor. În primul rând, trebuie să importem un script care va rezolva problema noastră de transparență alfa. Dean Martin are un fișier fantastic Javascript care aduce IE6 conform standardelor. Pur și simplu adăugând "-trans" la sfârșitul numelor de fișiere png de 24 de biți, ne putem rezolva problema. Asigurați-vă că vizitați folderul cu imagini și editați numele.

     

    Google CDN vine din nou la salvare, oferind o versiune găzduită a scriptului IE7. Asta rezolvă problema noastră de transparență, dar încă mai avem câteva ciudățenii.


    Rețineți că, în declarația noastră condiționată, am importat și un fișier "ie.css". Creați acel fișier acum și lipiți în următoarele:

     corp marja: 0; umplutura: 0;  #tabs height: 100%;  #main înălțime: 100%;  #main div.item width: 100%; overflow: ascuns; poziție: relativă; 

    Veți găsi că adăugarea pozițiilor: "relativă", "depășire: ascunsă" și "înălțime: 100%" va determina 90% din problemele dvs. IE6. Acum, aspectul nostru funcționează perfect în toate browserele!


    Ați terminat!


    A fost o LOT pentru a acoperi aici. Sper că am explicat destul de bine. Dacă nu, asta este pentru ce este asociat ecranul asociat! Asigurați-vă că vă revizuiți pentru a șterge zonele neclare. Dacă încă aveți întrebări, întrebați-mă! Mulțumesc mult pentru citire.

    Cod