Interogări pregătite și proceduri stocate. Funcții avansate MySQL De ce nu myqli sau mysql












PDO are propria sa metodă de conectare artificială numită . În plus, în timpul conexiunii, puteți seta un nor de rahat de opțiuni, dintre care unele sunt extrem de utile. O listă completă poate fi găsită, dar doar câteva sunt importante.

Exemplu de conexiune corectă:

$gazdă = "127.0.0.1" ;
$db = "test" ;
$utilizator = „rădăcină” ;
$trece = "" ;
$charset = "utf8" ;

$dsn = "mysql:host= $host ;dbname= $db ;charset= $charset " ;
$opt = [
PDO :: ATTR_ERRMODE => PDO :: ERRMODE_EXCEPTION ,
PDO :: ATTR_DEFAULT_FETCH_MODE => PDO :: FETCH_ASSOC ,
PDO::ATTR_EMULATE_PREPARES => false ,
];
$pdo = PDO nou ($dsn , $user , $pass , $opt );

Ce se petrece aici?

$dsn specifică tipul bazei de date cu care se lucrează (mysql), gazda, numele bazei de date și setul de caractere.
- urmat de nume de utilizator și parolă
- după care este specificată o serie de opțiuni, care nu este menționată în niciunul dintre manuale.

În ciuda faptului că această matrice este un lucru extrem de util, așa cum am menționat mai sus. Cel mai important lucru este ca modul de emitere a erorilor să fie setat numai sub formă de excepții.
- În primul rând, pentru că în toate celelalte moduri PDO nu raportează nimic inteligibil despre eroare,
- în al doilea rând, pentru că o excepție conține întotdeauna o urmă de stivă de neînlocuit,
- în al treilea rând - excepțiile sunt extrem de convenabile de tratat.

În plus, este foarte convenabil să setați FETCH_MODE în mod implicit pentru a nu-l scrie în FIECARE solicitare, deoarece hamsterilor harnici le place să facă foarte mult.
Tot aici puteți seta modul pconnect, emularea expresiilor pregătite și multe alte cuvinte înfricoșătoare.

Ca rezultat, obținem variabila $pdo, cu care lucrăm în continuare pe parcursul întregului script.

Puteți folosi două metode pentru a executa interogări.
Dacă nu sunt transmise variabile la interogare, atunci puteți utiliza funcția query(). Acesta va executa cererea și va returna un obiect special - instrucțiunea PDO. Poate fi foarte aproximativ comparat cu resursa mysql returnată de mysql_query(). Puteți obține date de la acest obiect atât în ​​mod tradițional, prin while, cât și prin foreach (). De asemenea, puteți cere să returnați datele primite într-un format special, așa cum este descris mai jos.
$stmt = $pdo -> interogare("SELECT numele de la utilizatori");
while ($row = $stmt -> fetch())
{
}

Dacă cel puțin o variabilă este transmisă cererii, atunci această solicitare trebuie executată fără greșeală numai prin expresii pregătite. Ce este? Aceasta este o interogare SQL obișnuită, în care este plasat un marker 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 = ;
$sql = ;

Pentru a executa o astfel de interogare, aceasta trebuie mai întâi pregătită folosind funcția prepare(). De asemenea, returnează o instrucțiune PDO, dar fără date încă. Pentru a le obține, trebuie să executați această solicitare, după ce i-ați transmis variabile. Îl poți trimite în două moduri:
Cel mai adesea, puteți executa pur și simplu metoda execute(), trecându-i o matrice cu variabile:
$stmt = $pdo -> pregăti( „SELECTează numele FROM utilizatorii WHERE email = ?”);
$stmt -> execute(array($email ));

$stmt = $pdo -> pregăti( „SELECTARE numele de la utilizatori WHERE email = :email”);
$stmt -> execute (array("email" => $email ));
După cum puteți vedea, în cazul substituenților numiți, trebuie trecut un tablou către execute(), în care cheile trebuie să se potrivească cu numele substituenților.

Uneori, foarte rar, a doua metodă poate fi necesară, când variabilele sunt mai întâi legate la cerere pe rând, folosind bindValue() / bindParam(), și apoi doar executate. În acest caz, nu se trece nimic la execute(). Un exemplu poate fi găsit în manual.
Folosind această metodă, ar trebui să fie întotdeauna preferată bindValue()? deoarece comportamentul lui bindParam() nu este evident pentru începători și va duce la probleme.

După aceea, puteți utiliza declarația PDO în aceleași moduri ca mai sus. De exemplu, prin foreach:
$stmt = $pdo -> pregăti( „SELECTează numele FROM utilizatorii WHERE email = ?”);
$stmt ->
foreach ($stmt ca $row )
{
echo $row [ „nume” ] . „\n” ;
}

