Pdo înlocuiește parametrii fără a executa interogarea. Cum se lucrează cu PDO? Ghid complet. Inserarea într-o bază de date, metoda exec().

Conexiune la baza de date este setat atunci când este creată o instanță a clasei PDO. Nu contează ce driver alegi să folosești; Va trebui să utilizați întotdeauna clasa PDO. Constructorul său acceptă parametri pentru specificarea sursei bazei de date (cunoscut sub numele de DSN) și parametri opționali pentru un nume de utilizator și o parolă.

Conexiune la MySQL:

$dbh = PDO nou ("mysql:host=localhost;dbname=test", $user, $pass);

Dacă apar erori de conexiune, va fi lansată o excepție: un obiect din clasa PDOException. Puteți să-l prindeți dacă doriți să gestionați această situație sau o puteți lăsa pentru handlerul global de excepții, care este setat prin set_exception_handler().

Gestionarea erorilor de conectare:

încercați ( $dbh = PDO nou ("mysql:host=localhost;dbname=test", $user, $pass); foreach($dbh->query('SELECT * from FOO') as $row) ( print_r($ row); ) $dbh = null; ) catch (PDOException $e) ( die("Eroare! Asta e. Am ajuns... ".$e->getMessage()); )

Atenţie: Dacă nu prindeți excepția aruncată de constructorul PDO, acțiunea implicită luată de motorul zend este să opriți scriptul și să afișați un traceback. Prostia asta va dezvălui toate detaliile tale intime ale comunicării cu baza de date. Acesta este va afișa detalii detaliate de conectare la baza de date, inclusiv numele de utilizator și parola! Depinde de tine să prinzi această excepție, fie în mod explicit (prin intermediul unei declarații încearcă să prinzi), sau implicit prin set_exception_handler().

Odată ce o conexiune la baza de date are succes, aceasta rămâne activă pe toată durata de viață a instanței obiectului PDO. Pentru a închide o conexiune, trebuie să distrugeți obiectul, asigurându-vă că toate referințele rămase la acesta sunt eliminate - acest lucru se poate face prin atribuirea valorii NULL variabilei care conține obiectul. Dacă nu faceți acest lucru în mod explicit, PHP va închide automat conexiunea atunci când scriptul iese.

Închiderea unei conexiuni:

$dbh = PDO nou ("mysql:host=localhost;dbname=test", $user, $pass); // Facem ceva aici: ... // Și acum, atenție: sfârșitul conexiunii! $dbh = nul;

Multe aplicații web beneficiază de crearea de conexiuni persistente la serverele de baze de date. Conexiunile persistente nu sunt închise când scriptul iese, ci sunt stocate în cache și reutilizate atunci când un alt script solicită conexiuni folosind aceleași date de conectare. Un cache de conexiune persistentă evită suprasarcina de stabilire a unei noi conexiuni de fiecare dată când un script trebuie să comunice cu baza de date, rezultând în aplicațiile web să ruleze mai rapid.

Configurarea unei conexiuni permanente:

$dbh = PDO nou ("mysql:host=localhost;dbname=test", $user, $pass, array(PDO::ATTR_PERSISTENT => true));

Ține minte: Dacă doriți să utilizați o conexiune persistentă, trebuie să setați PDO::ATTR_PERSISTENTîn matricea de opțiuni de driver, care este transmisă constructorului de clasă PDO. Prin setarea acestui atribut prin PDO::setAttribute() după ce obiectul este instanțiat, driverul nu va folosi legături persistente. Și, de asemenea, în acest caz, nu veți putea extinde clasa PDOStatement pentru unele dintre nevoile dvs., de exemplu. nu se va putea instala: PDO::ATTR_STATEMENT_CLASS

Cred că este timpul să-mi sporesc experiența și să trec de la funcțiile mysql_ la PDO atunci când lucrez cu o bază de date. Această bibliotecă este un plus puternic și rapid la PHP. Unul dintre avantajele sale este că funcționează cu multe baze de date (MS SQL, MySQL, PostgreSQL, Oracle etc.). De asemenea, o caracteristică distinctivă a acestei biblioteci sunt expresiile pregătite, așa-numitele instrucțiuni pregătite, care ar trebui să accelereze lucrul cu baza de date și, cel mai important, să facă schimbul de date în siguranță și să uite de vulnerabilități precum sql-injection. În plus, există și alte funcții foarte utile. În acest articol, am încercat să adun exemple de lucru utilizate frecvent din care puteți înțelege imediat esența muncii DOP.

În PHP, există trei extensii pentru lucrul cu baza de date MySQL: mysql, mysqli și PDO. PHP PDO (PHP Data Objects) este inclus în PHP 5.1 și versiuni ulterioare. Din câte am înțeles, în acest moment, funcțiile pentru lucrul cu baza de date mysql_ nu sunt recomandate pentru utilizare, deoarece dezvoltarea php_mysql s-a oprit la a suporta funcționalitatea MySQL 4.1.3. și, de asemenea, nu acceptă tranzacții, interfața obiect și este supusă unor vulnerabilități la înlocuirea valorilor într-o interogare. După mysql_ a apărut extensia mysqli (MySQL Îmbunătățit în versiunea 5), ​​care acceptă noi caracteristici MySQL și folosește atât sintaxa OPP, cât și programarea procedurală. Toate aceste biblioteci folosesc biblioteca client standard MySQL (libmysql). În aceeași notă, să ne uităm la exemple live despre cum să lucrați cu mysql folosind cea mai recentă extensie - DOP.

Conexiune la baza de date PDO

//un exemplu de conectare la MySQL folosind PDO $db = new PDO("mysql:host=localhost;dbname=test", $user, $pass);

Odată ce se stabilește o conexiune cu succes la un anumit server de bază de date, va fi returnat un obiect PDO. Acest obiect vă permite să efectuați o mare varietate de sarcini de bază de date.

Dacă există erori de conexiune, mecanismul de excepție va fi declanșat - PDOException. Ar trebui să împachetați întotdeauna operațiunile PDO într-un bloc try/catch. Puteți prinde excepția dacă doriți să gestionați erorile sau o puteți lăsa pentru handlerul global de excepții pe care l-ați creat cu set_exception_handler(). PDO are funcții speciale pentru erori: errorCode() – va returna numărul erorii, errorInfo() – va returna o matrice cu numărul și descrierea erorii. Sunt necesare deoarece modul implicit de tratare a erorilor este ERRMODE_SILENT. În acest caz, pentru a vedea aceste erori va trebui să le apelați:

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

Pentru a evita acest lucru, în modul de dezvoltare este mai ușor să setați imediat modul de tratare a erorilor dorit: ATTR_ERRMODE și ERRMODE_EXCEPTION. De asemenea, puteți specifica codificarea pentru lucrul cu baza de date. Ca rezultat, vom obține următorul cod de conectare:

Încercați ( $db = PDO nou ("mysql:host=$host;dbname=$dbname", $user, $parolă); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $db-> exec("set names utf8"); ) catch(PDOException $e) ( echo $e->getMessage(); )

După conectarea cu succes la baza de date, o instanță a clasei PDO este returnată la script. $db conține handle-ul bazei de date. Conexiunea rămâne activă pe toată durata de viață a obiectului PDO. Pentru a închide o conexiune, trebuie să distrugeți obiectul, asigurându-vă că toate celelalte referințe la acesta sunt șterse. Puteți face acest lucru atribuind variabilei care conține obiectul la NULL. Cu excepția cazului în care faceți acest lucru în mod explicit, PHP va închide automat conexiunea la finalizarea scriptului.

//Închiderea conexiunii $db = null;

