PHP & MySQL - Pripremljene izjave (Prepared Statements)


Šta je pripremljena izjava?

Pripremljeni izraz (poznat i kao parametrizirani izraz) je jednostavno prijedlog SQL upita koji sadrži rezervisano mjesto umjesto stvarnih vrijednosti parametara. Ova rezervisana mjesta će biti zamijenjena stvarnim vrijednostima u vrijeme izvršenja izjave. MySQLi podržava upotrebu anonimnog pozicijskog rezervisanog mjesta (?), kao što je prikazano u sljedećem primjeru:

INSERT INTO persons (first_name, last_name, email) VALUES (?, ?, ?);

PDO podržava i anonimno pozicijsko rezervirano mjesto (?), kao i imenovano rezervisano mjesto. Imenovano rezervisano mjesto započinje dvotačkom (:) nakon čega slijedi identifikator, poput ovog:

INSERT INTO persons (first_name, last_name, email)
VALUES (:first_name, :last_name, :email);

Izvršavanje pripremljene izjave sastoji se od dvije faze: pripreme i izvršenja.

  • Priprema - U fazi pripreme kreira se predložak SQL izraza koji se šalje na poslužitelj baze podataka. Poslužitelj analizira predložak izraza, vrši provjeru sintakse, optimizaciju upita i pohranjuje ga za kasniju upotrebu.
  • Izvrši - Tokom izvršavanja vrijednosti parametra se šalju na poslužitelj. Poslužitelj kreira izraz iz predloška izraza i vrijednosti za njegovo izvršavanje.

Pripremljeni izrazi su vrlo korisni, posebno u situacijama kada određeni izraz izvršite više puta s različitim vrijednostima, na primjer, niz INSERT izraza. Sljedeći dio opisuje neke od glavnih prednosti njegove upotrebe.



Prednosti upotrebe pripremljenih izjava

Pripremljena izjava može izvoditi istu izjavu više puta s visokom efikasnošću, jer se izjava samo još jednom raščlanjuje, dok se može izvršiti više puta. Takođe minimizira upotrebu propusnosti, jer nakon svakog izvršavanja samo vrijednosti rezerviranog mjesta moraju biti prenesene na poslužitelja baze podataka umjesto kompletnog SQL izraza. Pripremljeni izrazi takođe pružaju snažnu zaštitu od SQL Injection-a, jer vrijednosti parametara nisu ugrađene direktno u niz SQL upita. Vrijednosti parametara šalju se poslužitelju baze podataka odvojeno od upita pomoću drugog protokola i zbog toga ne mogu interferisati s njim. Poslužitelj koristi ove vrijednosti direktno na mjestu izvršenja, nakon raščlanjivanja predloška izraza. Zbog toga su pripremljeni izrazi manje skloni greškama i zbog toga se smatraju jednim od najkritičnijih elemenata u sigurnosti baze podataka. Sljedeći primjer će vam pokazati kako pripremljene izjave zapravo rade:


Kao što možete vidjeti u gornjem primjeru, samo jednom smo pripremili izraz INSERT, ali smo ga izvršili više puta prosljeđivanjem različitog skupa parametara.



Objašnjenje koda (proceduralni stil)

Unutar SQL INSERT izraza gornjeg primjera, upitnici se koriste kao rezervisana mjesta za vrijednosti imena first_name, last_name, email polja. Funkcija mysqli_stmt_bind_param() veže varijable na rezervirana mjesta (?) u predlošku SQL izraza. Rezervisači (?) će biti zamijenjeni stvarnim vrijednostima koje se u varijablama drže u vrijeme izvršenja. String definicije tipa naveden kao drugi argument, tj. string "sss" navodi da je tip podataka svake varijable vezivanja stringa. String definicije tipa specifikuje tipove podataka odgovarajućih varijabli vezivanja i sadrži jedan od sljedećih karaktera:

  • b - binarni (binary) (poput slike, PDF datoteke itd.)
  • d - dvostruko (double) (broj s pomičnom zarezom, decimalni brojevi)
  • i - cijeli broj (integer) (cijeli broj)
  • s - string (tekst)

Broj varijabli vezivanja i broj karaktera u stringu definicije tipa, moraju se podudarati s brojem rezervisanih mjesta u predlošku SQL izraza.



Korištenje ulaza primljenih putem web obrazca

Ako se sjećate iz prethodne lekcije, stvorili smo HTML obrazac za ubacivanje podataka u bazu. Ovdje ćemo taj primjer proširiti primjenom pripremljene izjave. Isti HTML obrazac možete koristiti za testiranje sljedećeg primjera skripte za ubacivanje podataka, ali samo pazite da koristite ispravno ime datoteke u atributu akcije obrasca. PRETHODNA LEKCIJA. Evo ažuriranog PHP koda za ubacivanje podataka. Ako pažljivo vidite primjer, vidjećete da nismo koristili mysqli_real_escape_string() za izbjegavanje korisničkih unosa, kao što smo učinili u prethodnom primjeru. Budući da se u pripremljenim izrazima unosi korisnika nikada ne mogu izmjeniti direktno u stringu upita.