IMPORTANT: Expresiile pregătite sunt principalul motiv pentru a utiliza DOP așa cum este singura cale sigură executarea de interogări SQL care implică variabile.

De asemenea, prepare() / execute() poate fi folosit pentru a executa în mod repetat o interogare pregătită odată cu diferite seturi de date. În practică, acest lucru este extrem de rar necesar și nu aduce o creștere specială a vitezei. Dar în cazul în care trebuie să faceți multe cereri de același tip, puteți scrie astfel:

$date = matrice(
1 => 1000,
5 => 300,
9 => 200,
);

$stmt = $pdo -> pregăti( "UPDATE utilizatorii SET bonus = bonus + ? WHERE id = ?");
foreach ($date ca $id => $bonus)
{
$stmt -> execute([ $bonus , $id ]);
}

Aici pregătim interogarea o dată și apoi o executăm de mai multe ori.

Am întâlnit deja metoda fetch() de mai sus, care servește la preluarea secvenţială a rândurilor din baza de date. Această metodă este analogă cu funcția mysq_fetch_array() și cu altele similare, dar funcționează diferit: în loc de multe funcții, aici este folosită una, dar comportamentul ei este stabilit de parametrul transmis. Voi scrie mai multe despre aceste opțiuni mai târziu, dar ca un sfat rapid, aș recomanda să utilizați fetch() în modul FETCH_LAZY:
$stmt = $pdo -> pregăti( „SELECTează numele FROM utilizatorii WHERE email = ?”);
$stmt -> execute([ $_GET [ "email" ]]);
while ($rând = $stmt -> preluare (PDO::FETCH_LAZY ))
{
echo $rând [ 0 ] . „\n” ;
echo $row [ „nume” ] . „\n” ;
echo $rând -> nume . „\n” ;
}

În acest mod, nu se irosește memorie suplimentară și, în plus, coloanele pot fi accesate în oricare dintre trei moduri - printr-un index, un nume sau o proprietate.

De asemenea, instrucțiunea PDO are o funcție de ajutor pentru a obține valoarea unei singure coloane. Este foarte convenabil dacă solicităm un singur câmp - în acest caz, cantitatea de scris este redusă semnificativ:
$stmt = $pdo -> pregăti( „SELECTează numele din tabelul WHERE id=?”);
$stmt -> execute(array($id ));
$nume = $stmt -> fetchColumn();

Dar cea mai interesantă funcție, cu cea mai mare funcționalitate, este fetchAll(). Ea este cea care face din PDO o bibliotecă de nivel înalt pentru lucrul cu baza de date, și nu doar un driver de nivel scăzut.

FetchAll() returnează o matrice care conține toate rândurile returnate de interogare. Din care se pot trage două concluzii:
1. Această funcție nu trebuie utilizată atunci când interogarea returnează o mulțime de date. În acest caz, este mai bine să folosiți o buclă tradițională cu fetch()
2. Deoarece în aplicațiile PHP moderne datele nu sunt niciodată afișate imediat după primire, ci sunt transmise șablonului pentru aceasta, fetchAll () devine pur și simplu indispensabil, permițându-vă să nu scrieți cicluri manual și, prin urmare, să reduceți cantitatea de cod.

Obținerea unui tablou simplu.
Apelată fără parametri, această funcție returnează o matrice obișnuită indexată care conține șiruri din baza de date în formatul specificat în FETCH_MODE în mod implicit. Constantele PDO::FETCH_NUM, PDO::FETCH_ASSOC, PDO::FETCH_OBJ pot schimba formatul din mers.

Obțineți o coloană.
Uneori, trebuie să obțineți o matrice simplă unidimensională solicitând un singur câmp dintr-o grămadă de șiruri. Pentru aceasta, se folosește modul PDO::FETCH_COLUMN.
$date = $pdo -> interogare("SELECT numele de la utilizatori" )-> fetchAll(PDO::FETCH_COLUMN );
matrice(
0 => „Ioan” ,
1 => „Mike” ,
2 => „Maria” ,
3 => „Kathy” ,
)

Obțineți perechi cheie-valoare.
De asemenea, un format popular atunci când este de dorit să obțineți aceeași coloană, dar indexată nu după numere, ci după unul dintre câmpuri. Constanta PDO::FETCH_KEY_PAIR este responsabilă pentru acest lucru.
$date = $pdo -> interogare("SELECT ID, nume FROM utilizatori" )-> fetchAll(PDO::FETCH_KEY_PAIR );
matrice(
104 => "Ioan" ,
110
120 => "Maria" ,
121
)