Multe aplicații web vor beneficia de crearea de conexiuni persistente la serverele de baze de date. Conexiunile persistente nu sunt închise la sfârșitul scriptului, ci sunt stocate în cache și reutilizate atunci când un alt script solicită o conexiune folosind aceleași acreditări. O conexiune persistentă reduce costul general al creării unei noi conexiuni de fiecare dată când un script trebuie să acceseze baza de date, rezultând o aplicație web mai rapidă.

//Conexiune persistentă $dbh = PDO nou ("mysql:host=localhost;dbname=test", $user, $pass, array(PDO::ATTR_PERSISTENT => true));

Acum că ați văzut cum să deschideți și să închideți o conexiune, să ne uităm la alte exemple de lucru cu PDO. În acest caz, vă voi arăta cum să interogați o anumită bază de date. Interogările pot fi făcute folosind 3 funcții: exec(), query() și prepare+execute.

Exec()

Primul - exec va returna doar numărul de rânduri implicate sau FALSE în caz de eroare și este utilizat acolo unde nu sunt returnate date, de exemplu la ștergere:

//folosind metoda exec() try( $db = new PDO("mysql:host=localhost;dbname=test","user","parola"); $delrows=$db->exec("DELETE FROM users WHERE id>20"); echo "Numărul de rânduri șterse: ".$delrows; ) catch(PDOException $e)( echo "Eroare: ".$e->getMessage(); exit(); ) //Mai mult $ db- >exec("ȘTERGEȚI DE LA oameni de unde 1"); //sau $db->exec("SET time_zone = "-8:00""); //sau $db->exec("CREATE TABLE `test`(id INT PRIMARY KEY AUTO_INCREMENT, nume VARCHAR(20) NOT NULL DEFAULT "", email VARCHAR(50) NOT NULL DEFAULT "")"); //sau $db->exec("SETARE SET DE CARACTERE utf8");

Interogare()

În al doilea rând, query() va returna rezultatul într-un obiect PDOStatement. De asemenea, returnează rezultat sau FALSE în caz de eroare. Puteți avea încredere în el cu cereri simple. Puteți folosi query() cu o condiție (chiar nu știu de ce cineva ar avea nevoie de asta), dar apoi trebuie totuși să scăpați de date folosind metoda PDO::quote

//Interogări simple $db->query("SET CARACTER SET utf8"); $db->query("SELECT * FROM utilizatori"); //Puteți calcula numărul de rânduri $stmt = $db->query("SELECT * FROM table"); $row_count = $stmt->rowCount(); echo $row_count." rânduri selectate"; //O alta optiune cu cantitate $stmt = $db->query("SELECT * din utilizatori"); $rows = $stmt->fetchAll(); $număr = număr ($rânduri); foreach($rows as $row) ( print_r($row); ) //Interogare cu condiție și escape $conn->query("SELECT * FROM table WHERE id = " . $conn->quote($id));

lastInsertId() returnează ID-ul ultimului rând al bazei de date inserat.

//Metoda lastInsertId() returnează id-ul ultimei înregistrări $db->query("INSERT INTO users SET name="Vasya",address="Here",email=" [email protected]""); $insertId=$db->lastInsertId();

Declarații pregătite.

A treia cale - pregăti+executa - Expresii pregătite, sunt și instrucțiuni pregătite, sunt și substituenți, sunt declarații pregătite sau legați variabile, vă permit să definiți o expresie o dată și apoi să o executați de mai multe ori cu diferiți parametri. De asemenea, vă permit să separați variabilele din cerere, ceea ce face codul mai sigur și crește viteza de execuție. Codul dvs. nu va mai trebui să încerce să curețe datele transferate. Vom face asta o singură dată înainte de a executa interogarea bazei de date. Pentru a face acest lucru folosim funcția A pregati(); Este nevoie de o interogare SQL ca parametru, dar în ea, în loc de variabile, sunt folosite etichete, sub forma unui semn de întrebare „?” sau numere „:1”, sau a unei variabile al cărei nume începe cu două puncte „:” . Dacă v-ați oprit la semnele de întrebare (:numerele), atunci trebuie să transmiteți o matrice de valori în secvența corespunzătoare funcției de execuție. Dacă alegerea dvs. este numită variabile, atunci trebuie să atribuiți o valoare fiecărei variabile prin una dintre cele două funcții: fie bindValue(), care atribuie o valoare unei pseudo-variabile, fie bindParam(), care leagă o pseudo-variabilă la o variabilă reală. Al treilea parametru poate indica tipul variabilei, de exemplu $db->bindParam(':id',$id, PDO::PARAM_INT).

//Etichete fără nume încearcă ( $stmt = $db->prepare("INSERT INTO test (etichetă,culoare) VALUES (?,?)"); $stmt -> execute(array("perfect","verde") ) ; ) catch(PDOException $e)( echo "Eroare: ".$e->getMessage(); exit(); ) //stmt este un "mâner de stare" //Etichete denumite $stmt = $db->prepare ( „INSERT INTO test (label,color) VALUES (:label,:color)”); $stmt -> execute(array("label"=>"perfect", "color"=>"green")); //O altă opțiune $stmt = $db->prepare("INSERT INTO users (prenume, prenume, email) VALUES (:firstname, :lastname, :email)"); $stmt->bindParam(":prenume", $prenume); $stmt->bindParam(":lastname", $lastname); $stmt->bindParam(":email", $email); $prenume = „Ioan”; $nume = "Smith"; $email = " [email protected]"; $stmt->execute();

Permiteți-mi să vă reamintesc încă o dată că, dacă nu utilizați expresii pregătite, dar doriți totuși să securizați datele transmise, atunci acest lucru se poate face folosind funcția PDO:quote.

date PDO SELECT

Metodele fetch() sau fetchAll() sunt folosite pentru a prelua date. Înainte de a apela funcția, trebuie să spuneți PDO cum veți prelua datele din baza de date. PDO::FETCH_ASSOC va returna rândurile ca o matrice asociativă cu numele câmpurilor ca chei. PDO::FETCH_NUM va returna șirurile ca o matrice numerică. În mod implicit, preluarea are loc cu PDO::FETCH_BOTH, care dublează datele atât cu chei numerice, cât și cu chei asociative, așa că este recomandat să specificați o modalitate de a evita matricele duplicat:

$stmt = $db->query("SELECT * din utilizatori"); //Setarea modului de preluare $stmt->setFetchMode(PDO::FETCH_ASSOC); while($row = $stmt->fetch()) ( echo "

" . $row["prenume"] . " " . $row["nume"] ."

"; ecou"

" . $row["e-mail"] ."


"; }

Sau puteți specifica metoda fetch în metoda ->fetch() în sine

