Accesul la bazele de date PHP îl faci corect?

Am acoperit API-ul PHP PDO de câteva ori aici pe Nettuts +, dar, în general, acele articole s-au concentrat mai mult pe teorie și mai puțin pe aplicație. Acest articol va rezolva problema!

Pentru a spune clar, dacă utilizați în continuare PHP vechi MySQL API pentru a vă conecta la bazele dvs. de date, citiți mai departe!

Căutați o comandă rapidă?

Dacă lucrați cu PHP sau MySQL și aveți nevoie de o remediere rapidă pentru o eroare în codul dvs., puteți avea o singură eroare fixată rapid și accesibil de către dezvoltatorul PHP Araneux pe Envato Studio.


Ce?

Este posibil ca, în acest moment, singurul gând din mintea ta să fie: "Ce naiba este DOP?" Ei bine, este unul dintre cele trei API-uri disponibile pentru conectarea la o bază de date MySQL. "Trei", spui? Da; mulți oameni nu știu acest lucru, dar există trei API-uri diferite pentru conectare:

  • MySQL
  • mysqli - MySQL îmbunătățită
  • PDO - Obiectele de date PHP

Traditionalul MySQL API are cu siguranță sarcina și a devenit atât de popular, în mare parte datorită faptului că face procesul de recuperare a unor înregistrări dintr-o bază de date cât mai ușor posibil. De exemplu:

/ * * Anti-Pattern * / # Conectați mysql_connect ('localhost', 'username', 'password') sau mori ('Nu s-a putut conecta:' mysql_error ()); # Alegeți o bază de date mysql_select_db ('someDatabase') sau mori ('Nu am putut selecta baza de date'); # Efectuați interogarea bazei de date $ query = "SELECT * from someTable"; $ result = mysql_query ($ query) sau mor ('Query failed:' mysql_error ()); # Filtrați prin rânduri și ecou informațiile dorite în timp ce ($ row = mysql_fetch_object ($ rezultat)) echo $ row-> name; 

Da, codul de mai sus este destul de simplu, dar vine cu partea sa semnificativă de dezavantaje.

  • depreciată: Deși nu a fost oficial respinsă - datorită utilizării pe scară largă - în ceea ce privește cele mai bune practici și educația, ar putea fi, de asemenea,.
  • evadarea: Procesul de scăpare a datelor introduse de utilizatori este lăsat de dezvoltator - mulți dintre aceștia nu înțeleg sau știu cum să dezinstaleze datele.
  • Flexibilitate: API nu este flexibil; codul de mai sus este personalizat pentru lucrul cu o bază de date MySQL. Ce se întâmplă dacă comutați?

PDO sau PHP Data Objects, oferă un API mai puternic, care nu-i pasă de driverul pe care îl utilizați; este baza de date agnostică. În plus, oferă abilitatea de a utiliza declarații pregătite, eliminând practic orice îngrijorare a injectării SQL. Verificați gama de scripturi și aplicații PDO de pe Envato Market pentru a obține o idee despre ceea ce este posibil.


Cum?

Când am început să învăț despre API-ul DOP, trebuie să recunosc că a fost ușor intimidant. Acest lucru nu sa datorat faptului că API a fost prea complicat (nu este) - este doar vechea myqsl API a fost atât de ușor de utilizat!

Nu vă faceți griji, totuși; urmați acești pași simpli și veți fi difuzați în cel mai scurt timp.

Conectați

Deci, deja cunoașteți modul vechi de conectare la o bază de date MySQL:

# Conectați mysql_connect ('localhost', 'username', 'password') sau mori ('Nu s-a putut conecta:'. Mysql_error ());

Cu PDO, creăm o nouă instanță a clasei și specificăm driverul, numele bazei de date, numele de utilizator și parola - cum ar fi:

$ conn = PDO nou ("mysql: host = localhost; dbname = myDatabase", $ username, $ password);

Nu lăsa chestia asta lungă să te deruteze; este foarte simplu: specificăm numele driverului (mysql, în acest caz), urmat de detaliile necesare (șir de conectare) pentru conectarea la acesta.

Ce este frumos cu privire la această abordare este că, dacă dorim în schimb să folosim o bază de date sqlite, actualizăm pur și simplu DSN sau "Nume sursă de date"; nu suntem dependenți de MySQL în modul în care suntem atunci când folosim funcții, cum ar fi mysql_connect.

Erori

Dar, dacă există o eroare și nu ne putem conecta la baza de date? Să înfășurăm totul într-un încearcă să prinzi bloc:

încercați $ conn = nou DOP ("mysql: host = localhost; dbname = myDatabase", $ username, $ password); $ conn-> setAttribute (DOP :: ATTR_ERRMODE, DOP :: ERRMODE_EXCEPTION);  captură (PDOException $ e) echo 'ERROR:'. $ E> getMessage (); 

Asa e mai bine! Rețineți că, în mod prestabilit, modul de eroare implicit pentru PDO este DOP :: ERRMODE_SILENT. Dacă această setare este lăsată neschimbată, va trebui să preluați manual erorile după efectuarea unei interogări.