Obțineți toate rândurile indexate după un câmp.
De asemenea, este adesea necesar să obțineți toate rândurile din baza de date, dar și indexate nu după numere, ci printr-un câmp unic. Aceasta este ceea ce face constanta PDO::FETCH_UNIQUE.
$date = $pdo -> query("SELECT * FROM users" )-> fetchAll(PDO::FETCH_UNIQUE );
matrice(
104 => matrice (
"name" => "Ioan" ,
"mașină" => "Toyota" ,
),
110 => matrice (
"name" => "Mike" ,
"car" => "Ford" ,
),
120 => matrice (
"name" => "Maria" ,
"mașină" => "Mazda" ,
),
121 => matrice (
"name" => "Kathy" ,
"mașină" => "Mazda" ,
),
)

Trebuie reținut că primul câmp din coloană trebuie să fie un câmp unic.

În total, există mai mult de o duzină de moduri diferite de obținere a datelor în PDO. În plus, le poți combina! Dar acesta este un subiect pentru un articol separat.

Când lucrați cu expresii pregătite, ar trebui să înțelegeți că un substituent poate înlocui doar un șir sau un număr. Nici un cuvânt cheie, nici un identificator, nici o parte dintr-un șir sau un set de șiruri nu pot fi înlocuite printr-un substituent. 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:

$nume = "% $nume %" ;
$stm = $pdo -> pregăti( "SELECT * FROM tabelul WHERE nume LIKE?");
$stm -> execute(array($nume));
$date = $stm -> fetchAll();

Ei bine, ai înțeles ideea. E rău și aici. PDO nu oferă deloc instrumente pentru lucrul cu identificatorii, iar aceștia trebuie formatați la modă veche, manual (sau priviți, până la urmă, spre SafeMysql , în care acest lucru, ca multe alte probleme, este rezolvat simplu și elegant).
Trebuie reținut că regulile de formatare a identificatorilor diferă pentru diferite baze de date.

În mysql, pentru a formata manual un id, trebuie să faceți două lucruri:
- includeți-l între ghilimele simple din spate (backticks, "`").
- scala aceste caractere în interiorul identificatorului din interior prin dublare.

$câmp = "`" . str_replace ("`" , "``" , $_GET [ "câmp" ]). "`";
$sql = $câmp" ;

Cu toate acestea, există o avertizare aici. Formatarea singură poate să nu fie suficientă. codul de mai sus ne va proteja de injectarea clasică, dar în unele cazuri inamicul poate scrie ceva nedorit dacă înlocuim fără grija numele câmpurilor și tabelelor direct în interogare. De exemplu, există un câmp de administrare în tabelul utilizatori. Dacă numele câmpurilor primite nu sunt filtrate, atunci în acest câmp, atunci când o solicitare este generată automat dintr-un POST, orice prost va nota orice muck.

Prin urmare, numele tabelelor și câmpurilor care provin de la utilizator ar trebui verificate pentru valabilitate, ca în exemplul de mai jos

Orice cod de încorporare care poate fi văzut în numeroase tutoriale inspiră melancolie și dorința de a ucide un supărat. Construcții multikilometrice cu repetarea acelorași nume - în indicii $_POST, în nume de variabile, în nume de câmpuri într-o solicitare, în nume de substituenți într-o cerere, în nume de substituenți și nume de variabile la legare.
Privind acest cod, îmi doresc să omor pe cineva, sau cel puțin să-l fac un pic mai scurt.

Acest lucru se poate face prin adoptarea convenției conform căreia numele câmpurilor din formular se vor potrivi cu numele câmpurilor din tabel. Apoi, aceste nume pot fi listate o singură dată (pentru a vă proteja împotriva înlocuirii menționate mai sus) și utilizați o mică funcție de ajutor pentru a construi interogarea, care, datorită particularităților mysql, este potrivită atât pentru interogările INSERT, cât și pentru UPDATE:

funcția pdoSet ($permis și $valori, $sursă = matrice()) (
$set = "" ;
$valori = matrice();
if (! $sursa ) $sursa = & $_POST ;
foreach ($permis ca $câmp ) (
dacă (isset($sursă [ $câmp])) (
$set .= "`" . str_replace ("`" , "``" , $câmp ). "`" . "=: $câmp , " ;
$valori [ $field ] = $sursa [ $field ];
}
}
return substr ($set , 0 , - 2 );
}

În consecință, pentru a introduce codul va fi