$stmt = $db->query("SELECT * FROM table"); while($row = $stmt->fetch(PDO::FETCH_ASSOC)) ( echo $row["field1"]." ".$row["field2"]; //etc... ) // Atenție, exemplu cu LIKE nu merge! $stmt = $db->prepare("SELECTARE câmp din tabelul WHERE câmp LIKE %?%"); $stmt->bindParam(1, $căutare, PDO::PARAM_STR); $stmt->execute(); //Ai nevoie de asta: $stmt = $db->prepare("SELECT field FROM table WHERE field LIKE?"); $stmt->bindValue(1, "%$search%", PDO::PARAM_STR); $stmt->execute(); //Un alt exemplu $stmt = $db->prepare("SELECT * FROM table WHERE id=? AND name=?"); $stmt->bindValue(1, $id, PDO::PARAM_INT); $stmt->bindValue(2, $nume, PDO::PARAM_STR); $stmt->execute(); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); //O altă opțiune $stmt = $db->prepare("SELECT * din utilizatori"); $stmt -> execute(); while($rând = $stmt->fetch()) ( print_r($rând); )

Datele PDO UPDATE

Se întâmplă în esență în același mod ca INSERT și SELECT (în acest caz, vom folosi din nou substituenți cu nume):

$stmt = $db->prepare("UPDATE utilizatorii setați e-mail = :email unde lastname=:lastname"); $stmt->bindParam(":lastname", $lastname); $stmt->bindParam(":email", $email); $nume = "Smith"; $email = " [email protected]"; $stmt->execute();

ȘTERGEÎndepărtarea are loc în cel mai simplu mod:

$db->exec("ȘTERGERE DE LA utilizatori");

Desigur, puteți utiliza și substituenți cu nume atunci când ștergeți.

Dacă aveți propriile șabloane utilizate frecvent când lucrați cu extensia PHP PDO, v-aș fi recunoscător dacă le-ați împărtăși. Link către manual

Dacă aveți o eroare Variabila nedefinită: DBH... atunci puteți citi cum să o remediați.

Google m-a ajutat să găsesc o foaie de cheat pe PDO, poate cineva o va găsi utilă:

PDO (PHP Data Objects) este o extensie PHP care implementează interacțiunea cu bazele de date folosind obiecte. Avantajul este că nu există nicio conexiune la un anumit sistem de gestionare a bazelor de date. PDO acceptă DBMS: MySQL, PostgreSQL, SQLite, Oracle, Microsoft SQL Server și altele.

De ce să folosiți DOP

Funcțiile mysql din PHP pentru lucrul cu baze de date au fost demult depășite; astăzi este recomandabil să utilizați mysqli sau PDO (PHP Data Objects). În plus, mysqli este o bibliotecă care, în general, nu este destinată să fie utilizată direct în cod. Poate servi ca un bun material de construcție pentru crearea unei biblioteci de nivel superior. Când lucrați cu mysqli, ar trebui să vă amintiți, de asemenea, să asigurați securitatea aplicației dvs., în special protecția împotriva injecțiilor SQL. În cazul utilizării PDO (cu interogările sale pregătite), o astfel de protecție iese din cutie; principalul lucru este să aplicați corect metodele necesare.

Baza de date de testare cu tabel

// Din consola Windows mysql> CREATE DATABASE `pdo-test` CHARACTER SET utf8 COLLATE utf8_general_ci; USE pdo-test; CREATE TABLE categorii (id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY(id), nume VARCHAR(255) NOT NULL); INSERT INTO `categories` (`nume`) VALORI ("Laptop-uri și tablete"), ("Computere și periferice"), ("componente PC"), ("Smartphone-uri și ceasuri inteligente"), ("Televizoare și media") , ("Jocuri și console"), ("Echipamente audio"), ("Echipamente foto și video"), ("Echipamente și mobilier de birou"), ("Echipamente de rețea"), ("Aparate electrocasnice mari"), ( „Produse de bucătărie”), („Frumusețe și sănătate”), („Produse pentru casă”), („Unelte”), („Produse auto”);

Instalare PDO

// Instalare pe Linux sudo apt update sudo apt install php7.2-mysql sudo apt-get install pdo-mysql // În php.ini adăugați extensie=pdo.so extension=pdo_mysql.so // Pe Windows, de regulă, driverul este deja instalat, trebuie doar să verificați dacă este activat în extensia php.ini=php_pdo_mysql.dll

Verificați driverele disponibile

print_r(PDO::getAvailableDrivers());

Conexiune la baza de date

Conexiunile sunt stabilite automat atunci când un obiect PDO este creat din clasa sa de bază.

// Exemplul #1. Conexiune simplă $db = PDO nou ("mysql:host=localhost;dbname=pdo", "root", "parolă");

Dacă există o eroare de conexiune, PHP va afișa o eroare:

Eroare fatală: PDOException neprinsă: ... // Exemplul #2. Tratarea erorilor de conexiune încercați ( $dbh = PDO nou ("mysql:host=localhost;dbname=pdo", "root", "parolă"); ) catch (PDOException $e) (printați „Eroare!: " . $e- >getMessage(); die(); )

În acest exemplu de legătură, folosim construcția try...catch. Mulți se ceartă despre oportunitatea utilizării sale. Personal, folosesc try...catch , nu mă deranjează.

Cereri pregătite și directe

Există două moduri de a executa interogări în PDO:

  • Direct - constă dintr-un pas;
  • Pregătit - constă din doi pași.

Cereri directe

  • query() este folosit pentru instrucțiunile care nu fac modificări, cum ar fi SELECT. Returnează un obiect PDOStatemnt din care rezultatele interogării sunt preluate folosind metodele fetch() sau fetchAll. O puteți compara cu resursa mysql, care a fost returnată de mysql_query().
  • exec() este folosit pentru instrucțiunile INSERT, DELETE, UPDATE. Returnează numărul de rânduri procesate de cerere.

Interogările directe sunt utilizate numai dacă nu există variabile în interogare și sunteți sigur că interogarea este sigură și scăpată corect.

$stmt = $db->query("SELECT * FROM categorii"); while ($rând = $stmt->fetch()) ( echo "

"; print_r($rând); )

Interogări pregătite

Dacă cel puțin o variabilă este transmisă cererii, atunci această solicitare trebuie executată numai prin expresii pregătite. Ce înseamnă? Aceasta este o interogare SQL obișnuită, în care este plasat un marcator special în loc de o variabilă - un substituent. PDO acceptă substituenți poziționali (?), pentru care ordinea variabilelor trecute este importantă și substituenți denumiti (:nume), pentru care ordinea nu este importantă. Exemple:

$sql = "SELECTAȚI numele DIN categoriile WHERE id = ?"; $sql = "SELECTARE numele DIN categoriile WHERE nume = :nume";

Pentru a executa o astfel de interogare, trebuie mai întâi pregătită folosind metoda prepare(). De asemenea, returnează o declarație PDO, dar fără date încă. Pentru a le obține, trebuie să executăm această solicitare, după ce am trecut anterior variabilele noastre în ea. Îl puteți transmite în două moduri: Cel mai adesea, puteți executa pur și simplu metoda execute(), trecându-i un tablou cu variabile:

$stmt = $pdo->prepare("SELECT `name` FROM categories WHERE `id` = ?"); $stmt->execute([$id]); $stmt = $pdo->prepare("SELECT `nume` FROM categoriile WHERE `nume` = :nume"); $stmt->execute(["nume" => $nume]);

După cum puteți vedea, în cazul substituenților numiți, o matrice în care cheile trebuie să se potrivească cu numele substituenților trebuie să fie transmisă pentru a executa (). Apoi puteți prelua rezultatele interogării:

$id = 1; $stmt = $db->prepare("SELECT * FROM categoriile WHERE `id` = ?"); $stmt->execute([$id]); $categorie = $stmt->fetch(PDO::FETCH_LAZY); ecou"

"; print_r($categorie);

IMPORTANT! Interogările pregătite sunt motivul principal pentru a utiliza PDO, deoarece este singura modalitate sigură de a executa interogări SQL care implică variabile.

Primirea datelor. metoda fetch().

Ne-am familiarizat deja cu metoda fetch(), care este folosită pentru a obține secvențial rânduri din baza de date. Această metodă este un analog al funcției mysq_fetch_array() și a altora similare, dar acționează diferit: în loc de multe funcții, aici este folosită una, dar comportamentul ei este specificat de parametrul transmis. Detaliile despre acești parametri vor fi scrise și, ca o scurtă recomandare, vă sfătuiesc să utilizați fetch() în modul FETCH_LAZY

$id = 1; $stmt = $db->prepare("SELECT * FROM categoriile WHERE `id` = ?"); $stmt->execute([$id]); while ($rând = $stmt->fetch(PDO::FETCH_LAZY)) ( echo „Nume categorie: „.$rând->nume; )

În acest mod, nu se irosește memorie suplimentară și, în plus, coloanele pot fi accesate în oricare dintre trei moduri - prin index, nume sau proprietate (prin ->). Dezavantajul acestui mod este că nu funcționează cu fetchAll()

Primirea datelor. metoda fetchColumn().

Declarația PDO are și o metodă pentru obținerea valorii unei singure coloane. Este foarte convenabil dacă solicităm un singur câmp - în acest caz cantitatea de cod este redusă semnificativ:

$id = 1; $stmt = $db->prepare("SELECT `name` FROM categories WHERE `id` = ?"); $stmt->execute([$id]); $nume = $stmt->fetchColumn(); echo "Nume categorie: ".$nume;

Primirea datelor. metoda fetchAll().

$date = $db->query("SELECT * FROM categories")->fetchAll(PDO::FETCH_ASSOC); foreach ($date ca $k => $v)( echo "Nume categorie: ".$v["nume"]."
"; }

PDO și operatorul LIKE

Când lucrați cu interogări pregătite, ar trebui să înțelegeți că un substituent poate înlocui numaișir sau număr. Nu este un cuvânt cheie, nu un identificator, nu face parte dintr-un șir sau dintr-un set de șiruri prin intermediul unui substituent nu poți înlocui. Prin urmare, pentru LIKE, trebuie mai întâi să pregătiți întregul șir de căutare și apoi să îl înlocuiți în interogare:

$search = "comp"; $query = "SELECT * FROM categoriile WHERE `name` LIKE ?"; $params = ["%$search%"]; $stmt = $db->prepare($interogare); $stmt->execute($params); $date = $stmt->fetchAll(PDO::FETCH_ASSOC); $i = 1; foreach ($date ca $categorie)( echo $i++ . ". " . $categorie["nume"]."
"; }

Aici poate apărea o problemă! Este posibil ca căutarea să nu funcționeze deoarece primiți date din baza de date într-o codificare greșită. Trebuie să adăugați codificarea la conexiune dacă nu este listată acolo!

$db = PDO nou ("mysql:host=localhost;dbname=pdo;charset=utf8", "root", "");

PDO și operatorul LIMIT

Important! Când PDO rulează în modul de emulare, toate datele care au fost transmise direct către execute() sunt formatate ca șiruri. Adică sunt evadate și încadrate între ghilimele. Prin urmare LIMIT?,? se transformă în LIMIT „10”, „10” și în mod evident provoacă o eroare de sintaxă și, în consecință, o matrice de date goală.

Soluția #1: Dezactivați modul de emulare:

$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Soluția #2: Leagă aceste numere folosind bindValue() , forțându-le să fie de tip PDO::PARAM_INT:

$limita = 3; $stm = $db->prepare("SELECT * FROM categories LIMIT ?"); $stm->bindValue(1, $limit, PDO::PARAM_INT); $stm->execute(); $date = $stm->fetchAll(); ecou"

"; print_r($date);

operator PDO și IN

Când selectați dintr-un tabel, este necesar să recuperați înregistrările care corespund tuturor valorilor matricei.

$arr = ; $in = str_repeat("?,", count($arr) - 1) . „?”; $sql = "SELECT * FROM categoriile WHERE `id` IN ($in)"; $stm = $db->prepare($sql); $stm->execute($arr); $date = $stm->fetchAll(); ecou"

"; print_r($date);

Adăugarea de intrări

$name = "Categorie nouă"; $query = "INSERT INTO `categories` (`nume`) VALORI (:nume)"; $params = [ ":nume" => $nume ]; $stmt = $pdo->prepare($interogare); $stmt->execute($params);

Schimbarea intrărilor

$id = 1; $name = "Intrare schimbata"; $query = "UPDATE `categorii` SET `nume` = :nume WHERE `id` = :id"; $params = [ ":id" => $id, ":name" => $nume ]; $stmt = $pdo->prepare($interogare); $stmt->execute($params);

Ștergerea intrărilor

$id = 1; $query = "ȘTERGERE DIN `categorii` WHERE `id` = ?"; $params = [$id]; $stmt = $pdo->prepare($interogare); $stmt->execute($params);

Utilizarea tranzacțiilor

try ( // Începutul tranzacției $pdo->beginTransaction(); // ... cod // Dacă totul a avut succes ca urmare a executării codului nostru, // atunci vom înregistra acest rezultat $pdo->commit() ; ) catch (Excepția $e) ( // În caz contrar, anulați tranzacția. $pdo->rollBack(); echo "Eroare: " . $e->getMessage(); )

Important! Tranzacțiile în PDO funcționează numai pe tabelele InnoDB

În acest articol, ne-am familiarizat cu conceptele de bază ale PDO, instalarea acestuia, conectarea la baza de date și cele mai simple opțiuni pentru selectarea, modificarea și ștergerea datelor. Vom analiza mai multe subiecte legate de DOP în postările viitoare.

Oferă metode de pregătire a expresiilor și de lucru cu obiecte care te pot face mai productiv!

Introducere în DOP

„PDO – PHP Data Objects este un nivel de acces la baze de date care oferă metode unificate pentru accesarea diferitelor baze de date.”

Nu se bazează pe o sintaxă specifică a bazei de date și vă permite să treceți cu ușurință la un alt tip de bază de date și platformă pur și simplu schimbând șirul de conexiune în majoritatea cazurilor.

Această lecție nu este o descriere a procesului de lucru cu SQL. Este destinat celor care folosesc extensii mysql sau mysqli pentru a-i ajuta să treacă la un DOP mai puternic și mai portabil.

Suport pentru baze de date

Extensia acceptă orice bază de date pentru care există un driver PDO. În prezent, driverele sunt disponibile pentru următoarele tipuri de baze de date:

  • PDO_DBLIB (FreeTDS / Microsoft SQL Server / Sybase)
  • PDO_FIREBIRD (Firebird/Interbase 6)
  • PDO_IBM (IBM DB2)
  • PDO_INFORMIX (Server dinamic IBM Informix)
  • PDO_MYSQL (MySQL 3.x/4.x/5.x)
  • PDO_OCI (Interfață de apel Oracle)
  • PDO_ODBC (ODBC v3 (IBM DB2, unixODBC și win32 ODBC))
  • PDO_PGSQL (PostgreSQL)
  • PDO_SQLITE (SQLite 3 și SQLite 2)
  • PDO_4D (4D)

Pentru ca sistemul să funcționeze, este suficient să instalați doar acele drivere care sunt cu adevărat necesare. Puteți obține o listă de drivere disponibile pe sistem, după cum urmează:

Print_r(PDO::getAvailableDrivers());

Conexiune

Diferite baze de date pot avea metode de conectare ușor diferite. Metodele de conectare la mai multe baze de date populare sunt prezentate mai jos. Veți observa că primele trei sunt identice între ele și doar SQLite are o sintaxă specifică.


încercați ( # MS SQL Server și Sybase cu PDO_DBLIB $DBH = PDO nou ("mssql:host=$host;dbname=$dbname, $user, $pass"); $DBH = nou PDO("sybase:host=$host ;dbname=$dbname, $user, $pass"); # MySQL cu PDO_MYSQL $DBH = PDO nou ("mysql:host=$host;dbname=$dbname", $user, $pass); # SQLite $DBH = PDO nou ("sqlite:my/database/path/database.db"); ) catch(PDOException $e) ( echo $e->getMessage(); )

Atenție la blocaj încearcă să prinzi- ar trebui să împachetați întotdeauna operațiunile PDO într-un bloc încearcă să prinziși utilizați mecanismul de excepție. De obicei, se face o singură conexiune, exemplul nostru arată mai multe conexiuni pentru a afișa sintaxa. $DBH conține un handle de bază de date și va fi folosit pe parcursul tutorialului nostru.

Puteți închide orice conexiune setând mânerul la nul.

# Închideți conexiunea $DBH = null;

Puteți afla mai multe despre opțiunile specifice și șirurile de conexiune pentru diferite baze de date din documentele de pe PHP.net.

Excepții și DOP

PDO poate folosi excepții pentru a gestiona erorile. Aceasta înseamnă că toate operațiunile PDO trebuie să fie incluse într-un bloc încearcă să prinzi. PDO poate arunca trei niveluri de erori, nivelul de control al erorilor este selectat prin setarea atributului modului de control al erorilor pentru descriptorul bazei de date:

$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Indiferent de nivelul de control setat, o eroare de conexiune ridică întotdeauna o excepție și, prin urmare, ar trebui să fie întotdeauna închisă într-un bloc încearcă să prinzi.

PDO::ERRMODE_SILENT

Nivelul de control al erorilor este setat implicit. La acest nivel, erorile sunt generate după același principiu ca și în extensii mysql sau mysqli. Celelalte două niveluri de control al erorilor sunt mai potrivite pentru stilul de programare DRY (Don't Repeat Youself).

PDO::ERRMODE_WARNING

La acest nivel de control al erorilor, sunt generate avertismente PHP standard și programul poate continua să se execute. Acest nivel este convenabil pentru depanare.

PDO::ERRMODE_EXCEPTION

Acest nivel de control al erorilor ar trebui utilizat în majoritatea situațiilor. Sunt generate excepții pentru a gestiona cu atenție erorile și pentru a ascunde datele care ar putea ajuta pe cineva să vă spargă sistemul. Mai jos este un exemplu care demonstrează beneficiile excepțiilor:

# Conectați-vă la baza de date încercați ( $DBH = PDO nou ("mysql:host=$host;dbname=$dbname", $user, $pass); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ; # Se tastează greșit DELECT în loc de SELECT! $DBH->prepare("ȘTERGERE numele de la oameni"); ) catch(PDOException $e) ( echo "Ne pare rău. Dar operația nu a putut fi efectuată."; file_put_contents("PDOErrors. txt" , $e->getMessage(), FILE_APPEND); )

Există o eroare intenționată în instrucțiunea SELECT aici. Acest lucru va face o excepție. Excepția va trimite o descriere a erorii în fișierul jurnal și va afișa un mesaj utilizatorului.

Inserarea si actualizarea datelor

Inserarea de date noi sau actualizarea datelor existente este una dintre cele mai frecvent utilizate operațiuni comune de baze de date. Când se utilizează PDO, acesta este descompus în două etape. Tot ceea ce este descris în acest capitol se aplică ambelor operațiuni. ACTUALIZAȚIȘi INTRODUCE.


Iată un exemplu de tip de inserare de date cel mai utilizat:

# STH este „mânerul de stat” $STH = $DBH->prepare(„INSERT INTO folks (first_name) values ​​​​(„Cathy”)”); $STH->execute();

Desigur, puteți efectua această operație folosind metoda exec(), iar numărul de apeluri va fi cu unul mai puțin. Dar este mai bine să folosiți o metodă mai lungă pentru a obține beneficiile expresiilor pregătite. Chiar dacă intenționați să le utilizați o singură dată, expresiile pregătite vă vor ajuta să vă protejați împotriva atacurilor asupra sistemului dumneavoastră.

Expresii pregătite

Instrucțiunile pregătite sunt instrucțiuni SQL precompilate care pot fi executate de mai multe ori prin trimiterea doar a datelor către server. Au avantajul suplimentar de a popula automat șablonul cu date sub formă de protecție împotriva atacurilor prin atașamente de cod SQL.

Puteți utiliza expresii pregătite incluzând șabloane în codul dvs. SQL. Mai jos sunt 3 exemple: unul fără șabloane, unul cu șabloane fără nume, unul cu șabloane numite.

# fără șabloane - deschis atacurilor cu injecție SQL! $STH = $DBH->("INSERT INTO folks (nume, adresă, oraș) valori ($nume, $adresă, $oraș)"); # șabloane fără nume $STH = $DBH->("INSERT INTO folks (nume, adresa, oraș) valori (?, ?, ?); # șabloane denumite $STH = $DBH->("INSERT INTO folks (nume) , addr , city) valoare (:name, :addr, :city)");

Ar trebui să evitați utilizarea primei metode. Alegerea tiparelor cu nume sau fără nume afectează modul în care setați datele pentru aceste expresii.

Șabloane fără nume

# atribuiți variabile fiecărui șablon, indexate de la 1 la 3 $STH->bindParam(1, $name); $STH->bindParam(2, $adr); $STH->bindParam(3, $oraș); # Inserați o linie $name = "Dima" $addr = "Lizyukova St."; $oraș = „Moscova”; $STH->execute(); # Inserați o altă linie $name = "Senya" $addr = "Dead fund comunist"; $oraș = „Petru”; $STH->execute();

Operația se desfășoară în două etape. În primul pas, variabilele sunt alocate șabloanelor. Apoi, variabilelor li se atribuie valori și se execută expresia. Pentru a trimite următoarea bucată de date, trebuie să modificați valorile variabilelor și să rulați din nou expresia.

Pare puțin greoi pentru expresii cu mulți parametri? Cu siguranță. Cu toate acestea, dacă datele dvs. sunt stocate într-o matrice, atunci totul va fi foarte scurt:

# Date de inserat $date = array("Monya", "Forget-Me-Not Avenue", "Zakutaysk"); $STH = $DBH->(„INSERT INTO folks (nume, adresă, oraș) valori (?, ?, ?)”); $STH->execute($date);

Datele din matrice sunt înlocuite în șabloane în ordinea în care apar. $data merge la primul șablon, $data la al doilea și așa mai departe. Cu toate acestea, dacă matricea este indexată într-o ordine diferită, atunci o astfel de operație nu va fi efectuată corect. Trebuie să vă asigurați că ordinea modelelor se potrivește cu ordinea datelor din matrice.

Șabloane denumite

Iată un exemplu de utilizare a unui șablon numit:

# Primul argument al funcției este numele șablonului numit # Un șablon numit începe întotdeauna cu două puncte $STH->bindParam(":name", $name);

Puteți utiliza comenzi rapide, dar funcționează cu matrice asociate. Exemplu:

# Date de inserat $date = array("name" => "Michelle", "addr" => "Kuznechny Lane", "city" => "Cnjkbwf"); # Stenografie $STH = $DBH->("INSERT INTO folks (nume, adresa, oras) valoare (:nume, :adresa, :oras)"); $STH->execute($date);

Cheile de tabel nu necesită două puncte, dar trebuie totuși să se potrivească cu numele șablonului. Dacă utilizați o matrice de matrice, puteți să o iterați și să apelați pur și simplu a executa pentru fiecare set de date.

O altă caracteristică frumoasă a șabloanelor cu nume este capacitatea de a insera obiecte direct în baza de date atunci când proprietățile și numele câmpurilor se potrivesc. Exemplu:

# Persoana din clasa obiectului simplu ( public $nume; public $adresa; public $oras; function __construct($n,$a,$c) ( $this->name = $n; $this->addr = $a; $ this->city = $c; ) # etc... ) $cathy = new person("Katya","Lenin Avenue","Mozhaisk"); # Executați: $STH = $DBH->("INSERT INTO folks (nume, adresă, oraș) valoare (:nume, :adresă, :oraș)"); $STH->execute((matrice)$cathy);

Conversia tipului de obiect în matrice V a executa face ca proprietățile să fie tratate ca chei de matrice.

Primirea datelor


Metoda de identificare a stării este utilizată pentru a obține date ->fetch(). Înainte de a apela metoda aduce() trebuie să spuneți PDO cum veți prelua datele din baza de date. Puteți selecta următoarele opțiuni:

  • PDO::FETCH_ASSOC: returnează o matrice indexată după numele coloanelor
  • PDO::FETCH_BOTH (implicit): returnează o matrice indexată după nume de coloane și numere
  • PDO::FETCH_BOUND: Atribuie valorile coloanelor dvs. unui set de variabile folosind metoda ->bindColumn()
  • PDO::FETCH_CLASS: atribuie valori de coloană proprietăților unei clase numite; dacă proprietatea corespunzătoare nu există, aceasta este creată
  • PDO::FETCH_INTO: actualizează o instanță existentă a unei clase numite
  • PDO::FETCH_LAZY: combinatie PDO::FETCH_BOTH/PDO::FETCH_OBJ, creează nume de variabile obiect pe măsură ce sunt utilizate
  • PDO::FETCH_NUM: returnează o matrice indexată după numerele coloanei
  • PDO::FETCH_OBJ: returnează un obiect anonim cu nume de proprietate corespunzătoare numelor de coloane

În realitate, situațiile de bază sunt rezolvate folosind trei opțiuni: FETCH_ASSOC, FETCH_CLASSȘi FETCH_OBJ. Pentru a seta metoda de extragere a datelor:

$STH->setFetchMode(PDO::FETCH_ASSOC);

De asemenea, puteți seta metoda de recuperare a datelor direct în apelul de metodă ->fetch().

FETCH_ASSOC

Acest tip de regăsire a datelor creează o matrice asociativă indexată după numele coloanelor. Ar trebui să fie destul de bine cunoscut celor care folosesc extensii mysql/mysqli. Exemplu de date eșantion:

$STH = $DBH->query("SELECT numele, adresa, orasul de la oameni"); # Setați modul de recuperare a datelor $STH->setFetchMode(PDO::FETCH_ASSOC); while($row = $STH->fetch()) ( echo $row["nume"] . "\n"; echo $row["adresa"] . "\n"; echo $row["oraș"] . "\n"; )

Ciclu in timp ce continuă să itereze rezultatul eșantionului câte un rând până la finalizare.

FETCH_OBJ

Cu acest tip de regăsire a datelor, este creat un obiect de clasă std pentru fiecare rând de date primite:

$STH = $DBH->query("SELECT numele, adresa, orasul de la oameni"); # Setați modul de preluare a datelor $STH->setFetchMode(PDO::FETCH_OBJ); # arată rezultatul while($row = $STH->fetch()) ( echo $row->name . "\n"; echo $row->addr . "\n"; echo $row->city . " \ n"; )

FETCH_CLASS

Cu acest tip de extragere, datele sunt plasate direct în clasa pe care o alegeți. Folosind FETCH_CLASS proprietățile obiectului dvs. sunt setate ÎNAINTE de a apela constructorul. Este foarte important. Dacă o proprietate corespunzătoare numelui coloanei nu există, atunci o astfel de proprietate va fi creată (cum ar fi public) Pentru dumneavoastră.

Aceasta înseamnă că, dacă datele au nevoie de transformare după ce au fost preluate din baza de date, aceasta poate fi făcută automat de către obiectul dvs. de îndată ce sunt create.

De exemplu, imaginați-vă o situație în care adresa trebuie să fie parțial ascunsă pentru fiecare intrare. Putem îndeplini sarcina manipulând proprietatea din constructor:

Clasa secret_person ( public $nume; public $adresa; public $oras; public $alte_date; function __construct($other = "") ( $this->address = preg_replace("//", "x", $this-> adresa); $aceasta->alte_date = $altele; ) )

Odată ce datele sunt extrase în clasă, toate caracterele minuscule a-z din adresă vor fi înlocuite cu caracterul x. Acum, folosind clasa și preluarea datelor, transformarea are loc complet transparent:

$STH = $DBH->query("SELECT numele, adresa, orasul de la oameni"); $STH->setFetchMode(PDO::FETCH_CLASS, "persoana_secreta"); while($obj = $STH->fetch()) ( echo $obj->addr; )

Dacă adresa a fost „Leninsky Prospekt 5”, veți vedea „Lxxxxxxxxxx xx-x 5”. Desigur, există situații în care doriți ca constructorul să fie apelat înainte ca datele să fie atribuite. PDO are mijloacele pentru a implementa acest lucru:

$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, „persoană_secretă”);

Acum, când repeți exemplul anterior cu modul setat PDO::FETCH_PROPS_LATE adresa nu va fi ascunsă deoarece constructorul a fost apelat și proprietățile au fost atribuite.

Dacă aveți nevoie, puteți transmite argumente constructorului atunci când extrageți date în obiect:

$STH->setFetchMode(PDO::FETCH_CLASS, "persoana_secreta", array("lucruri"));

Dacă trebuie să transmiteți diferite date constructorului pentru fiecare obiect, puteți seta modul de recuperare a datelor în cadrul metodei aduce:

$i = 0; while($rowObj = $STH->fetch(PDO::FETCH_CLASS, "secret_person", array($i))) ( // face chestii $i++ )

Alte metode utile

Deoarece PDO nu poate fi descris pe deplin într-un scurt articol, vom prezenta câteva metode utile pentru efectuarea operațiunilor de bază.

$DBH->lastInsertId();

Metodă ->lastInsertId() este întotdeauna apelat de un handle de bază de date (nu de un handle de stare) și returnează valoarea ID-ului auto-incrementat al ultimului rând inserat pentru o anumită conexiune.

$DBH->exec("ȘTERGEȚI DE LA oameni de unde 1"); $DBH->exec("SET time_zone = "-8:00"");

Metodă ->exec() folosit pentru diverse operatii auxiliare.

$safe = $DBH->quote($nesigur);

Metodă ->citate()șiruri de cote, astfel încât acestea să poată fi utilizate în interogări. Aceasta este rezerva dumneavoastră în cazul în care expresiile pregătite nu sunt folosite.

$rows_afectated = $STH->rowCount();

Metodă ->rowCount() returnează valoarea întreg, indicând numărul de rânduri care sunt procesate de operație. În cea mai recentă versiune de PDO, conform raportului de eroare (http://bugs.php.net/40822), această metodă nu funcționează cu expresii SELECTAȚI. Dacă aveți probleme și nu puteți actualiza PHP, puteți obține numărul de rânduri în felul următor:

$sql = "SELECTARE COUNT(*) FROM folks"; if ($STH = $DBH->query($sql)) ( # Verificați numărul de rânduri dacă ($STH->fetchColumn() > 0) ( # Ar trebui să existe un cod SELECT aici) else ( echo „Există nici un rând care să se potrivească cu interogarea.” ; ) )

Sper că ți-a plăcut lecția!

  • Traducere

Mulți dezvoltatori PHP sunt obișnuiți să folosească extensiile mysql și mysqli pentru a lucra cu baze de date. Dar, începând cu versiunea 5.1 în PHP, există o modalitate mai convenabilă - PHP Data Objects. Această clasă, numită pe scurt PDO, oferă metode de lucru cu obiecte și declarații pregătite care vă vor îmbunătăți semnificativ productivitatea!

Introducere în DOP

„PDO – PHP Data Objects este un strat care oferă o modalitate universală de a lucra cu mai multe baze de date.”

Lasă preocuparea pentru caracteristicile de sintaxă ale diferitelor SGBD-uri în seama dezvoltatorului, dar face procesul de comutare între platforme mult mai puțin dureros. Adesea, aceasta necesită doar schimbarea șirului de conexiune la baza de date.


Acest articol este scris pentru persoanele care folosesc mysql și mysqli pentru a-i ajuta să migreze la PDO mai puternic și mai flexibil.

Suport DBMS

Această extensie poate suporta orice sistem de gestionare a bazelor de date pentru care există un driver PDO. La momentul scrierii, sunt disponibile următoarele drivere:
  • PDO_CUBRID (CUBRID)
  • PDO_DBLIB (FreeTDS / Microsoft SQL Server / Sybase)
  • PDO_FIREBIRD (Firebird/Interbase 6)
  • PDO_IBM (IBM DB2)
  • PDO_INFORMIX (Server dinamic IBM Informix)
  • PDO_MYSQL (MySQL 3.x/4.x/5.x)
  • PDO_OCI (Interfață de apel Oracle)
  • PDO_ODBC (ODBC v3 (IBM DB2, unixODBC și win32 ODBC))
  • PDO_PGSQL (PostgreSQL)
  • PDO_SQLITE (SQLite 3 și SQLite 2)
  • PDO_SQLSRV (Microsoft SQL Server)
  • PDO_4D (4D)
Cu toate acestea, nu toate sunt pe serverul dvs. Puteți vedea lista de drivere disponibile astfel:
print_r(PDO::getAvailableDrivers());

Conexiune

Metodele de conectare la diferite SGBD-uri pot diferi ușor. Mai jos sunt exemple de conectare la cele mai populare. Veți observa că primele trei au sintaxă identică, spre deosebire de SQLite.
încercați ( # MS SQL Server și Sybase prin PDO_DBLIB $DBH = PDO nou ("mssql:host=$host;dbname=$dbname", $user, $pass); $DBH = PDO nou ("sybase:host=$host ;dbname=$dbname", $user, $pass); # MySQL prin PDO_MYSQL $DBH = PDO nou ("mysql:host=$host;dbname=$dbname", $user, $pass); # SQLite $DBH = PDO nou ("sqlite:my/database/path/database.db"); ) catch(PDOException $e) ( echo $e->getMessage(); )
Vă rugăm să acordați atenție blocului try/catch - merită întotdeauna să includeți toate operațiunile dvs. PDO în el și să utilizați mecanismul de excepție (mai multe despre asta mai târziu).

$DBH înseamnă „mânerul bazei de date” și va fi folosit pe tot parcursul articolului.

Puteți închide orice conexiune prin redefinirea variabilei sale la null.
# închide conexiunea $DBH = null;
Mai multe informații despre opțiunile distinctive ale diferitelor SGBD-uri și metodele de conectare la acestea pot fi găsite pe php.net.

Excepții și DOP

PDO poate arunca excepții la erori, așa că totul ar trebui să fie într-un bloc try/catch. Imediat după crearea unei conexiuni, PDO poate fi pus în oricare dintre cele trei moduri de eroare:
$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Dar este de remarcat faptul că o eroare atunci când încercați să vă conectați va arunca întotdeauna o excepție.

PDO::ERRMODE_SILENT

Acesta este modul implicit. Probabil că veți folosi aproximativ același lucru pentru a detecta erorile din extensiile mysql și mysqli. Următoarele două moduri sunt mai potrivite pentru programarea DRY.

PDO::ERRMODE_WARNING

Acest mod va provoca un avertisment standard și va permite scriptului să continue executarea. Convenabil pentru depanare.

PDO::ERRMODE_EXCEPTION

În majoritatea situațiilor, acest tip de control al execuției scriptului este de preferat. Aruncă o excepție, permițându-vă să gestionați în mod inteligent erorile și să ascundeți informațiile sensibile. Ca, de exemplu, aici:
# conectați-vă la baza de date încercați ( $DBH = PDO nou ("mysql:host=$host;dbname=$dbname", $user, $pass); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) ; # La naiba! Am tastat DELECT în loc de SELECT! $DBH->prepare(„DELECT name FROM people”)->execute(); ) catch(PDOException $e) ( echo „Houston, avem o problemă.”; file_put_contents ("PDOErrors .txt", $e->getMessage(), FILE_APPEND); )
Există o eroare de sintaxă în expresia SQL care va arunca o excepție. Putem înregistra detaliile erorii într-un fișier jurnal și putem sugera utilizatorului în limbaj uman că s-a întâmplat ceva.

Inserați și actualizați

Inserarea de date noi și actualizarea datelor existente sunt unele dintre cele mai comune operațiuni ale bazei de date. În cazul DOP, acest proces constă de obicei din două etape. (Secțiunea următoare se referă atât la UPDATE, cât și la INSERT)


Un exemplu banal de inserare de date noi:
# STH înseamnă "Statement Handle" $STH = $DBH->prepare ("INSERT INTO folks (first_name) values ​​​​("Cathy")"); $STH->execute();
De fapt, puteți face același lucru cu o singură metodă exec(), dar metoda în doi pași oferă toate beneficiile instrucțiunilor pregătite. Acestea ajută la protejarea împotriva injecțiilor SQL, așa că este logic să le folosiți chiar și pentru o interogare unică.

Declarații pregătite

Utilizarea instrucțiunilor pregătite întărește protecția împotriva injecțiilor SQL.

O instrucțiune Prepared este o instrucțiune SQL precompilată care poate fi executată în mod repetat prin trimiterea doar a diferitelor seturi de date către server. Un avantaj suplimentar este că este imposibil să se efectueze injecția SQL prin datele utilizate în substituenți.

Mai jos sunt trei exemple de declarații pregătite.
# fără substituenți - ușa către injecțiile SQL este deschisă! $STH = $DBH->prepare("INSERT INTO folks (nume, adresă, oraș) valori ($nume, $adresă, $oraș)"); # substituenți fără nume $STH = $DBH->prepare ("INSERT INTO folks (nume, adresă, oraș) valori (?, ?, ?)"); # substituenți numiți $STH = $DBH->prepare ("INSERT INTO folks (nume, adresă, oraș) valori (:name, :addr, :city)");
Primul exemplu este aici doar pentru comparație și ar trebui evitat. Diferența dintre substituenții fără nume și cei cu nume este modul în care treceți datele către instrucțiunile pregătite.

Substituenți fără nume

# atribuiți variabile fiecărui substituent, cu indici de la 1 la 3 $STH->bindParam(1, $name); $STH->bindParam(2, $adr); $STH->bindParam(3, $oraș); # introduceți o linie $name = "Daniel" $addr = "1 Wicked Way"; $oraș = „Arlington Heights”; $STH->execute(); # introduceți o altă linie, cu date diferite $name = "Steve" $addr = "5 Circle Drive"; $oraș = „Schaumburg”; $STH->execute();
Aici sunt doi pași. Pe primul, atribuim variabile tuturor substituenților (liniile 2-4). Apoi atribuim valori acestor variabile și executăm interogarea. Pentru a trimite un nou set de date, pur și simplu modificați valorile variabilei și rulați din nou cererea.

Dacă expresia dvs. SQL are mulți parametri, atunci alocarea unei variabile fiecăruia este foarte incomod. În astfel de cazuri, puteți stoca datele într-o matrice și le puteți transmite:
# setul de date îl vom introduce $data = array("Cathy", "9 Dark and Twisty Road", "Cardiff"); $STH = $DBH->prepare("INSERT INTO folks (nume, adresa, oraș) valori (?, ?, ?)"); $STH->execute($date);
$data vor fi inserate în locul primului substituent, $data în locul celui de-al doilea etc. Dar aveți grijă: dacă indexurile dvs. sunt încurcate, acest lucru nu va funcționa.

Substituenți numiți

# primul argument este numele substituentului # începe de obicei cu două puncte # deși funcționează fără ele $STH->bindParam(":name", $name);
Aici puteți trece și o matrice, dar trebuie să fie asociativă. Cheile ar trebui să fie, după cum ați putea ghici, numele substituenților.
# datele pe care le introducem $data = array("name" => "Cathy", "addr" => "9 Dark and Twisty", "city" => "Cardiff"); $STH = $DBH->prepare("INSERT INTO folks (nume, adresă, oraș) valori (:name, :addr, :city)"); $STH->execute($date);
Una dintre avantajele utilizării substituenților numiți este abilitatea de a insera obiecte direct în baza de date dacă numele proprietăților se potrivesc cu numele parametrilor. De exemplu, puteți introduce date astfel:
# clasă pentru o persoană de clasă obiect simplă ( public $nume; public $adresă; public $oraș; funcția __construct($n,$a,$c) ( $this->name = $n; $this->addr = $ a ; $this->city = $c; ) # asa mai departe... ) $cathy = new person("Cathy","9 Dark and Twisty","Cardiff"); # și aici este partea interesantă $STH = $DBH->prepare ("INSERT INTO folks (name, addr, city) values ​​​​(:name, :addr, :city)"); $STH->execute((matrice)$cathy);
Convertirea unui obiect într-o matrice în timpul execute() face ca proprietățile să fie tratate ca chei de matrice.

Eșantionarea datelor



Datele pot fi preluate folosind metoda ->fetch(). Înainte de a o apela, este recomandabil să indicați în mod explicit sub ce formă le solicitați. Există mai multe opțiuni:
  • PDO::FETCH_ASSOC: returnează o matrice cu nume de coloane ca chei
  • PDO::FETCH_BOTH (implicit): returnează o matrice cu indecși atât sub formă de nume de coloane, cât și de numere de serie ale acestora
  • PDO::FETCH_BOUND: atribuie valori de coloană variabilelor corespunzătoare specificate folosind metoda ->bindColumn().
  • PDO::FETCH_CLASS: atribuie valori de coloană proprietăților corespunzătoare ale clasei specificate. Dacă nu există nicio proprietate pentru o coloană, aceasta va fi creată
  • PDO::FETCH_INTO: actualizează o instanță existentă a clasei specificate
  • PDO::FETCH_LAZY: combină PDO::FETCH_BOTH și PDO::FETCH_OBJ
  • PDO::FETCH_NUM: returnează o matrice cu chei ca numere de coloană
  • PDO::FETCH_OBJ: returnează un obiect anonim cu proprietăți corespunzătoare numelor de coloană
În practică, veți avea nevoie de obicei de trei: FETCH_ASSOC, FETCH_CLASS și FETCH_OBJ. Pentru a specifica formatul datelor, utilizați următoarea sintaxă:
$STH->setFetchMode(PDO::FETCH_ASSOC);
De asemenea, îl puteți seta direct când apelați metoda ->fetch().

FETCH_ASSOC

Acest format creează o matrice asociativă cu nume de coloane ca indici. Ar trebui să fie familiar celor care folosesc extensiile mysql/mysqli.
# deoarece aceasta este o interogare obișnuită fără substituenți, # puteți utiliza imediat metoda query() $STH = $DBH->query("SELECT name, address, city from folks"); # setați modul de preluare $STH->setFetchMode(PDO::FETCH_ASSOC); while($row = $STH->fetch()) ( echo $row["nume"] . "\n"; echo $row["adresa"] . "\n"; echo $row["oraș"] . "\n"; )
Bucla while() va itera pe întregul rezultat al interogării.

FETCH_OBJ

Acest tip de achiziție de date creează o instanță a clasei std pentru fiecare rând.
# creați o interogare $STH = $DBH->query("SELECT numele, adresa, orașul de la oameni"); # selectați modul de preluare $STH->setFetchMode(PDO::FETCH_OBJ); # tipăriți rezultatul while($row = $STH->fetch()) ( echo $row->name . "\n"; echo $row->adr . "\n"; echo $row->city . " \ n"; )

FETCH_CLASS

Când utilizați fetch_class, datele sunt scrise în instanțe ale clasei specificate. În acest caz, valorile sunt atribuite proprietăților obiectului ÎNAINTE de a apela constructorul. Dacă proprietățile cu nume corespunzătoare numelor de coloane nu există, acestea vor fi create automat (cu domeniul public).

Dacă datele dumneavoastră necesită prelucrare obligatorie imediat după ce sunt primite din baza de date, acestea pot fi implementate în constructorul clasei.

De exemplu, să luăm o situație în care trebuie să ascundeți o parte din adresa de reședință a unei persoane.
clasa persoana_secreta ( public $nume; public $adresa; public $oras; public $alte_date; function __construct($altul = "") ( $this->addr = preg_replace("//", "x", $this-> adresa); $aceasta->alte_date = $altele; ) )
La crearea unui obiect, toate literele latine mici trebuie înlocuite cu x. Sa verificam:
$STH = $DBH->query("SELECT numele, adresa, orasul de la oameni"); $STH->setFetchMode(PDO::FETCH_CLASS, "persoana_secreta"); while($obj = $STH->fetch()) ( echo $obj->addr; )
Dacă adresa din baza de date arată ca „5 Rosebud”, atunci rezultatul va fi „5 Rxxxxxx”.

Desigur, uneori veți dori ca constructorul să fie numit ÎNAINTE de a atribui valori. PDO permite și acest lucru.
$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, „persoană_secretă”);
Acum că ați completat exemplul anterior cu o opțiune suplimentară (PDO::FETCH_PROPS_LATE), adresa nu va fi modificată, deoarece nu se întâmplă nimic după ce valorile sunt scrise.

În cele din urmă, dacă este necesar, puteți transmite argumente direct constructorului atunci când creați obiectul:
$STH->setFetchMode(PDO::FETCH_CLASS, "persoana_secreta", array("lucruri"));
Puteți chiar să transmiteți argumente diferite fiecărui obiect:
$i = 0; while($rowObj = $STH->fetch(PDO::FETCH_CLASS, "secret_person", array($i))) ( // face ceva $i++; )

Alte metode utile

Deși acest articol nu poate (și nu încearcă) să acopere fiecare aspect al lucrului cu PDO (este un modul uriaș!), următoarele câteva caracteristici nu pot fi omise fără mențiuni.
$DBH->lastInsertId();
Metoda ->lastInsertId() returnează id-ul ultimei înregistrări inserate. Este de remarcat faptul că este întotdeauna apelat pe un obiect de bază de date (numit $DBH în acest articol), și nu pe un obiect cu o expresie ($STH).
$DBH->exec("ȘTERGEȚI DE LA oameni de unde 1"); $DBH->exec("SET time_zone = "-8:00"");
Metoda ->exec() este folosită pentru operațiunile care nu returnează alte date decât numărul de înregistrări afectate de acestea.
$safe = $DBH->quote($nesigur);
Metoda ->quote() plasează ghilimele în șir de date, astfel încât să fie sigur să le folosiți în interogări. Util dacă nu folosiți declarații pregătite.
$rows_afectated = $STH->rowCount();
Metoda ->rowCount() returnează numărul de înregistrări care au participat la operație. Din păcate, această funcție nu a funcționat cu interogări SELECT până la PHP 5.1.6. Dacă nu este posibilă actualizarea versiunii PHP, numărul de înregistrări poate fi obținut astfel:
$sql = "SELECTARE COUNT(*) FROM folks"; if ($STH = $DBH->query($sql)) ( # verificați numărul de înregistrări dacă ($STH->fetchColumn() > 0) ( # faceți o selecție completă aici deoarece datele au fost găsite! ) else ( # imprimați un mesaj că nu au fost găsite date care să satisfacă cererea) )

Concluzie

Sper că acest material îi va ajuta pe unii dintre voi să migreze din extensiile mysql și mysqli.