echo $ conn-> errorCode (); echo $ conn-> errorInfo ();

În schimb, o alegere mai bună, în timpul dezvoltării, este actualizarea acestei setări DOP :: ERRMODE_EXCEPTION, care va declanșa excepții pe măsură ce apar. În acest fel, orice excepție neafectată va opri scenariul.

Pentru referință, opțiunile disponibile sunt:

  • DOP :: ERRMODE_SILENT
  • DOP :: ERRMODE_WARNING
  • DOP :: ERRMODE_EXCEPTION

aduce

În acest moment, am creat o conexiune la baza de date; să adunăm niște informații din ea. Există două modalități principale de a realiza această sarcină: întrebare și a executa. Vom examina ambele.

întrebare

/ * * Metoda de interogare * Anti-Pattern * / $ name = 'Joe'; # date furnizate de utilizator încercați $ conn = noi PDO ("mysql: host = localhost; dbname = myDatabase", $ username, $ password); $ conn-> setAttribute (DOP :: ATTR_ERRMODE, DOP :: ERRMODE_EXCEPTION); $ date = $ conn-> interogare ('SELECT * FROM myTable WHERE nume ='. $ conn-> quote ($ name)); foreach (date $ ca $ $) print_r ($ row);  captură (PDOException $ e) echo 'ERROR:'. $ E> getMessage (); 

Deși funcționează acest lucru, observați că încă scăpăm manual din datele utilizatorului cu DOP :: citat metodă. Gândiți-vă la această metodă, mai mult sau mai puțin, la DOP echivalent cu utilizarea mysql_real_escape_string; ambele vor scăpa și vor cita șirul pe care îl transmiteți. În situațiile în care obligați date furnizate de utilizatori la o interogare SQL, este foarte recomandat să utilizați în schimb declarații pregătite. Acestea fiind spuse, dacă interogările dvs. SQL nu depind de datele formularului, întrebare metoda este o alegere utilă, și face procesul de looping prin rezultate la fel de ușor ca o pentru fiecare afirmație.

Rapoarte pregătite

/ * * Metoda declarațiilor pregătite * Best Practice * / $ id = 5; încercați $ conn = nou DOP ("mysql: host = localhost; dbname = myDatabase", $ username, $ password); $ conn-> setAttribute (DOP :: ATTR_ERRMODE, DOP :: ERRMODE_EXCEPTION); $ stmt = $ conn-> pregăti ('SELECT * FROM myTable WHERE id =: id'); $ stmt-> execuție (array ('id' => $ id)); în timp ce ($ row = $ stmt-> fetch ()) print_r ($ row);  captură (PDOException $ e) echo 'ERROR:'. $ E> getMessage (); 

În acest exemplu, folosim a pregati pentru a pregăti literalmente interogarea, înainte ca datele utilizatorului să fie atașate. Cu această tehnică, injecția SQL este practic imposibilă, deoarece datele nu se introduc niciodată în interogarea SQL, ea însăși. Observați că, în schimb, folosim parametrii numiți (: id) pentru a specifica înlocuitorii.

Alternativ, puteți folosi ? parametrii, totuși, aceasta face pentru o experiență mai puțin lizibilă. Stick cu parametrii numiți.

Apoi, executăm interogarea, trecând în același timp o matrice, care conține datele care ar trebui să fie legate de acești substituenți.

$ stmt-> execuție (array ('id' => $ id));

O abordare alternativă, dar perfect acceptabilă, ar fi folosirea bindParam astfel:

$ stmt-> bindParam (': id', $ id, DOP :: PARAM_INT); $ Stmt-> execute ();

Specificând Ouput

După ce a sunat a executa , există o varietate de modalități diferite de a primi datele: un matrice (implicit), un obiect etc. În exemplul de mai sus, se utilizează răspunsul implicit: DOP :: FETCH_ASSOC; acest lucru poate fi ușor de înlăturat, deși, dacă este necesar:

în timp ce ($ row = $ stmt-> fetch (PDO :: FETCH_OBJ)) print_r ($ rând); 

Acum, am specificat că vrem să interacționăm cu setul de rezultate într-un mod mai orientat spre obiect. Opțiunile disponibile includ, dar nu se limitează la:

  • DOP :: FETCH_ASSOC: Returnează un matrice.
  • DOP :: FETCH_BOTH: Returnează un tablou, indexat atât de numele coloanei, cât și de indexarea 0.
  • DOP :: FETCH_BOUND: Returnează TRUE și atribuie valorile coloanelor din setul de rezultate variabilelor PHP la care au fost legate.
  • DOP :: FETCH_CLASS: Returnează o nouă instanță a clasei specificate.
  • DOP :: FETCH_OBJ: Returnează un obiect anonim, cu nume de proprietăți care corespund coloanelor.

O problemă cu codul de mai sus este că nu oferim nici un feedback, dacă nu s-au returnat rezultate. Să rezolvăm următoarele:

$ stmt-> execuție (array ('id' => $ id)); # Obțineți o matrice care conține toate rândurile rezultate $ result = $ stmt-> fetchAll (); # Dacă s-au returnat una sau mai multe rânduri ... dacă (count ($ result)) foreach ($ rezultat ca $ row) print_r ($ row);  altceva echo "Niciun rând nu a fost returnat."; 