$allowed = array("nume", "nume" , "e-mail"); // câmpuri permise
$sql = "INSERT INTO users SET " . pdoSet($permis, $valori ​​);
$stm = $dbh -> pregăti($sql );
$stm -> execute($valori);

Și pentru actualizare - aceasta:

$allowed = array("nume", "nume" , "e-mail" , "parolă"); // câmpuri permise
$_POST [ „parolă” ] = MD5 ( $_POST [ „login” ]. $_POST [ „parolă” ]);
$sql = "UPDATE users SET " . pdoSet($allowed , $values ​​​​). " WHERE id = :id" ;
$stm = $dbh -> pregăti($sql );
$values["id"] = $_POST["id"];
$stm -> execute($valori);

Nu foarte eficient, dar foarte eficient. Permiteți-mi să vă reamintesc, apropo, că dacă utilizați Clasa pentru a lucra sigur și convenabil cu MySQL, atunci totul se face în două rânduri.

DOP și cuvinte cheie
Aici, în afară de filtrare, este imposibil să te gândești la nimic. prin urmare, este o prostie să rulezi toți operatorii nespecificați direct în cerere prin lista albă:

$dirs = array("ASC" , "DESC" );
$key = array_search($_GET [ "dir" ], $dirs ));
$dir = $comenzi [ $cheie ];
$sql = „SELECT * FROM `table` ORDER BY$câmp $dir" ;

Termen DOP este o abreviere pentru Obiecte de date PHP. După cum sugerează și numele, această tehnologie vă permite să lucrați cu conținutul bazei de date prin intermediul obiectelor.

De ce nu myqli sau mysql?

Cel mai adesea, în ceea ce privește noile tehnologii, se pune întrebarea cu privire la avantajele acestora față de instrumentele bune vechi și dovedite, precum și transferul proiectelor actuale și vechi către acestea.

PDO orientat pe obiect

PHP se dezvoltă foarte activ și își propune să devină unul dintre cele mai bune instrumente pentru dezvoltarea rapidă a aplicațiilor web, atât la nivel de masă, cât și la nivel de întreprindere.

Vorbind despre PHP, vom spune modern orientat pe obiecte PHP, care vă permite să scrieți cod generic care este ușor de testat și reutilizat.

Utilizare DOP vă permite să aduceți munca cu baza de date la nivel orientat pe obiect și să îmbunătățiți portabilitatea codului. De fapt, utilizarea DOP nu atât de dificil pe cât s-ar putea crede.

Abstracția

Imaginează-ți că dezvoltăm o aplicație de mult timp, folosind MySQL. Și apoi, la un moment bun, devine necesară înlocuirea MySQL pe PostgreSQL.

Cel puțin, va trebui să înlocuim toate apelurile mysqli_connect() (mysql_connect()) pe pg_connect()și, prin analogie, alte funcții utilizate pentru interogarea și procesarea datelor.

Folosind DOP, ne vom limita la modificarea cativa parametri din fisierele de configurare.

Legarea parametrilor

Utilizarea parametrilor legați oferă mai multă flexibilitate în interogare și îmbunătățește protecția împotriva SQL injectii.

Obținerea datelor ca obiecte

Cei care deja folosesc ORM(mapping obiect-relațional - mapare obiect-relațională a datelor), de exemplu, Doctrină cunoașteți comoditatea prezentării datelor din tabelele bazei de date ca obiecte. DOP vă permite să primiți date sub formă de obiecte și fără a utiliza ORM.

Extensia mysql nu mai este acceptată

Suport extensie mysql eliminat definitiv din nou PHP 7. Dacă intenționați să migrați proiectul la o versiune nouă PHP, ar trebui să utilizați deja cel puțin mysqli în el. Desigur, este mai bine să începeți să utilizați DOP dacă nu ai făcut-o deja.

Mi se pare că aceste motive sunt suficiente pentru a înclina cântarul spre utilizarea DOP. În plus, nu trebuie să instalați nimic suplimentar.

Verificarea PDO în sistem

Versiuni PHP 5.5și mai sus, de cele mai multe ori, conțin deja o extensie pentru a lucra cu DOP. Pentru a verifica, rulați o comandă simplă în consolă:

php -i | grep "pdo"

Acum să-l deschidem în orice browser și să găsim datele necesare căutând șirul DOP.

Cunoașterea DOP

Procesul de lucru cu DOP nu prea diferit de tradițional. În general, procesul de utilizare DOP arata asa:

  1. Conexiune la baza de date;
  2. Dacă este necesar, pregătirea unei cereri și a parametrilor obligatorii;
  3. Executarea unei cereri.

