PHP proširenja za rad sa bazama podataka Postoje pojedinačna proširenja za različite tipove baza podataka sa svojim bibliotekama funkcija npr. postoji podrška za IBM DB2, Oracle, Ingres, MySQL, PostgreSQL, SQLite, dbase, filepro, Fokus je na PDO proširenju jer nudi data-access abstraction: bez obzira na bazu podataka koja se koristi, koriste se iste funkcije za postavljanje upita i dohvatanje podataka PDO ne nudi i database abstraction: ne vrši se emulacija ili rewriting upita u skladu sa tipom baze koja se koristi (u te svrhe se može koristiti npr. proširenje PEAR DB, MDB2, ADODb, ) PDO (PHP Data Objects) Pogledati: http://php.net/manual/en/book.pdo.php Povezivanje: Povezivanje sa bazom se ostvaruje kreiranjem instance PDO klase i konekcija se smatra otvorenom sve dok postoji kreirani PDO objekat $db= new PDO('mysql:localhost;dbname=list', 'veb', 'veb'); Argumenti su: tzv. dsn (data source name) niska sa naznakom tipa baze, mrežnog imena, po potrebi porta, i imena baze korisničko ime šifra atributi konekcije PDO::ATTR_CASE kontrola imenovanja kolona rezultata PDO::ATTR_PERSISTENT kontrola trajnosti konekcije PDO::ATTR_ERRMODE kontrola nivoa grešaka PDO::ATTR_AUTOCOMMIT commit nakon svakog sql iskaza.. koji se mogu podesiti i naknadno na nivou instance metodom setattribute() npr. $db->setattribute(pdo::attr_case, PDO::ATTR_LOWER) Rezultat $db je instanca klase PDO
U slučaju greške se generiše izuzetak tipa PDOException i odgovornost je programera da ga dohvati i obradi (u suprotnom postoji rizik od ispisa stek trace-a i prikaza važnih podataka npr. ako je u php.ini datoteci servera postavljeno display_errors svojstvo) try{ $db=new PDO('mysql:localhost;dbname=', 'uvit', 'uvit', array(pdo::attr_persistent=>true));... $db=null; }catch(pdoexception $e){ echo e->getmessage(); exit(); } Priprema upita: metoda prepare $stmt=$db->prepare( select * from list where id=:id ); pripremljeni upit je tipa PDOStatement na mestu gde se trebaju javiti stvarne vrednosti uvode se tzv. čuvari mesta (en. placeholders) pogodnosti koje priprema upita nosi: brzina: jednom pripremljen upit (analiziran, optimizovan sa utvrđenim planom izvršavanja) se može više puta izvršavati sigurnost: vrši se razdvajanje logike baze od logike podataka pa je opsnost od napada minimizovana (npr. od SQL injekcija) vrednosti čuvara mesta se mogu zadati prilikom izvršavanja (npr. funkcijom execute) ili unapred, mehanizmom vezivanja što bi značilo da se svaki put prilikom izvršavanja upita koriste trenutne vrednosti vezanih promenljivih prilikom vezivanja je moguće zadati i tipove podataka (provere zgodne zbog sigurnosti aplikacije): PDO::PARAM_STR (podrazumevani tip, niska), PDO::PARAM_INT, PDO::PARAM_BOOL, PDO::PARAM_NULL, PDO::PARAM_LOB
vezivanje parametra za čuvare mesta: 1. način: imenovanje čuvara mesta $stmt=$db->prepare( insert into t values (:username, :password, :email) ); $stmt->bindparam( :username, $username, PDO::PARAM_STR); $stmt->bindparam( :password, $password, PDO::PARAM_STR); $stmt->bindparam( :email, $email, PDO::PARAM_STR); čuvar mesta se može javiti samo jednom u upitu ako je potrebno istu vrednost upotrebiti na više mesta moraju se upotrebiti različiti čuvari 2. način: numerisanje čuvara mesta $stmt=$db->prepare( insert into t values (?,?,?) ); $stmt->bindparam(1, $username, PDO::PARAM_STR); $stmt->bindparam(2, $password, PDO::PARAM_STR); $stmt->bindparam(3, $email, PDO::PARAM_STR); 3. način: direktnim navođenjem prilikom izvršavanja $stmt=$db->prepare( insert into t values (:username, :password, :email) ); $stmt->execute(array('username'=> Pera, 'password'=> fdser3, 'email'=> pera@gmail.com )); ili $stmt=$db->prepare( insert into t values (?,?,?) ); $stmt->execute(array($username, $password, $email)); Izvršavanje upita: metode query i exec za izvršavanje nepripremljenih upita: $db->exec( select * from list where id=4 ); $db->query( select * from list where id=4 ); exec vraća samo broj redova rezultata (za sve tipove upita), dok query vraća kao rezultat ili PDOStatement objekat ili false u slučaju greške
metoda execute za izvršavanje pripremljenih upita: $stmt->execute(); $stmt mora biti objekat koji predstavlja pripremnljen upit, povratna vrednost je true ili false dok rezultat izvršavanja ostaje na nivou $stmt objekta Obrada rezultata: metoda fetchall(): za dohvatanje svih redova rezultata rezultat je niz ili false u slučaju greške metoda fetch(): za dohvatanje pojedinačnih redova rezultata kada nema više redova fetch() vraća false inače, vraća po dve vrednosti za svaku kolonu jedna vrednost ima za indeks ime kolone, a druga vrednost ima za indeks redni broj kolone npr. $row=$result->fetch(); $row[1], $row['username'], $row[2], $row['password'], argument metode fetch() utiče na tip rezultata: PDO::FETCH_BOTH podrazumevano PDO::FETCH_NUM rezultat je niz, a indeksi su samo numeričke vrednosti PDO::FETCH_ASSOC rezultat je niz, a indeksi su samo imena kolona PDO::FETCH_OBJ rezultat je niz objekata (primeraka klase ) čija su svojstva imenovana kolonama način rada fetch() metode se može podesiti i sa setfetchmode() metodom slično važi i za funkciju fetchall() Prebrojavanje skupa rezultata: za INSERT, UPDATE I DELETE iskaze metoda rowcount() za SELECT iskaz count(fetchall()) broj kolona se može dobiti pozivom metode columncount()
Obrada grešaka: Različite metode rezultiraju različitim tipovima grešaka: konstruktor PDO klase generiše izuzetak, prepare, execute i fetch vraćaju false vrednost. Umesto analize pojedinačnih tipova grešaka, uniformniji i preporučljiviji način za obradu grešaka je, recimo, da se na nivou PDO objekta postavi atribut PDO::ATTR_ERRMODE na vrednost PDO::ATTR_EXCEPTION i da se prilikom pojave greške prijavi izuzetak tipa PDOException koji se dalje može obrađivati u okviru catch bloka Na nivou klase PDOException javno su dostupne: svojstva: errorinfo informacije o grešci poslednjeg izvršenog upita u pitanju je niz koji sadrži SQL 92 SQLSTATE kod greške, kod specifičan za drajver koji se koristi i tekstualni opis greške javne metode: getmessage() - za očitavanje tekstualnog opisa greške getcode() - za očitavanje SQL koda greške getfile() - za očitavanje imena datoteke u kojoj se javila greška getline() - za očitavanje linije u kojoj se greška javila gettrace() i gettraceasstring() - za dobijanje stack-traca u formi niza ili niske