În acest moment, codul nostru complet ar trebui să arate așa:

 $ id = 5; încercați $ conn = nou PDO ("mysql: host = localhost; dbname = someDatabase", $ username, $ password); $ stmt = $ conn-> pregăti ('SELECT * FROM myTable WHERE id =: id'); $ stmt-> execuție (array ('id' => $ id)); $ rezultat = $ stmt-> fetchAll (); dacă (count ($ result)) foreach ($ rezultat ca $ row) print_r ($ row);  altceva echo "Niciun rând nu a fost returnat.";  captură (PDOException $ e) echo 'ERROR:'. $ E> getMessage (); 

Exerciții multiple

Extensia PDO devine deosebit de puternică atunci când se execută aceeași interogare SQL de mai multe ori, dar cu diferiți parametri.

încercați $ conn = nou PDO ("mysql: host = localhost; dbname = someDatabase", $ username, $ password); $ conn-> setAttribute (DOP :: ATTR_ERRMODE, DOP :: ERRMODE_EXCEPTION); # Pregătiți interogarea ONCE $ stmt = $ conn-> prepare ('INSERT INTO someTable VALUES (: name)'); $ stmt-> bindParam (': nume', $ nume); # Prima introducere $ name = 'Keith'; $ Stmt-> execute (); # A doua inserare $ name = 'Steven'; $ Stmt-> execute ();  captură (PDOException $ e) echo $ e-> getMessage (); 

Odată ce interogarea a fost pregătită, ea poate fi executată de mai multe ori, cu parametri diferiți. Codul de mai sus va introduce două rânduri în baza de date: una cu numele "Kevin", iar cealaltă, "Steven".


CRUD

Acum, că aveți procesul de bază în loc, să examinăm rapid diferitele sarcini CRUD. După cum veți găsi, codul necesar pentru fiecare este practic identic.

Creați (inserați)

încercați $ pdo = nou PDO ("mysql: host = localhost; dbname = someDatabase", $ username, $ password); $ pdo-> setAttribute (DOP :: ATTR_ERRMODE, DOP :: ERRMODE_EXCEPTION); $ stmt = $ pdo-> prepare ('INSERT INTO VALORI TABEL (: nume)'); $ stmt-> execute (array (': name' => 'Justin Bieber')); # Rows afectate? echo $ stmt-> rowCount (); // 1 captură (PDOException $ e) echo 'Eroare:'. $ E> getMessage ();

Actualizați

$ id = 5; $ name = "Joe instalatorul"; încercați $ pdo = nou PDO ("mysql: host = localhost; dbname = someDatabase", $ username, $ password); $ pdo-> setAttribute (DOP :: ATTR_ERRMODE, DOP :: ERRMODE_EXCEPTION); $ stmt = $ pdo-> prepare ('UPDATE someTable SET nume =: nume WHERE id =: id'); $ stmt-> execuție (array (': id' => $ id, ': name' => $ nume)); echo $ stmt-> rowCount (); // 1 captură (PDOException $ e) echo 'Eroare:'. $ E> getMessage (); 

Șterge

$ id = 5; // dintr-un formular sau ceva similar încercați $ pdo = nou PDO ('mysql: host = localhost; dbname = someDatabase', $ username, $ password); $ pdo-> setAttribute (DOP :: ATTR_ERRMODE, DOP :: ERRMODE_EXCEPTION); $ stmt = $ pdo-> pregăti ('DELETE FROM someTable WHERE id =: id'); $ stmt-> bindParam (': id', $ id); // de data aceasta, vom folosi metoda bindParam $ stmt-> execute (); echo $ stmt-> rowCount (); // 1 captură (PDOException $ e) echo 'Eroare:'. $ E> getMessage (); 

Cartografierea obiectelor

Unul dintre cele mai noi aspecte ale PDO (mysqli, de asemenea) este că ne dă posibilitatea de a cartografia rezultatele interogării într-o instanță de clasă sau un obiect. Iată un exemplu:

utilizator de clasă public $ first_name; public $ last_name; funcția publică full_name () return $ this-> first_name ". $ this-> last_name; încercați $ pdo = nou PDO ('mysql: host = localhost; dbname = someDatabase', $ username, $ password); $ pdo-> setAttribute (PDO :: ATTR_ERRMODE, PDO :: ERRMODE_EXCEPTION); $ result = $ pdo-> interogare ('SELECT * FROM someTable' "Utilizator"), în timp ce ($ user = $ result-> fetch ()) # Apelați metoda noastră full_name echo $ user-> full_name (); catch (PDOException $ e) e-> getMessage ();

Gânduri închise

Linia de fund: dacă încă mai folosiți acel vechi MySQL API pentru conectarea la bazele dvs. de date, opriți. Deși nu a fost încă depreciată, în ceea ce privește educația și documentarea, ar putea fi și ea. Codul dvs. va fi semnificativ mai sigur și simplificat dacă veți adopta extensia DOP. Verificați elementele DOP de pe Envato Market pentru a vedea ce puteți face.

Cod