Conexiune la baza de date

Pentru a vă conecta la baza de date, trebuie să creați un nou obiect DOPși transmiteți-i numele sursei de date, cunoscut și ca DSN.

În general, DSN constă din numele driverului separat prin două puncte de șirul de conexiune specific fiecărui driver DOP.

Pentru MySQL, conexiunea se face astfel:

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

$conexiune = PDO nou( „mysql:host=localhost;dbname=mydb;charset=utf8”, „rădăcină” , „rădăcină” );

În acest caz, DSN conține numele șoferului mysql, specificând gazda (format posibil gazdă=HOSTNAME:PORT), numele bazei de date, codificare, nume de utilizator MySQLși parola lui.

Cereri

Spre deosebire de mysqli_query(), în DOP Există două tipuri de cereri:

  • Rezultatul returnat ( selectați, afișați);
  • Nu returnează niciun rezultat ( introduce, detaliu alte).

În primul rând, să luăm în considerare a doua opțiune.

Executarea interogărilor

Luați în considerare un exemplu de executare a unei interogări folosind un exemplu introduce.

$connection->exec("INSERT INTO users VALUES (1, "somevalue"");

$conexiune -> exec();

Desigur, această interogare returnează numărul de rânduri afectate și îl puteți vedea după cum urmează.

$affectedRows = $connection->exec("INSERT INTO user VALUES (1, "somevalue""); echo $affectedRows;

