pdo metode. Zašto biste trebali koristiti PDO za pristup bazama podataka? Obrada rezultata, FETCH i FETCHALL metode

Termin PDO je skraćenica za koncept PHP objekti podataka. Kao što ime govori, ova tehnologija vam omogućava rad sa sadržajem baze podataka kroz objekte.

Zašto ne myqli ili mysql?

Najčešće se, kada se radi o novim tehnologijama, postavlja pitanje njihovih prednosti u odnosu na stare dobre i provjerene alate, kao i prijenos postojećih i starih projekata na njih.

Objektna orijentacija PDO

PHP Vrlo se aktivno razvija i nastoji da postane jedan od najboljih alata za brzi razvoj web aplikacija, kako na masovnom tako i na korporativnom nivou.

Pričamo o tome PHP, mislimo na moderan objektno orijentisan PHP, što vam omogućava da napišete univerzalni kod koji je pogodan za testiranje i ponovnu upotrebu.

Upotreba PDO omogućava vam da premjestite rad baze podataka na objektno orijentiranu razinu i poboljšate prenosivost koda. U stvari, upotreba PDO nije tako teško kao što se misli.

Apstrakcija

Zamislimo da već dugo razvijamo aplikaciju koristeći MySQL. A onda, u jednom lijepom trenutku, postaje potrebno zamijeniti MySQL on PostgreSQL.

U najmanju ruku, morat ćemo zamijeniti sve pozive mysqli_connect() (mysql_connect()) on pg_connect() i, po analogiji, druge funkcije koje se koriste za upite i obradu podataka.

Koristeći PDO, ograničit ćemo se na promjenu nekoliko parametara u konfiguracijskim datotekama.

Vezivanje parametara

Korištenje povezanih parametara pruža veću fleksibilnost u dizajnu upita i poboljšava zaštitu od SQL injekcije.

Primanje podataka kao objekata

Oni koji već koriste ORM(objektno-relacijsko mapiranje - objektno-relacijsko mapiranje podataka), na primjer, Doktrina, poznaju pogodnost predstavljanja podataka iz tabela baze podataka u obliku objekata. PDO omogućava primanje podataka u obliku objekata i bez upotrebe ORM.

Mysql ekstenzija više nije podržana

Podrška za proširenje mysql trajno uklonjeno iz novog PHP 7. Ako planirate migrirati projekat na novu verziju PHP, trebali biste sada koristiti barem mysqli u njemu. Naravno, bolje je početi koristiti PDO ako to već niste učinili.

Čini mi se da su ovi razlozi dovoljni da preokrenu vagu u korist upotrebe PDO. Štaviše, ne morate instalirati ništa dodatno.

Provjera prisustva PDO u sistemu

Verzije PHP 5.5 i viši, najčešće, već sadrže ekstenziju za rad PDO. Da provjerite, samo pokrenite jednostavnu naredbu u konzoli:

php -i | grep "pdo"

Sada ga otvorimo u bilo kojem pregledniku i pronađimo potrebne podatke pretraživanjem po redu PDO.

Upoznavanje sa PDO

Proces rada sa PDO ne razlikuje se previše od tradicionalnog. Općenito, proces korištenja PDO izgleda ovako:

  1. Povežite se sa bazom podataka;
  2. Ako je potrebno, pripremite zahtjev i parametre veze;
  3. Izvršavanje zahtjeva.

Povezivanje na bazu podataka

Da biste se povezali sa bazom podataka potrebno je kreirati novi objekat PDO i proslijedite mu ime izvora podataka, također poznatog kao DSN.

Uglavnom, DSN sastoji se od imena drajvera odvojenog dvotočkom od niza veze specifičnog za svaki drajver PDO.

Za MySQL, veza se vrši ovako:

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

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

U ovom slučaju, DSN sadrži ime drajvera mysql, indikacija hosta (mogući format host=HOST_NAME:PORT), naziv baze podataka, kodiranje, korisničko ime MySQL i njegovu lozinku.

Zahtjevi

Za razliku od mysqli_query(), V PDO postoje dvije vrste zahtjeva:

  • Vraćanje rezultata ( izaberite, prikažite);
  • Ne vraća rezultat ( insert, detalj i drugi).

Prije svega, razmotrimo drugu opciju.

Izvršavanje upita

Pogledajmo primjer izvršavanja zahtjeva koristeći primjer insert.

$connection->exec("INSERT INTO korisničke VRIJEDNOSTI (1, "somevalue"");

$connection -> exec () ;

Naravno, ovaj upit vraća broj zahvaćenih redova i možete ga vidjeti na sljedeći način.

$affectedRows = $connection->exec("INSERT U korisničke VRIJEDNOSTI (1, "somevalue""); echo $affectedRows;

$affectedRows = $connection -> exec ( "INSERT U korisničke VRIJEDNOSTI (1, "neka vrijednost"") ;

echo $affectedRows ;

Dobivanje rezultata upita

U slučaju upotrebe mysqli_query(), kod bi mogao biti sljedeći.

$result = mysql_query("SELECT * FROM users"); while($row = mysql_fetch_assoc($result)) ( echo $row["id"] . " " . $row["name"]; )

$result = mysql_query ("SELECT * FROM users" ) ;