$affectedRows = $conexiune -> exec( „INSERT INTO users VALUES (1, „somevalue””) ;

echo $afectedRows ;

Obținerea rezultatelor interogării

În caz de utilizare mysqli_query(), codul ar putea fi după cum urmează.

$rezultat = mysql_query("SELECT * FROM utilizatori"); while($row = mysql_fetch_assoc($result)) ( echo $row["id"] . " " . $row["nume"]; )

$rezultat = mysql_query ("SELECT * FROM utilizatori");

în timp ce ($rând = mysql_fetch_assoc ($rezultat) ) (

Pentru DOP, codul va fi mai simplu și mai concis.

foreach($connection->query("SELECT * FROM users") ca $row) ( echo $row["id"] . " " . $row["nume"]; )

foreach ($connection -> query("SELECT * FROM users") ca $row ) (

echo $row [ "id" ] . " " . $row [ "nume" ] ;

Moduri de achizitie a datelor

Ca în mysqli, DOP vă permite să primiți date în diferite moduri. Pentru a determina modul, clasa DOP conţine constantele corespunzătoare.

  • PDO::FETCH_ASSOC- returnează un tablou indexat după numele coloanei din tabelul bazei de date;
  • PDO::FETCH_NUM- returnează un tablou indexat după numărul coloanei;
  • PDO::FETCH_OBJ- returnează un obiect anonim cu nume de proprietate corespunzătoare numelor de coloane. De exemplu, $row->id va conține valoarea din coloana id.
  • PDO::FETCH_CLASS- returnează o nouă instanță a clasei, cu valorile proprietăților corespunzătoare datelor din rândul tabelului. Dacă parametrul este specificat PDO::FETCH_CLASSTYPE(De exemplu PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE), numele clasei va fi determinat din valoarea primei coloane.

Notă: aceasta nu este o listă completă, toate constantele posibile și combinațiile lor sunt disponibile în documentație.

Un exemplu de obținere a unui tablou asociativ:

$statement = $conexiune->interogare("SELECT * FROM utilizatori"); while($row = $statement->fetch(PDO::FETCH_ASSOC)) ( echo $row["id"] . " " . $row["nume"]; )

$statement = $conexiune ->

while ($rând = $statement -> preluare (PDO::FETCH_ASSOC ) ) (

echo $row [ "id" ] . " " . $row [ "nume" ] ;

Notă: Se recomandă să specificați întotdeauna modul de eșantionare, deoarece modul de eșantionare PDO::FETCH_BOTH va necesita de două ori mai multă memorie - de fapt, vor fi create două tablouri, una asociativă și una obișnuită.

Luați în considerare utilizarea modului eșantionare PDO::FETCH_CLASS. Să creăm o clasă utilizator:

clasa Utilizator ( $id protejat; $nume protejat; funcția publică getId() ( return $this->id; ) public function setId($id) ( $this->id = $id; ) funcția publică getName() ( return $this->name; ) funcția publică setName($nume) ($this->name = $nume; ) )

clasa Utilizator

protejat $id ;

protejat $nume ;

funcția publică getId()

returnează $this -> id ;

funcția publică setId ($id)

$acest -> id = $id ;

funcția publică getName()

returnează $acest -> nume ;

funcția public setName ($nume )

$acest -> nume = $nume ;

Acum să selectăm datele și să le afișăm folosind metodele clasei:

$statement = $conexiune->interogare("SELECT * FROM utilizatori"); while($row = $statement->fetch(PDO::FETCH_CLASS, „Utilizator”)) ( echo $row->getId() . " " . $row->getName(); )

$statement = $conexiune -> interogare ("SELECT * FROM users" );

while ($rând = $statement -> preluare (PDO::FETCH_CLASS , „Utilizator”) ) (

echo $row -> getId() . " " . $row -> getName();

Interogări pregătite și legarea parametrilor

Pentru a înțelege esența și toate avantajele legării parametrilor, trebuie să aruncați o privire mai atentă asupra mecanismelor DOP. Când chemat $statement -> interogare() in codul de mai sus, DOP va pregăti o interogare, o va executa și va returna rezultatul.

Când chemat $conexiune -> pregătiți() este creată o interogare pregătită. Interogările pregătite reprezintă capacitatea sistemului de management al bazei de date de a primi un șablon de interogare, de a-l compila și de a-l executa după primirea valorilor variabilelor utilizate în șablon. Motoarele de șabloane funcționează în același mod. inteligentși Crenguţă.

Când chemat $statement -> execute() valorile sunt transmise pentru înlocuire în șablonul de interogare și DBMS execută interogarea. Această acțiune este similară cu apelarea funcției șablon face().

Un exemplu de utilizare a interogărilor pregătite în PHP DOP:

În codul de mai sus, este pregătită o interogare pentru selectarea unei înregistrări cu un câmp id egală cu valoarea care va fi înlocuită :id. În această etapă, SGBD-ul va analiza și compila interogarea, eventual folosind memorarea în cache (în funcție de setări).

Acum trebuie să treceți parametrul lipsă și să executați cererea:

$id = 5; $statement->execute([ ":id" => $id ]);

Beneficiile utilizării parametrilor legați

Poate că, după ce ați analizat cum funcționează interogările pregătite și parametrii asociați, beneficiile utilizării lor devin clare.

DOP oferă o modalitate convenabilă de a scăpa de datele utilizatorului, de exemplu, un astfel de cod nu mai este necesar:

În schimb, are mai mult sens să faci asta:

Puteți chiar să scurtați și mai mult codul utilizând parametri numerotați în loc de cei numiți:

În același timp, utilizarea interogărilor pregătite vă permite să îmbunătățiți performanța atunci când utilizați aceeași interogare șablon de mai multe ori. Eșantion de selecție a cinci utilizatori aleatori din baza de date:

$numberOfUsers = $connection->query("SELECT COUNT(*) FROM users")->fetchColumn(); $utilizatori = ; $statement = $connection->prepare("SELECT * FROM users WHERE id = ? LIMIT 1"); pentru ($i = 1; $i<= 5; $i++) { $id = rand(1, $numberOfUsers); $users = $statement->execute([$id])->fetch(PDO::FETCH_OBJ); )

$numberOfUsers = $conexiune -> interogare ("SELECT COUNT(*) FROM users" ) -> fetchColumn () ;

$utilizatori = ;

pentru ($i = 1; $i<= 5 ; $i ++ ) {

$id = rand (1, $numarDeUtilizatori) ;

$users = $statement -> execute ([ $id ] ) -> preluare (PDO::FETCH_OBJ ) ;

La apelarea unei metode a pregati(), SGBD-ul va analiza și compila interogarea, folosind cacherea dacă este necesar. Mai târziu în ciclu pentru, sunt preluate numai datele cu parametrul specificat. Această abordare vă permite să obțineți date mai rapid, reducând timpul de rulare al aplicației.

La obținerea numărului total de utilizatori din baza de date, a fost utilizată metoda fetchColumn(). Această metodă returnează valoarea unei singure coloane și este utilă atunci când returnează valori scalare, cum ar fi valorile numărătoare, sume, maxime sau minime.

Valori legate și operatorul IN

Adesea, când începem cu DOP, există dificultăți cu operatorul ÎN. De exemplu, să presupunem că utilizatorul introduce mai multe nume separate prin virgule. Intrarea utilizatorului este stocată într-o variabilă $nume.

Majoritatea bazelor de date acceptă conceptul de interogări pregătite. Ce este? Acesta poate fi descris ca un fel de șablon de interogare SQL compilat care va fi rulat de aplicație și configurat cu parametrii de intrare. Interogările pregătite au două avantaje principale:

  • Interogarea trebuie pregătită o dată și apoi poate fi rulată de câte ori este necesar, atât cu aceiași, cât și cu parametri diferiți. Atunci când o interogare este pregătită, SGBD o analizează, compilează și își optimizează planul de execuție. În cazul interogărilor complexe, acest proces poate dura o perioadă semnificativă de timp și poate încetini considerabil aplicația dacă este necesar să se execute interogarea de mai multe ori cu parametri diferiți. Când se utilizează o interogare pregătită, SGBD analizează/compilează/optimizează o interogare de orice complexitate o singură dată, iar aplicația lansează șablonul deja pregătit pentru execuție. Interogările pregătite în acest fel consumă mai puține resurse și rulează mai rapid.
  • Parametrii de interogare pregătiți nu trebuie să fie evadați cu ghilimele; șoferul face acest lucru automat. Dacă aplicația folosește exclusiv interogări pregătite, dezvoltatorul poate fi sigur că nu pot avea loc injecții SQL (totuși, dacă alte părți ale textului de interogare sunt scrise cu caractere fără escape, injecțiile SQL sunt încă posibile; aici vorbim despre parametri).

Interogările pregătite sunt de asemenea utile, deoarece PDO le poate emula dacă driverul bazei de date nu are această funcționalitate. Aceasta înseamnă că o aplicație poate folosi aceeași tehnică de acces la date, indiferent de capacitățile SGBD.

Beispiel #1 Repetarea inserărilor de baze de date folosind interogări pregătite

Numeși valoare, care sunt înlocuite cu pseudovariabilele corespunzătoare:

$stmt = $dbh -> pregăti( „INSERT INTO REGISTRY (nume, valoare) VALORI (:nume, :valoare)”);
$stmt -> bindParam(":nume" , $nume );
$stmt -> bindParam(":value" , ​​​​$value );

// introduceți o linie
$nume = "unul" ;
$valoare = 1 ;
$stmt -> execute();

$nume = „două” ;
$valoare = 2 ;
$stmt -> execute();
?>

Beispiel #2 Repetarea inserărilor de baze de date folosind interogări pregătite

În acest exemplu, o interogare INSERT este executată de 2 ori cu valori diferite Numeși valoare care sunt substituite cu pseudovariabile ? .

$stmt = $dbh -> pregăti( „INSERT INTO REGISTRY (nume, valoare) VALUES (?, ?)”);
$stmt -> bindParam(1 , $nume );
$stmt -> bindParam(2 , $valoare );

// introduceți o linie
$nume = "unul" ;
$valoare = 1 ;
$stmt -> execute();

// acum un alt șir cu valori diferite
$nume = „două” ;
$valoare = 2 ;
$stmt -> execute();
?>

Beispiel #3 Preluarea datelor folosind interogări pregătite

În acest exemplu, se face o selecție din baza de date prin cheia pe care utilizatorul o introduce prin formular. Intrarea utilizatorului este cotată automat, astfel încât nu există riscul de injectare SQL.

Dacă DBMS acceptă parametrii de ieșire, aplicația îi poate folosi, precum și parametrii de intrare. Parametrii de ieșire sunt utilizați de obicei pentru a prelua date din procedurile stocate. Utilizarea parametrilor de ieșire este oarecum mai complicată, deoarece dezvoltatorul trebuie să cunoască dimensiunea maximă a valorilor extrase în etapa de setare a acestor parametri. Dacă valoarea regăsită este mai mare decât cea așteptată, va fi generată o eroare.

Beispiel #4 Apelarea unei proceduri stocate fără parametri

$stmt = $dbh -> prepare("CALL sp_returns_string(?)" );
$stmt -> bindParam(1 , $return_value , PDO :: PARAM_STR , 4000 );

// apelarea unei proceduri stocate
$stmt -> execute();

imprimare „procedura returnată$return_value\n" ;
?>

Puteți seta parametrul în același timp de intrare și de ieșire; sintaxa este aceeași ca și pentru parametrii de ieșire. În exemplul următor, șirul „hello” este transmis unei proceduri stocate, iar apoi acel șir va fi înlocuit cu valoarea returnată.

Exemplul #5 Apelarea unei proceduri stocate cu un parametru de intrare/ieșire

$stmt = $dbh -> pregăti( „Apelați sp_takes_string_returns_string(?)”);
$valoare = "(!LANG:bună ziua" ;!}
$stmt -> bindParam(1 , $valoare , PDO :: PARAM_STR | PDO :: PARAM_INPUT_OUTPUT , 4000 );

// apelarea unei proceduri stocate
$stmt -> execute();

imprimare „procedura returnată$valoare\n" ;
?>

(matrice("% $_GET [ nume ] %" ));
?>

În acest articol final, ne vom uita la, care sunt interogările pregătite, cum să captezi erorileși ce sunt tranzacțiile în DOP.

Interogări pregătite

Atunci când executăm o interogare de bază de date, aceasta este analizată și optimizată, ceea ce în mod natural necesită timp. Dacă avem o mulțime de interogări complexe, atunci acest lucru poate dura foarte mult timp. Folosind la fel interogări pregătite, acest lucru se face o dată și apoi putem folosi interogarea noastră de câte ori vrem. De asemenea, nu trebuie să scăpăm de parametri, deoarece driverul bazei de date va face totul singur. Să vedem cum să le folosim.

$stmt = $db->prepare("INSERT INTO articles (titlu, text) VALUES (:title, :text)");
$stmt->bindParam(":titlu", $titlu);
$stmt->bindParam(":text", $text);



$stmt->execute();



$stmt->execute();

Pentru a pregăti o cerere, o scriem în metodă a pregati, unde în loc de valori specificăm o linie ca aceasta: ":titlu". In metoda bindParam specificăm la ce linie ce date se leagă. În cazul nostru, la linie :titlu date obligatorii de la o variabilă $titlu, și la linie :text- date dintr-o variabilă $text. Pentru a executa o solicitare, trebuie să apelați metoda a executa. Se numesc astfel de parametri numit, acum uită-te la anonim.

$stmt = $db->prepare("INSERT INTO articles (titlu, text) VALUES (?, ?)");
$stmt->bindParam(1, $titlu);
$stmt->bindParam(2, $text);

$title = "(!LANG:titlul articolului 1";!}
$text = "Un text pentru primul articol";
$stmt->execute();

$title = "(!LANG:titlul articolului 2";!}
$text = "Un text pentru al doilea articol";
$stmt->execute();

Aici totul este identic, cu excepția faptului că în loc de linie :titlu este indicat un semn de întrebare, iar în metodă bindParam număr 1 mijloace primul semnul întrebării și numărul 2 - al doilea semnul întrebării. Folosiți cum vă place mai mult.

Captarea erorilor

Pentru a detecta erori, folosim construcția familiară încearcă să prinzi si clasa PDOException.

Încerca(
$db = PDO nou ("myql:host=$host;dbname=$dbname", $user, $pass);
) catch(PDOException $e) (
echo „Ai o eroare: „.$e->getMessage().”
";
echo "Online: ".$e->getLine();
}

De exemplu, am făcut o greșeală și am scris mysql, dar nu mysql. Această eroare va fi prinsă și vom afișa textul acesteia și pe ce linie a apărut eroarea.

Tranzacții

sa luam in considerare tranzactii chiar pe exemplu.

Încerca(
$db = PDO nou ("mysql:host=$host;dbname=$dbname", $user, $pass);
$db->beginTransaction();

$stmt = $db->exec("INSERT INTO `articles`(`title`) VALUES("title1")");
$stmt = $db->exec("INSERT INTO `articles`(`title`) VALUES("title2")");
ieșire(„eroare”);

$stmt = $db->exec("INSERT INTO `articles`(`title`) VALUES("title3")");
$db->commit();

) catch(PDOException $e) (
$db->rollBack();
}

startTransactionînseamnă că începem o tranzacție. Angajează-te confirmă modificările și rollback anulează totul.

Esența tranzacțiilor este că fie facem totul, fie nu facem nimic. În exemplul nostru, inserăm în tabel articole valorile titlul 1, titlul2, titlu 3. Dar după ce am inserat a doua valoare, am simulat o eroare oprind scriptul cu Ieșire. Dacă nu am folosi tranzactii, atunci avem primele două titlu ar fi introdus, dar acesta din urmă nu este. În exemplul nostru, acest lucru nu este esențial, dar există momente în care acest lucru poate duce la blocări grave în aplicație. Pentru a preveni acest lucru, folosim tranzactii, unde metoda rollback va readuce totul la forma sa originală și primele noastre două titlu nici nu se va introduce, iar dacă totul a mers bine, fără erori, atunci metoda comite va confirma modificările și toate trei titlu va fi introdus cu succes.

Concluzie

Deci, în cele trei articole ale noastre despre învăţarea DOP, am acoperit tot ce aveți nevoie pentru a utiliza această interfață cu ușurință. Cred că înțelegi cum DOP ne face viața mai ușoară și o vom folosi în proiectele tale. Noroc!

Ți-a plăcut articolul? Impartasiti cu prietenii!