dok ($row = mysql_fetch_assoc ($result) ) (

Za PDO, kod će biti jednostavniji i sažetiji.

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

foreach ($connection -> query ("SELECT * FROM users") kao $red ) (

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

Načini prikupljanja podataka

Kao u mysqli, PDO omogućava primanje podataka na različite načine. Za određivanje načina rada, klase PDO sadrži odgovarajuće konstante.

  • PDO::FETCH_ASSOC— vraća niz indeksiran imenom kolone u tabeli baze podataka;
  • PDO::FETCH_NUM— vraća niz indeksiran brojem kolone;
  • PDO::FETCH_OBJ- vraća anonimni objekat sa imenima svojstava koja odgovaraju imenima kolona. Na primjer, $row->id će sadržavati vrijednost iz kolone id.
  • PDO::FETCH_CLASS— vraća novu instancu klase, sa vrijednostima svojstava koje odgovaraju podacima iz reda tabele. Ako je parametar specificiran PDO::FETCH_CLASSTYPE(Na primjer PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE), ime klase će se odrediti iz vrijednosti prve kolone.

Bilješka: Ovo nije potpuna lista svih mogućih konstanti i njihove kombinacije su dostupne u dokumentaciji.

Primjer dobivanja asocijativnog niza:

$statement = $connection->query("SELECT * FROM users"); while($row = $statement->fetch(PDO::FETCH_ASSOC)) ( echo $row["id"] . " " . $row["name"]; )

$statement = $veza ->

dok ($red = $naredba -> dohvati (PDO::FETCH_ASSOC) ) (

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

Bilješka: Preporučuje se da uvijek navedete način uzorkovanja jer je način PDO::FETCH_BOTHće zahtijevati duplo više memorije - u stvari, biće kreirana dva niza, asocijativna i regularna.

Razmislite o korištenju načina uzorkovanja PDO::FETCH_CLASS. Hajde da napravimo klasu Korisnik:

klasa Korisnik ( zaštićen $id; zaštićeno $name; javna funkcija getId() (vrati $this->id; ) javna funkcija setId($id) ( $this->id = $id; ) javna funkcija getName() ( vrati $this->name ) javna funkcija setName($name) ( $this->name = $name; ) )

class User

zaštićeni $id ;

zaštićeno $name ;

javna funkcija getId()

vrati $this -> id;

javna funkcija setId ($id)

$this -> id = $id ;

javna funkcija getName()

vrati $this -> name ;

javna funkcija setName ($name)

$this -> name = $name ;

Sada odaberimo podatke i prikažimo podatke koristeći metode klase:

$statement = $connection->query("SELECT * FROM users"); while($row = $statement->fetch(PDO::FETCH_CLASS, "Korisnik")) ( echo $row->getId() . " " . $row->getName(); )

$statement = $connection -> upit ("SELECT * FROM users" ) ;

dok ($red = $naredba -> dohvati (PDO::FETCH_CLASS, "Korisnik") ) (

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

Pripremljeni upiti i vezanje parametara

Da biste razumjeli suštinu i sve prednosti povezivanja parametara, morate detaljnije pogledati mehanizme PDO. Prilikom poziva $statement -> query() u kodu iznad, PDOće pripremiti zahtjev, izvršiti ga i vratiti rezultat.

Prilikom poziva $connection -> pripremi() kreiran je pripremljeni zahtjev. Pripremljeni upiti su sposobnost sistema za upravljanje bazom podataka da primi predložak upita, prevede ga i izvrši nakon preuzimanja vrijednosti varijabli korištenih u predlošku. Predlošci rade na sličan način. Pametno I Grančica.

Prilikom poziva $statement -> execute() vrijednosti za zamjenu se prenose u predložak upita i DBMS izvršava upit. Ova radnja je slična pozivanju funkcije predloška render().

Primjer korištenja pripremljenih upita u PHP PDO:

U kodu iznad je pripremljen zahtjev za odabir zapisa sa poljem id jednaka vrijednosti koja će biti zamijenjena : id. U ovoj fazi, DBMS će analizirati i kompajlirati zahtjev, po mogućnosti korištenjem keširanja (ovisno o postavkama).

Sada morate proslijediti parametar koji nedostaje i izvršiti zahtjev:

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

Prednosti korištenja povezanih parametara

Možda nakon pregleda kako pripremljeni upiti funkcionišu i pridruženih parametara, prednosti njihovog korištenja postaju očigledne.

PDO pruža zgodan način za izbjegavanje korisničkih podataka, na primjer, kod poput ovog više nije potreban:

Umjesto toga, sada je preporučljivo učiniti sljedeće:

Možete čak i dodatno skratiti kod koristeći numerirane parametre umjesto imenovanih:

U isto vrijeme, korištenje pripremljenih upita poboljšava performanse kada se isti predložak upita više puta koristi. Primjer odabira pet slučajnih korisnika iz baze podataka:

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

$numberOfUsers = $connection -> upit ("SELECT COUNT(*) FROM users" ) -> fetchColumn () ;

$users = ;

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

$id = rand(1, $numberOfUsers);

$users = $naredba -> izvršiti ([ $id ] ) -> dohvatiti (PDO::FETCH_OBJ) ;

Prilikom pozivanja metode pripremiti(), DBMS će analizirati i kompajlirati zahtjev, koristeći keširanje ako je potrebno. Kasnije u ciklusu za, uzorkuju se samo podaci sa navedenim parametrom. Ovaj pristup vam omogućava brže preuzimanje podataka, smanjujući vrijeme rada aplikacije.

Prilikom dobivanja ukupnog broja korisnika u bazi podataka korištena je metoda dohvatiColumn(). Ova metoda dohvaća vrijednost jedne kolone i korisna je pri preuzimanju skalarnih vrijednosti kao što su broj, zbroj, maksimalne ili minimalne vrijednosti.

Vezane vrijednosti i IN operator

Često, kada počnete da radite sa PDO, javljaju se poteškoće kod operatera IN. Na primjer, zamislite da korisnik unese nekoliko imena odvojenih zarezima. Korisnički unos se pohranjuje u varijablu $name.

Veza sa bazom podataka se postavlja kada se kreira instanca PDO klase. Nije važno koji drajver odaberete; Uvijek ćete morati koristiti PDO klasu. Njegov konstruktor prihvata parametre za određivanje izvora baze podataka (poznatog kao DSN) i opcione parametre za korisničko ime i lozinku.

Veza na MySQL:

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

Ako dođe do bilo kakve greške u povezivanju, bit će izbačen izuzetak: objekt klase PDOException. Možete ga uhvatiti ako želite riješiti ovu situaciju, ili ga možete ostaviti za globalni obrađivač izuzetaka, koji je postavljen preko set_exception_handler().

Rukovanje greškama u vezi:

pokušajte ( $dbh = novi PDO("mysql:host=localhost;dbname=test", $user, $pass); foreach($dbh->query('SELECT * from FOO') kao $row) ( print_r($ row ) $dbh = null ) catch (PDOException $e) ("Greška! To je to. Evo nas... ".$e->getMessage());

pažnja: Ako ne uhvatite izuzetak koji je izbacio PDO konstruktor, podrazumevana radnja koju preduzima zend motor je da zaustavi skriptu i prikaže povratni trag. Ovo sranje će otkriti sve vaše intimne detalje komunikacije sa bazom podataka. To je će prikazati detaljne detalje veze sa bazom podataka uključujući korisničko ime i lozinku! Na vama je da uhvatite ovaj izuzetak, bilo eksplicitno (putem izjave pokušaj uhvatiti), ili implicitno putem set_exception_handler().

Jednom kada je veza s bazom podataka uspješna, ona ostaje aktivna za cijeli život instance PDO objekta. Da biste zatvorili vezu, morate uništiti objekt, osiguravajući da su sve preostale reference na njega uklonjene - to se može učiniti dodjeljivanjem vrijednosti NULL varijabli koja sadrži objekt. Ako to ne učinite eksplicitno, PHP će automatski zatvoriti vezu kada skripta izađe.

Zatvaranje veze:

$dbh = novi PDO("mysql:host=localhost;dbname=test", $user, $pass); // Nešto radimo ovdje: ... // A sada, pažnja: kraj veze! $dbh = null;

Mnoge web aplikacije imaju koristi od stvaranja trajnih veza sa serverima baze podataka. Trajne veze se ne zatvaraju kada skripta izađe, već se keširaju i ponovo koriste kada druga skripta zatraži veze koristeći iste vjerodajnice za vezu. Stalna keš memorija veze izbjegava troškove uspostavljanja nove veze svaki put kada skripta treba da komunicira sa bazom podataka, što rezultira bržim radom web aplikacija.

Postavljanje trajne veze:

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

Imajte na umu: Ako želite da koristite trajnu vezu, morate podesiti PDO::ATTR_PERSISTENT u nizu opcija drajvera, koji se prosleđuje konstruktoru klase PDO. Postavljanjem ovog atributa putem PDO::setAttribute() nakon instanciranja objekta, upravljački program neće koristiti trajne veze. Takođe, u ovom slučaju nećete moći proširiti klasu PDOStatement za neke svoje potrebe, tj. neće biti moguće instalirati: PDO::ATTR_STATEMENT_CLASS

  • Prevod

Mnogi PHP programeri su navikli da koriste mysql i mysqli ekstenzije za rad sa bazama podataka. Ali od verzije 5.1 u PHP-u postoji pogodniji način - PHP Data Objects. Ova klasa, skraćeno nazvana PDO, pruža metode za rad sa objektima i pripremljenim iskazima koji će značajno poboljšati vašu produktivnost!

Uvod u PDO

“PDO – PHP Data Objects je sloj koji nudi univerzalan način rada sa više baza podataka.”

To prepušta brigu o sintaktičkim karakteristikama različitih DBMS-ova programeru, ali čini proces prebacivanja između platformi mnogo manje bolnim. Često ovo zahtijeva samo promjenu niza povezivanja baze podataka.


Ovaj članak je napisan za ljude koji koriste mysql i mysqli kako bi im pomogli da pređu na moćniji i fleksibilniji PDO.

DBMS podrška

Ovo proširenje može podržati bilo koji sistem upravljanja bazom podataka za koji postoji PDO drajver. U vrijeme pisanja, dostupni su sljedeći drajveri:
  • PDO_CUBRID (CUBRID)
  • PDO_DBLIB (FreeTDS / Microsoft SQL Server / Sybase)
  • PDO_FIREBIRD (Firebird/Interbase 6)
  • PDO_IBM (IBM DB2)
  • PDO_INFORMIX (IBM Informix Dynamic Server)
  • PDO_MYSQL (MySQL 3.x/4.x/5.x)
  • PDO_OCI (Oracle Call Interface)
  • 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)
Međutim, nisu svi na vašem serveru. Listu dostupnih drajvera možete vidjeti ovako:
print_r(PDO::getAvailableDrivers());

Veza

Metode povezivanja na različite DBMS-ove mogu se neznatno razlikovati. Ispod su primjeri povezivanja s najpopularnijim. Primijetit ćete da prva tri imaju identičnu sintaksu, za razliku od SQLite-a.
pokušajte ( # MS SQL Server i Sybase preko PDO_DBLIB $DBH = novi PDO("mssql:host=$host;dbname=$dbname", $user, $pass); $DBH = novi PDO("sybase:host=$host ;dbname=$dbname", $user, $pass); # MySQL preko PDO_MYSQL $DBH = novi PDO("mysql:host=$host;dbname=$dbname", $user, $pass); # SQLite $DBH = novi PDO("sqlite:my/database/path/database.db" catch(PDOException $e) ( echo $e->getMessage(); )
Obratite pažnju na blok try/catch - uvijek je vrijedno umotati sve vaše PDO operacije u njega i koristiti mehanizam izuzetaka (više o tome kasnije).

$DBH je skraćenica za “database handle” i koristit će se u cijelom članku.

Možete zatvoriti bilo koju vezu redefiniranjem njene varijable na null.
# zatvara vezu $DBH = null;
Više informacija o karakterističnim opcijama različitih DBMS-ova i metodama povezivanja na njih možete pronaći na php.net.

Izuzeci i PDO

PDO može baciti izuzetke na greške, tako da bi sve trebalo biti u bloku try/catch. Odmah nakon kreiranja veze, PDO se može staviti u bilo koji od tri načina greške:
$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Ali vrijedi napomenuti da će greška prilikom pokušaja povezivanja uvijek izazvati izuzetak.

PDO::ERRMODE_SILENT

Ovo je zadani način rada. Vjerovatno ćete koristiti otprilike istu stvar da uhvatite greške u mysql i mysqli ekstenzijama. Sljedeća dva načina su pogodnija za DRY programiranje.

PDO::ERRMODE_WARNING

Ovaj način će uzrokovati standardno upozorenje i omogućiti skriptu da nastavi s izvršavanjem. Pogodno za otklanjanje grešaka.

PDO::ERRMODE_EXCEPTION

U većini situacija, ova vrsta kontrole izvršavanja skripte je poželjnija. Izbacuje izuzetak, omogućavajući vam da pametno rukujete greškama i sakrijete osjetljive informacije. Kao, na primjer, ovdje:
# pokušajte povezati se sa bazom podataka ( $DBH = novi PDO("mysql:host=$host;dbname=$dbname", $user, $pass); $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) # Prokletstvo ukucao sam DELECT umjesto SELECT ("DELECT name FROM people") -> execute() catch(PDOException) (echo "Houston, imamo probleme."); "PDOErrors" .txt", $e->getMessage(), FILE_APPEND); )
Postoji sintaksička greška u SQL izrazu koja će baciti izuzetak. Možemo zabilježiti detalje greške u log fajlu i nagovijestiti korisniku na ljudskom jeziku da se nešto dogodilo.

Umetanje i ažuriranje

Umetanje novih podataka i ažuriranje postojećih podataka neke su od najčešćih operacija baze podataka. U slučaju PDO, ovaj proces se obično sastoji od dva koraka. (Sljedeći odjeljak je sve o UPDATE i INSERT)


Trivijalan primjer umetanja novih podataka:
# STH znači "Statement Handle" $STH = $DBH->prepare("INSERT INTO folks (first_name) values" ("Cathy")"); $STH->izvrši();
Zapravo, možete učiniti istu stvar s jednom exec() metodom, ali metoda u dva koraka daje sve prednosti pripremljenih izjava. Pomažu u zaštiti od SQL injekcija, pa ih ima smisla koristiti čak i za jednokratni upit.

Pripremljene izjave

Korištenje pripremljenih izjava jača zaštitu od SQL injekcija.

Prepared izraz je unaprijed kompajlirani SQL izraz koji se može izvoditi više puta slanjem samo različitih skupova podataka na poslužitelj. Dodatna prednost je to što je nemoguće izvršiti SQL injekciju kroz podatke koji se koriste u rezerviranim mjestima.

U nastavku su tri primjera pripremljenih izjava.
# bez rezerviranih mjesta - vrata za SQL injekcije su otvorena! $STH = $DBH->prepare("INSERT INTO folks (ime, addr, city) vrijednosti ($name, $addr, $city)"); # neimenovani čuvari mjesta $STH = $DBH->prepare("INSERT INTO folks (ime, addr, city) vrijednosti (?, ?, ?)"); # imenovani čuvari mjesta $STH = $DBH->prepare("INSERT INTO folks (name, addr, city) vrijednosti (:name, :addr, :city)");
Prvi primjer je ovdje samo radi poređenja i treba ga izbjegavati. Razlika između bezimenih i imenovanih čuvara mjesta je u tome kako prosljeđujete podatke pripremljenim izjavama.

Neimenovani čuvari mjesta

# dodjeljuje varijable svakom čuvaru mjesta, sa indeksima od 1 do 3 $STH->bindParam(1, $name); $STH->bindParam(2, $addr); $STH->bindParam(3, $city); # umetnite jedan red $name = "Daniel" $addr = "1 Wicked Way"; $city = "Arlington Heights"; $STH->izvrši(); # umetnite drugi red, sa drugačijim podacima $name = "Steve" $addr = "5 Circle Drive"; $city = "Schaumburg"; $STH->izvrši();
Ovdje postoje dva koraka. Na prvom, dodeljujemo varijable svim čuvarima mesta (redovi 2-4). Zatim ovim varijablama dodjeljujemo vrijednosti i izvršavamo upit. Da biste poslali novi skup podataka, jednostavno promijenite vrijednosti varijabli i ponovo pokrenite zahtjev.

Ako vaš SQL izraz ima mnogo parametara, tada je dodjeljivanje varijable svakom vrlo nezgodno. U takvim slučajevima možete pohraniti podatke u niz i proslijediti ih:
# skup podataka koji ćemo umetnuti $data = array("Cathy", "9 Dark and Twisty Road", "Cardiff"); $STH = $DBH->prepare("INSERT INTO ljudi (ime, adresa, grad) vrijednosti (?, ?, ?)"); $STH->izvrši($data);
$data će biti umetnuta umjesto prvog čuvara mjesta, $data umjesto drugog, itd. Ali budite oprezni: ako su vam indeksi pokvareni, ovo neće raditi.

Imenovani čuvari mjesta

# prvi argument je ime čuvara mjesta # obično počinje dvotočkom # iako radi bez njih $STH->bindParam(":name", $name);
Ovdje također možete proslijediti niz, ali on mora biti asocijativan. Ključevi bi trebali biti, kao što možete pretpostaviti, imena čuvara mjesta.
# podaci koje ubacujemo $data = array("name" => "Cathy", "addr" => "9 Dark and Twisty", "city" => "Cardiff"); $STH = $DBH->prepare("INSERT INTO folks (ime, addr, city) vrijednosti (:name, :addr, :city)"); $STH->izvrši($data);
Jedna od pogodnosti korištenja imenovanih čuvara mjesta je mogućnost umetanja objekata direktno u bazu podataka ako se imena svojstava podudaraju s imenima parametara. Na primjer, možete umetnuti podatke ovako:
# klasa za jednostavnu klasu objekata person ( public $name; public $addr; public $city; function __construct($n,$a,$c) ( $this->name = $n; $this->addr = $ a $this->city = $c ) # tako dalje... ) $cathy = new person("Cathy","9 Dark and Twisty","Cardiff"); # i evo zanimljivog dijela $STH = $DBH->prepare("INSERT INTO folks (ime, addr, city) vrijednosti (:name, :addr, :city)"); $STH->execute((niz)$cathy);
Konvertovanje objekta u niz tokom execute() uzrokuje da se svojstva tretiraju kao ključevi niza.

Uzorkovanje podataka



Podaci se mogu preuzeti pomoću metode ->fetch(). Pre nego što ih pozovete, preporučljivo je da eksplicitno naznačite u kom obliku su vam potrebni. Postoji nekoliko opcija:
  • PDO::FETCH_ASSOC: vraća niz sa imenima kolona kao ključevima
  • PDO::FETCH_BOTH (zadano): vraća niz sa indeksima u obliku naziva kolona i njihovih serijskih brojeva
  • PDO::FETCH_BOUND: dodjeljuje vrijednosti stupaca odgovarajućim varijablama navedenim pomoću metode ->bindColumn().
  • PDO::FETCH_CLASS: dodjeljuje vrijednosti stupaca odgovarajućim svojstvima navedene klase. Ako ne postoji svojstvo za neki stupac, biće kreirano
  • PDO::FETCH_INTO: ažurira postojeću instancu navedene klase
  • PDO::FETCH_LAZY: kombinuje PDO::FETCH_BOTH i PDO::FETCH_OBJ
  • PDO::FETCH_NUM: vraća niz sa ključevima kao brojevima kolona
  • PDO::FETCH_OBJ: vraća anonimni objekat sa svojstvima koja odgovaraju imenima kolona
U praksi će vam obično trebati tri: FETCH_ASSOC, FETCH_CLASS i FETCH_OBJ. Da biste naveli format podataka, koristite sljedeću sintaksu:
$STH->setFetchMode(PDO::FETCH_ASSOC);
Možete ga postaviti i direktno kada pozivate metodu ->fetch().

FETCH_ASSOC

Ovaj format kreira asocijativni niz sa imenima kolona kao indeksima. To bi trebalo biti poznato onima koji koriste mysql/mysqli ekstenzije.
# pošto je ovo običan upit bez čuvara mjesta, # možete odmah koristiti query() metodu $STH = $DBH->query("IZABIR ime, adresa, grad od ljudi"); # postavlja način preuzimanja $STH->setFetchMode(PDO::FETCH_ASSOC); while($row = $STH->fetch()) ( echo $row["name"] . "\n"; echo $row["addr"] . "\n"; echo $row["city"] "\n" ;
while() petlja će iterirati cijeli rezultat upita.

FETCH_OBJ

Ova vrsta akvizicije podataka kreira instancu std klase za svaki red.
# kreiraj upit $STH = $DBH->query("IZABERI ime, adresu, grad od ljudi"); # biramo način preuzimanja $STH->setFetchMode(PDO::FETCH_OBJ); # ispisuje rezultat while($row = $STH->fetch()) ( echo $row->name . "\n"; echo $row->addr . "\n"; echo $row->city . " \ n"; )

FETCH_CLASS

Kada se koristi fetch_class, podaci se zapisuju u instance navedene klase. U ovom slučaju, vrijednosti se dodjeljuju svojstvima objekta PRIJE pozivanja konstruktora. Ako svojstva s nazivima koji odgovaraju imenima stupaca ne postoje, bit će kreirana automatski (sa javnim opsegom).

Ako vaši podaci zahtijevaju obaveznu obradu odmah nakon što su primljeni iz baze podataka, mogu se implementirati u konstruktoru klase.

Na primjer, uzmimo situaciju u kojoj trebate sakriti dio adrese stanovanja osobe.
class secret_person (javno $name; javni $addr; javni $city; javni $other_data; funkcija __construct($other = "") ( $this->addr = preg_replace("//", "x", $this-> addr $this->other_data = $other);
Prilikom kreiranja objekta, sva mala latinična slova moraju biti zamijenjena sa x. hajde da proverimo:
$STH = $DBH->query("IZABERI ime, adresu, grad od ljudi"); $STH->setFetchMode(PDO::FETCH_CLASS, "secret_person"); while($obj = $STH->fetch()) ( echo $obj->addr; )
Ako adresa u bazi podataka izgleda kao '5 Rosebud', onda će izlaz biti '5 Rxxxxxx'.

Naravno, ponekad ćete htjeti da se konstruktor pozove PRIJE dodjeljivanja vrijednosti. PDO dozvoljava i ovo.
$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, "tajna_osoba");
Sada kada ste prethodni primjer dopunili dodatnom opcijom (PDO::FETCH_PROPS_LATE), adresa se neće mijenjati, jer se ništa ne dešava nakon što se vrijednosti upišu.

Konačno, ako je potrebno, možete proslijediti argumente konstruktoru direktno prilikom kreiranja objekta:
$STH->setFetchMode(PDO::FETCH_CLASS, "secret_person", array("stuff"));
Možete čak proslijediti različite argumente svakom objektu:
$i = 0; while($rowObj = $STH->fetch(PDO::FETCH_CLASS, "secret_person", array($i))) ( // uradi nešto $i++; )

Druge korisne metode

Iako ovaj članak ne može (i ne pokušava da pokrije) svaki aspekt rada sa PDO-om (to je ogroman modul!), sljedećih nekoliko karakteristika ne može biti izostavljeno bez spominjanja.
$DBH->lastInsertId();
Metoda ->lastInsertId() vraća id posljednjeg umetnutog zapisa. Vrijedi napomenuti da se uvijek poziva na objektu baze podataka (koji se u ovom članku naziva $DBH), a ne na objektu s izrazom ($STH).
$DBH->exec("IZBRIŠI IZ ljudi GDJE 1"); $DBH->exec("SET time_zone = "-8:00"");
Metoda ->exec() se koristi za operacije koje ne vraćaju nikakve podatke osim broja zapisa na koje utiču.
$safe = $DBH->quote($nesigurno);
Metoda ->quote() postavlja navodnike u nizove podataka tako da ih je sigurno koristiti u upitima. Korisno ako ne koristite pripremljene izjave.
$rows_affected = $STH->rowCount();
Metoda ->rowCount() vraća broj zapisa koji su učestvovali u operaciji. Nažalost, ova funkcija nije radila sa SELECT upitima do PHP 5.1.6. Ako nije moguće ažurirati verziju PHP-a, broj zapisa se može dobiti na sljedeći način:
$sql = "IZABIR BROJ(*) OD ljudi"; if ($STH = $DBH->query($sql)) ( # provjeri broj zapisa if ($STH->fetchColumn() > 0) ( # izvrši potpunu selekciju ovdje jer su podaci pronađeni! ) else ( # ispisati poruku da nisu pronađeni podaci koji zadovoljavaju zahtjev) )

Zaključak

Nadam se da će ovaj materijal pomoći nekima od vas da pređu sa mysql i mysqli ekstenzija.


3. juna 2018 Andrey Chernyshov Tutorial za prevođenje 1737 0

PDO je akronim za PHP Data Objects: to je PHP ekstenzija za rad sa bazama podataka pomoću objekata. Jedna od njegovih prednosti leži u činjenici da nije direktno vezan za određenu bazu podataka: njegov interfejs vam omogućava pristup nekoliko različitih okruženja, uključujući: MySQL, SQLite, PostgreSQL, Microsoft SQL Server.

Ovaj vodič ima za cilj da pruži potpuni pregled PDO-a i vodi čitaoca korak po korak od kreiranja i povezivanja na bazu podataka, do odabira najprikladnijih metoda preuzimanja, demonstrirajući kako kreirati pripremljene upite i opisujući moguće načine greške.

Kreiranje testne baze podataka i tabele

Pre svega, kreiraćemo bazu podataka:

CREATE DATABASE solar_system; DODAJTE SVE PRIVILEGIJE NA solarnom_sistemu.* "testuser"@"localhost" IDENTIFIKOVANOM POMOĆU "testpassword";

Dodijelili smo korisniku testuser sve privilegije u bazi podataka solar_system koristeći testpassword za lozinku. Sada napravimo tabelu i ispunimo je nekim informacijama:

USE solar_system; CREATE TABLE planete (id TINYINT(1) UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARNI KLJUČ(id), ime VARCHAR(10) NOT NULL, boja VARCHAR(10) NOT NULL); INSERT INTO planets(ime, boja) VALUES("zemlja", "plavo"), ("mars", "crveno"), ("jupiter", "čudno");

Opis DSN (ime izvora podataka) veze

Sada kada imamo bazu podataka, moramo postaviti DSN. DSN je skraćenica od Data Source Name, i predstavlja skup informacija potrebnih za povezivanje sa bazom podataka, DSN je u obliku niza. Sintaksa se razlikuje ovisno o bazi podataka na koju se trebate povezati, ali pošto koristimo MySQL/MariaDB, moramo postaviti sljedeće:

  • Tip drajvera koji se koristi za povezivanje;
  • Ime glavnog računara na kojem se izvodi baza podataka;
  • Priključak (opciono);
  • Ime baze podataka;
  • Kodiranje (opciono).

Format stringa u našem slučaju će biti ovakav (spremićemo ga u varijablu $dsn):

$dsn = "mysql:host=localhost;port=3306;dbname=solar_system;charset=utf8";

Prije svega, postavljamo prefiks baze podataka ili prefiks baze podataka. U ovom slučaju, pošto se povezujemo sa bazom podataka tipa MySQL/MariaDB, koristimo mysql. Zatim smo prefiks od ostatka retka odvojili dvotočkom, a svaki sljedeći dio je od ostatka odvojen tačkom i zarezom.

U sljedeća dva odjeljka specificirali smo ime hosta na kojem se pokreće baza podataka i port koji se koristi za povezivanje. Ako port nije naveden, koristit će se zadani port, u ovom slučaju 3306. Odmah nakon imena baze podataka je charset .

Kreiranje PDO objekta

Sada kada je naš DSN spreman, počet ćemo kreirati PDO objekt. PDO konstruktor koristi DSN string kao prvi parametar, korisničko ime baze podataka kao drugi parametar, lozinku kao treći i opcioni niz postavki kao četvrti.

$options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]; $pdo = novi PDO($dsn, "testuser", "testpassword", $options);

Postavke se također mogu postaviti nakon kreiranja objekta, korištenjem metode SetAttribute():

$pdo->SetAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Konfiguriranje PDO-a za pregled grešaka

Pogledajmo neke od opcija dostupnih za PDO::ATTR_ERRMODE. Ove opcije su izuzetno važne jer određuju kako će se PDO ponašati kada se pojave greške. Moguće opcije:

PDO::ERRMODE_SILENT

Zadana opcija. PDO će jednostavno izbaciti kod greške i poruku o grešci. Mogu se dobiti pomoću metoda errorCode() i errorInfo().

PDO::ERRMODE_EXCEPTION

Ova opcija je, po mom mišljenju, preporučljiva za korištenje. Uz njegovu pomoć, pored izdavanja koda greške i informacija, PDO će izbaciti PDOException, koji će prekinuti izvršavanje skripte, a koristan je i za PDO transakcije (pogledaćemo ih malo kasnije).

PDO::ERRMODE_WARNING

Sa ovom opcijom, PDO će prikazati kod greške i poruku baš kao PDO::ERRMODE_SILENT , ali će također prikazati upozorenje WARNING koje ne prekida skriptu.

Postavljanje zadane metode uzorkovanja

Još jedna važna postavka je regulirana pomoću konstante PDO::DEFAULT_FETCH_MODE. Omogućava vam da konfigurišete podrazumevanu operaciju metode fetch() koja će se koristiti za dobijanje rezultata zahteva. Evo najčešće korištenih opcija:

PDO::FETCH_BOTH

Kada ga koristite, dobijeni rezultati će biti indeksirani i cijelim brojevima i nazivima stupaca. Koristeći ga u metodi za dobijanje reda iz tabele planeta, dobićemo sledeće rezultate:

$stmt = $pdo->query("SELECT * FROM planets"); $results = $stmt->fetch(PDO::FETCH_BOTH); Niz ( => 1 => 1 => zemlja => zemlja => plava => plava)

PDO::FETCH_ASSOC

Sa ovom konstantom, rezultati će biti zapisani u asocijativni niz u kojem će svaki ključ biti naziv stupca, a svaka vrijednost će predstavljati određenu vrijednost u redu:

$stmt = $pdo->query("SELECT * FROM planets"); $results = $stmt->fetch(PDO::FETCH_ASSOC); Niz ( => 1 => zemlja => plava)

PDO::FETCH_NUM

Koristeći PDO::FETCH_NUM konstantu dobijamo 0-indeksiran niz:

Niz ( => 1 => zemlja => plava)

PDO::FETCH_COLUMN

Ova konstanta je korisna za dobivanje samo vrijednosti iz stupca, a metoda će vratiti sve rezultate unutar jednostavnog jednodimenzionalnog niza. Na primjer, evo zahtjeva:

$stmt = $pdo->query("IZABERI ime SA planeta");

Kao rezultat:

Niz ( => zemlja => mars => jupiter)

PDO::FETCH_KEY_PAIR

Ova konstanta je korisna kada trebate dobiti vrijednosti iz dvije kolone. Metoda fetchAll() će vratiti rezultate kao asocijativni niz. U ovom nizu podaci iz prve kolone bit će navedeni u obliku ključeva, a iz druge - kao vrijednosti:

$stmt = $pdo->query("IZABIR ime, boja SA planeta"); $result = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);

Kao rezultat:

Niz ( => plavo => crveno => čudno)

PDO::FETCH_OBJECT

Kada koristite konstantu PDO::FETCH_OBJECT, anonimni objekat će biti kreiran za svaki dohvaćeni red. Njegova (javna) svojstva će biti nazvana isto kao i kolone, a rezultati upita će se koristiti kao vrijednosti. Korištenje ove metode za isti upit kao gore dat će sljedeći rezultat:

$results = $stmt->fetch(PDO::FETCH_OBJ); stdClass objekat ( => zemlja => plava)

PDO::FETCH_CLASS

Kao i prethodna konstanta, ovo će dodijeliti vrijednosti stupaca svojstvima objekta, ali u ovom slučaju moramo konfigurirati postojeću klasu koja će se koristiti za kreiranje objekta. Za demonstraciju, prvo ćemo kreirati klasu:

Class Planet (privatna $name; privatna $color; javna funkcija setName($planet_name) ( $this->name = $planet_name; ) javna funkcija setColor($planet_color) ( $this->color = $planet_color; ) javna funkcija getName () ( vrati $this->name; ) javna funkcija getColor() (vrati $this->color; ) )

Ne obraćajte pažnju na jednostavnost koda, pogledajmo bolje klasu Planet koju smo kreirali: ona ima private u svojim svojstvima, a klasa nema konstruktor. Pokušajmo sada postići rezultate.

Kada koristite fetch() sa PDO::FETCH_CLASS morate koristiti metodu setFetchMode() na objektu prije nego pokušate dohvatiti podatke, na primjer:

$stmt = $pdo->query("IZABIR ime, boja SA planeta"); $stmt->setFetchMode(PDO::FETCH_CLASS, "Planet");

Navodimo konstantu PDO::FETCH_CLASS kao prvi argument metode setFetchMode() i ime klase koja se koristi za kreiranje objekta (u našem slučaju “Planet”) kao drugi argument. Sada pokrenimo kod:

$planet = $stmt->fetch();

Ovo bi trebalo rezultirati objektom Planeta:

Var_dump($planet); Planeta Objekat ( => zemlja => plava)

Obratite pažnju na to kako su vrijednosti vraćene iz upita dodijeljene odgovarajućim karakteristikama objekta, iako su privatne.

Dodjela karakteristika nakon kreiranja objekta

Klasa “Planet” nije imala nikakav specifičan konstruktor, tako da nije bilo problema sa dodeljivanjem karakteristika; ali šta ako klasa ima konstruktor u kojem se postavljaju i mijenjaju karakteristike? Pošto su vrijednosti dodijeljene prije pokretanja konstruktora, one će biti prepisane.

PDO pomaže u obezbjeđivanju konstante FETCH_PROPS_LATE: kada se koristi, vrijednosti će biti dodijeljene nakon kreiranja objekta. primjer:

Class Planet ( privatno $name; privatna $color; javna funkcija __construct($name = mjesec, $color = siva) ( $this->name = $name; $this->color = $color; ) javna funkcija setName($ planet_name) ( $this->name = $planet_name; ) javna funkcija setColor($planet_color) ( $this->color = $planet_color; ) javna funkcija getName() (vrati $this->name; ) javna funkcija getColor() (vrati $this->color; ) )

Modificirali smo našu klasu Planet da kreiramo konstruktor koji će uzeti dva argumenta: ime ime i boju. Ovi argumenti imaju osnovne vrijednosti mjesec i sivo, što znači da ako nisu date druge vrijednosti, one će biti postavljene.

U ovom slučaju, ako ne koristimo FETCH_PROPS_LATE, bez obzira koje vrijednosti se dobiju iz baze podataka, sve karakteristike će ostati osnovne, jer će tokom procesa kreiranja objekta biti prepisane. Da to provjerimo, pokrenimo sljedeći upit:

$stmt = $pdo->query("IZABERI ime, boju IZ solarnog_sistema WHERE ime = "zemlja""); $stmt->setFetchMode(PDO::FETCH_CLASS, "Planet"); $planet = $stmt->fetch();

Sada pogledajmo objekt Planeta i provjerimo koje vrijednosti odgovaraju njegovim karakteristikama:

Var_dump($planet); object(Planet)#2 (2) ( ["name":"Planet":private]=> string(4) "moon" ["color":"Planet":private]=> string(4) "grey" )

Kao što se očekivalo, vrijednosti preuzete iz baze podataka su prepisane zadanim vrijednostima. Sada ćemo demonstrirati rješenje problema koristeći konstantu FETCH_PROPS_LATE (i isti upit kao i prethodni):

$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, "Planet"); $planet = $stmt->fetch(); var_dump($planet); object(Planet)#4 (2) ( ["name":"Planet":private]=> string(5) "earth" ["color":"Planet":private]=> string(4) "blue" )

Konačno je postignut željeni rezultat. Ali što ako konstruktor klase nema osnovne vrijednosti i one moraju biti specificirane? Ovo je već jednostavnije: možemo postaviti parametre konstruktora u obliku niza, kao treći argument iza imena klase, koristeći metodu setFetchMode(). Na primjer, promijenimo konstruktor:

Class Planet ( privatno $name; privatno $color; javna funkcija __construct($name, $color) ( $this->name = $name; $this->color = $color; ) [...])

Argumenti konstruktora su sada potrebni, pa izvodimo:

$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, "Planet", ["mjesec", "siva"]);

U ovom slučaju, parametri koje navedemo služe samo kao osnovne vrijednosti potrebne za rad objekta bez grešaka: oni će biti prepisani vrijednostima iz baze podataka.

Dohvaćanje višestrukih objekata

Naravno, moguće je dobiti više rezultata odjednom u obliku objekata, bilo korištenjem metode fetch() ili kroz petlju:

Dok ($planet = $stmt->fetch()) ( // Nešto što ima veze s rezultatima)

Ili dobijanje svih rezultata odjednom. U ovom slučaju, kao što je ranije spomenuto, kada koristite metodu fetchAll() morat ćete navesti način dohvaćanja ne prije pokretanja metode, već u trenutku kada se pokrene:

$stmt->fetchAll(PDO::FETCH_CLASS|PDO_FETCH_PROPS_LATE, "Planet", ["mjesec", "siva"]);

PDO::FETCH_INTO

Kada koristi ovu konstantu, PDO ne kreira novi objekt, umjesto toga ažurira karakteristike postojećeg, ali samo ako je javni ili ako se unutar objekta koristi metoda __set().

Pripremljeno protiv direktnih zahtjeva

PDO ima dva načina rada s upitima: korištenjem direktnih i pouzdanijim – pripremljenim.

Direktni zahtjevi

Postoje dvije glavne metode za korištenje direktnih upita: query() i exec() . Prvi kreira PDOStatemnt objekat, kojem se može pristupiti putem metoda fetch() ili fetchAll(): ako ih koristite u slučajevima kada se tabela ne mijenja, kao što je SELECT.

Druga metoda, umjesto toga, vraća broj reda koji je izmijenjen upitom: koristimo ga u slučajevima koji zamjenjuju redove, kao što su INSERT, DELETE ili UPDATE. Direktne upite treba koristiti samo u slučajevima kada u upitima nema varijabli i nema sumnje u sigurnost metode.

Pripremljeni upiti

PDO također podržava pripremljene upite u dva koraka: oni su korisni kada upiti imaju varijable i općenito su sigurniji jer će metoda pripreme() obaviti sav potreban posao umjesto nas. Pogledajmo kako se koriste varijable. Zamislite da želimo da unesemo karakteristike planete u tabelu Planeta. Prvo, pripremimo zahtjev:

$stmt = $pdo->prepare("INSERT INTO planets(name, color) VALUES(?, ?)");

Kao što je ranije rečeno, koristimo metodu pripreme() koja uzima SQL upit kao argument, koristeći privremene vrijednosti za varijable. Privremene vrijednosti mogu biti dvije vrste: pozicione i nominalne.

Positional

Koristi? pozicione privremene vrijednosti, kod je sažetiji, ali moramo specificirati podatke koji će biti umetnuti istim redoslijedom kao i nazivi stupaca u nizu koji je dat kao argument metodi execute():

$stmt->execute([$planet->name, $planet->color]);

Personalizovano

Korištenjem imenovanih rezerviranih mjesta, nije nam potreban poseban redoslijed, ali kao rezultat dobijamo više koda. Prilikom pokretanja metode execute(), moramo dostaviti podatke u obliku asocijativnog niza, gdje je svaki ključ ime privremene vrijednosti koja se koristi, a pridružena vrijednost je ono što se prenosi u upit. Na primjer, prethodni zahtjev bi postao:

$stmt = $pdo->prepare("INSERT INTO planets(name, color) VALUES(:name, :color)"); $stmt->execute(["name" => $planet->name, "color" => $planet->color]);

Metode pripreme() i execute() se mogu koristiti za upite koji modificiraju ili jednostavno preuzimaju informacije iz baze podataka. U prvom slučaju koristimo gore navedene metode dohvaćanja za dobivanje informacija, au drugom koristimo metodu rowCount().

metode bindValue() i bindParam().

Metode bindValue() i bindParam() se također mogu koristiti za pružanje vrijednosti koje će biti umetnute u zahtjev. Prvi vezuje vrijednost date varijable za pozicionu ili imenovanu privremenu vrijednost koja se koristi u pripremi zahtjeva. Uzimajući prethodni slučaj kao primjer, uradićemo:

$stmt->bindValue("name", $planet->name, PDO::PARAM_STR);

Mi vezujemo vrijednost $planet->name za privremenu vrijednost:name. Imajte na umu da koristeći metode bindValue() i bindParam() također možemo specificirati tip varijable kao treći argument koristeći odgovarajuću PDO konstantu, u ovom slučaju PDO::PARAM_STR.

Korištenjem bindParam() umjesto toga možemo vezati varijablu na odgovarajuću privremenu vrijednost koja se koristi u pripremi upita. Imajte na umu da je u ovom slučaju varijabla vezana za referencu i njena vrijednost će biti promijenjena u privremenu samo kada se pokrene metoda execute(). Sintaksa je ista kao i prošli put:

$stmt->bindParam("name", $planet->name, PDO::PARAM_STR)

Vezali smo varijablu, a ne njenu vrijednost, $planet->name na:name ! Kao što je gore rečeno, zamjena će se dogoditi samo kada se pokrene metoda execute(), tako da će privremena vrijednost biti zamijenjena vrijednošću varijable u tom trenutku.

PDO transakcije

Transakcije vam omogućavaju da održite dosljednost prilikom pokretanja više upita. Svi upiti se izvršavaju u grupama i primjenjuju se na bazu podataka samo ako su svi uspješni. Transakcije neće raditi sa svim bazama podataka, a ne sa svim SQL konstrukcijama, jer neke od njih uzrokuju probleme.

Kao ekstreman i čudan primjer, zamislite da je korisnik morao odabrati listu planeta i svaki put kada bi napravio novu selekciju, morali biste izbrisati prethodnu iz baze podataka prije nego što ubacite novu. Šta ako se brisanje dogodi, a umetanje ne? Dobićemo korisnika bez planeta! U osnovi, transakcije se primjenjuju ovako:

$pdo->beginTransaction(); try ( $stmt1 = $pdo->exec("IZBRIŠI SA planeta"); $stmt2 = $pdo->prepare("INSERT INTO planets(name, color) VALUES (?, ?)"); foreach ($planets as as). $planet) ( $stmt2->execute([$planet->getName(), $planet->getColor()]); ) $pdo->commit() ) catch (PDOException $e) ( $pdo-> rollBack ();

Prije svega, metoda beginTransaction() na PDO objektu onemogućuje autocommit zahtjeva, a zatim se zahtjevi pokreću traženim redoslijedom. U ovom trenutku, osim ako se ne dogodi PDOException, zahtjevi se automatski prosljeđuju kroz metodu commit(), inače se transakcije poništavaju putem metode rollBack() i autocommit se vraća.

Na ovaj način, sa više zahtjeva, uvijek će postojati dosljednost. Ovo je prilično očigledno, ali PDO transakcije se mogu koristiti samo ako je PDO::ATTR_ERRMODE postavljen na PDO::ERRMODE_EXCEPTION.

Bootstrap framework: brzi prilagodljivi izgled

Korak po korak video kurs o osnovama adaptivnog izgleda u Bootstrap okviru.

Naučite kako jednostavno, brzo i efikasno postaviti raspored koristeći moćan i praktičan alat.

Izgled po narudžbi i platiti.

Besplatan kurs "Site on WordPress"

Želite li savladati WordPress CMS?

Dobijte lekcije o dizajnu i izgledu web stranice na WordPressu.

Naučite raditi s temama i izrezanim izgledima.

Besplatan video kurs o crtanju dizajna web stranice, izgledu i instalaciji na CMS WordPress!

*Pređite mišem preko za pauziranje pomicanja.

Nazad napred

Osnove rada sa PDO ekstenzijom

Danas ćemo razgovarati o vrlo zanimljivoj temi - osnovama rada s ekstenzijom. PDO za PHP.

PDO (PHP objekti podataka)- ovo je jednostavno sučelje koje vam omogućava rad s različitim bazama podataka bez uzimanja u obzir njihovih specifičnosti. Sa PDO možemo lako prelaziti između različitih baza podataka i upravljati njima. Da bi bilo jasnije, pogledajmo primjer.

Kako smo se prije trebali povezati s bazom podataka MySQL?

Mysql_connect($host, $user, $password); mysql_select_db($db);

Za povezivanje na SQLite trebali smo to napisati ovako:

Sqlite_open($db);

Ako nam treba baza podataka PostgreSQL, onda to treba da napišete ovako:

Pg_connect("host=$host, dbname=$db, korisnik=$korisnik, lozinka=$lozinka");

Nije baš zgodno, zar ne? Ispostavilo se da ćemo, ako želimo promijeniti bazu podataka, morati ponoviti mnogo koda. I tako, da se ovo popravi, pojavila se posebna PHP ekstenzija - PDO.

Pogledajmo kako se sada možemo povezati s bazom podataka:

$db = novi PDO("mysql:host=$host;dbname=$db", $korisnik, $lozinka);

$db = novi PDO("sqlite:$db);

PostgreSQL:

$db = novi PDO("pgsql:host=$host;dbname=$db", $korisnik, $lozinka);

Kao što vidite, sve je isto, osim priključne linije. To je jedina razlika.


Pogledajmo sada kako smo nekada morali izvršavati upite:

$sql = "INSERT INTO(ime, email) VALUES($name, $email)"; // MySQL mysql_query($sql); // SQLite sqlite_query($sql); // PostgreSQL pg_query($sql);

Sada možemo da apstrahujemo od ovoga:

// PDO $result = $db->exec($sql);

Sve! Naš zahtjev će biti izvršen bez obzira koju bazu podataka koristimo, i u varijablu rezultatće pokazati broj zahvaćenih redova.

Međutim, na ovaj način nećemo moći odabrati nešto iz baze podataka. Za uzorkovanje trebamo koristiti not exec, A upit.

$sql = "IZABERI ime IZ korisnika"; $result = $db->query($sql);

Hajdemo sada Prisjetimo se sigurnosti, jer sve podatke treba provjeriti. Kako smo to radili prije?

$sql = "SELECT * FROM users WHERE name = $name"; $name = $_POST["name"]; // MySQL $name = mysql_real_escape_string($name); // SQLite $name = sqlite_escape_string($name); // PostgreSQL $name = pg_escape_string($name);

Sada ne moramo ovo da radimo. PDO uradiće sve za nas.

$name = $db->quote($name); $result = $db->query($sql);

PDO će sam provjeriti sve i obraditi prenesene podatke. Cool :) Još cooler će doći! Hajde da nastavimo.

Kako smo ranije konvertovali rezultat u niz? Pogledajmo bazu podataka kao primjer MySQL.

$result = mysql_query($sql); // Dakle $row = mysql_fetch_assoc($result); // Ili ovako... $row = mysql_fetch_array($result, FETCH_ASSOC);

Baš kao i asocijativni, mogli bismo dobiti i niz brojeva. Pogledajmo sada kako se to radi u PDO:

$stmt = $db->query($sql); //Asocijativni $result = $stmt->FETCH(PDO::FETCH_ASSOC); // Numerirani $result = $stmt->FETCH(PDO::FETCH_NUM); // Oba tipa nizova u isto vrijeme $result = $stmt->FETCH(PDO::FETCH_BOTH); // Objekt $result = $stmt->FETCH(PDO::FETCH_OBJ);

Takođe je veoma jednostavan za korišćenje:

// Asocijativni eho $result["name"]; // Numerirani echo $result; // Odjek objekta $result->name;

Za "lijenje" postoji ovo:

$stmt = $db->query($sql); $rezult = $stmt->FETCH(PDO::FETCH_LAZY);

Vraća sve 3 vrste odjednom. One. Ovo FETCH_BOTH I FETCH_OBJ zajedno. Kao što ste možda pretpostavili, nakon ovoga podacima se može pristupiti na bilo koji od tri načina:

Echo $result->name; echo $result["name"]; echo $result;

kako god Dohvati vraća samo jedan zapis, pa ako želimo da dobijemo sve zapise, onda treba da koristimo FetchAll.

$stmt = $db->query("SELECT * FROM users"); $result = $stmt->FetchAll(PDO::FETCH_ASSOC); foreach($rezultat kao $user) ( echo $user["name"]."
"; }

Ali postoji još jedna cool stvar vezana za Dohvati. Uz njegovu pomoć možemo ispuniti našu klasu podacima iz baze podataka automatski.

Korisnik klase (javni $login; javni $id; javna funkcija showInfo() ( echo " ".$this->id.""." : ".$this->login."
"; ) ) $db = novi PDO("mysql:host=localhost;dbname=test", "root", ""); $stmt = $db->query("SELECT * FROM `users`"); $ rezultat = $stmt->fetchAll(PDO::FETCH_CLASS, "Korisnik" foreach($rezultat kao $user) ( $user->showInfo(); )

Kao što vidite, sve je vrlo jednostavno. Samo treba da navedemo konstantu FETCH_CLASS i odvojeno zarezom u navodnicima, ime klase u koju će podaci biti umetnuti.

Zatim prolazimo kroz objekat i prikazujemo informacije koje su nam potrebne.
Pažnja! Imena svojstava u klasi moraju odgovarati imenima polja u bazi podataka.

Između ostalog, možemo kreirati tzv pripremljene upite. Koje su njihove prednosti?

1. Zahtjev možemo pripremiti jednom, a zatim ga pokrenuti onoliko puta koliko nam je potrebno. I sa istim i drugim parametrima.

Kada je upit pripremljen, DBMS ga analizira, kompajlira i optimizira njegov plan izvršenja. U slučaju složenih upita, vrijeme izvršenja bit će vidljivo ako ga pokrenemo s različitim parametrima. U slučaju pripremljenih upita, to se radi jednom i samim tim se gubi manje vremena.

2. Pripremljeni parametri upita ne moraju biti prikazani navodnicima, upravljački program to čini automatski. Ako aplikacija koristi samo pripremljene upite, SQL injekcije su gotovo nemoguće.

PDO može emulirati pripremljene upite, ako ih upravljački program ne podržava. Pogledajmo sada kako ih koristiti?

$stmt = $db->prepare("INSERT INTO users (name, login) VALUES (:name, :login)"); $stmt->bindParam(":name", $name); $stmt->bindParam(":login", $login); // Umetnite jedan red sa ovim vrijednostima $name = "vasya"; $login = "vasya123"; $stmt->izvrši(); // Sada još jedan red s različitim vrijednostima $name = "petya"; $login = "petya123"; $stmt->izvrši();

Metoda bindParam omogućava nam postavljanje parametara. Mislim da je tu sve jasno. Prvo, tamo gdje želimo da se umetnu podaci, napišite sljedeći red " :Ime". I onda ukazujemo odakle će doći. U ovom slučaju, oni će biti uzeti iz varijabli ime I Ulogovati se.

Sada možemo koristiti ovaj zahtjev s različitim parametrima koliko god puta želimo, a da bismo ga izvršili moramo pozvati metodu izvršiti. Ovo su bili imenovani opcije. Postoji također nije imenovan.

$stmt = $db->prepare("INSERT INTO users (name, login) VALUES (?, ?)"); // Podaci iz varijable name će biti umetnuti umjesto prvog upitnika $stmt->bindParam(1, $name); // Podaci iz varijable za prijavu će biti umetnuti umjesto drugog upitnika $stmt->bindParam(2, $login); // Umetnuti jedan red sa ovim vrijednostima $name = "vasya"; $login = "vasya123"; $stmt->izvrši(); // Sada još jedan red sa različitim vrijednostima $name = "petya"; $login = "petya123"; $stmt->izvrši();

Sljedeća tačka - Kako hvatamo greške?

Za ovo postoji klasa PDOException. Preporučujem da sve svoje zahtjeve pišete u bloku probaj-uhvati.

Pokušajte ( $db = novi PDO("myql:host=localhost;dbname=test", "root", ""); $stmt = $db->query("SELECT * FROM users"); $result = $stmt ->fetch(PDO::FETCH_ASSOC echo $result["login"] ) catch(PDOException $e) ( echo "Greška: ".$e->getMessage()."
"; echo "Na liniji: ".$e->getLine(); )

Ovdje smo pogriješili i napisali myql umjesto mysql. I klasa PDOExceptionće nam pisati o tome.

Ima nekoliko metoda, ali najčešće se koriste getMessage() koji nam vraća tekst greške i getLine(), koji vraća broj reda u kojem je došlo do greške.

I na kraju, hajde da pričamo o tome transakcije. Prvo ću dati kod.

Pokušajte ( $db = novi PDO("mysql:host=localhost;dbname=test", "root", ""); $db->beginTransaction(); $stmt = $db->exec("INSERT INTO `users `(`login`) VALUES("login1")"); $stmt = $db->exec("INSERT INTO `users`(`login`) VALUES("login2")"); $stmt = $db- >exec("INSERT INTO `users`(`login`) VALUES("login3")" ($db->commit() catch(PDOException $e) ($db->rollBack();)

Ovdje započinjemo transakciju koristeći metodu beginTransaction(). Slijede neki kod za upit. Zatim pozivamo metodu počiniti() da potvrdimo naše promjene. Ako nešto krene po zlu, onda u bloku uhvatiti nazivamo metodom rollback(), koji će sve naše podatke vratiti u prethodno stanje.

“Zašto su ove transakcije zapravo potrebne?” - pitate. Da biste odgovorili na ovo pitanje, razmotrite primjer koji sam dao gore. Tamo unosite vrijednost u polje "login". login1, login2, login3.

Zamislimo to nakon umetanja login1 I login2, došlo je do greške. Ispostavilo se da su ovi podaci umetnuti, i login3- Ne. U mnogim slučajevima ovo je neprihvatljivo i u budućnosti će prekinuti aplikaciju.

Transakcije su potrebne upravo da bi se spriječile takve situacije. Ako naša skripta ne uspije, onda metoda rollback() vratiće sve u prvobitni oblik. One. login1 I login2 takođe neće biti umetnuta. Emulirajmo ovu grešku.

Pokušajte ( $db = novi PDO("mysql:host=localhost;dbname=test", "root", ""); $db->beginTransaction(); $stmt = $db->exec("INSERT INTO `users `(`login`) VALUES("login1")"); $stmt = $db->exec("INSERT INTO `users`(`login`) VALUES("login2")"); exit("error") $stmt = $db->exec("INSERT INTO `users`(`login`) VALUES("login3")" $db->commit(PDOException $e) ($db-> rollBack); ();

Nakon umetanja login1 I login2 izlazimo iz skripte pomoću funkcije Izlaz(). Izbacimo izuzetak, završimo u bloku uhvatiti, a zatim sve vraćamo u prvobitni oblik. Sada, ako pogledamo u bazu podataka, nećemo tamo vidjeti login1 I login2.

Završićemo u ovom trenutku. Očigledno, ovdje nismo pokrili sve što nam PDO pruža, ali smo naučili osnove rada s njim. Detaljnije informacije o ovom proširenju uvijek možete pronaći na službenoj PHP web stranici.

Materijal je pripremio Vladislav Andreev posebno za web stranicu

P.S. Da li želite da napredujete u savladavanju PHP-a i OOP-a? Obratite pažnju na premium lekcije o različitim aspektima izrade web stranica, uključujući programiranje u PHP-u, kao i na besplatni kurs o kreiranju vlastitog CMS sistema u PHP-u od nule koristeći OOP:

Da li vam se dopao materijal i želite da mi se zahvalite?
Samo podijelite sa svojim prijateljima i kolegama!


mob_info