You are on page 1of 26

poglavlje 18



Rukovanje sesijama

dana{nje vreme, kori{}enje HTTP sesija za pra}enje perzistentnih informacija, kao {to
su korisni~ka pode{avnaja, ~ak i u najjednostavnijim aplikacijama predstavlja vi{e pravilo, nego izuzetak. Zbog toga, nezavisno od toga da li ste po~etnik u razvoju web

aplikacija, ili ste iskusan veteran koji je do sada koristio neki drugi programski jezik, trebalo bi
da posvetite neko vreme pa`ljivom ~itanju ovog poglavlja.
U programskom jeziku PHP rukovanje sesijama je dostupno od verzije 4.0 i predstavlja jednu
od najinteresantijih funkcionalnosti, o kojoj se uvek mnogo diskutuje. U ovom poglavlju mo`ete
nau~iti dosta o rukovanju sesijama, izme|u ostalog:


Zbog ~ega je neophodno rukovanje sesijama i koja je prednost rukovanja sesijama

Kako da konfiguri{ete PHP okru`enje, tako da na najefikasniji mogu}i na~in rukujete


sesijama

Kako da kreirate i uni{tavate sesije, odnosno kako da upravljate promenljivama vezanim za odre|ene sesije

Zbog ~ega mo`ete da razmotrite mogu}nost upravljanja podacima o sesijama


kori{}enjem baze podataka, odnosno kako da to prakti~no realizujete

[ta se podrazumeva pod rukovanjem sesijom?


Hypertext Transfer Protocol (HTTP) defini{e pravila koja se primenjuju prilikom transfera teksta,
grafike, videa i svih drugih podataka putem Weba. To je protokol bez stanja, {to zna~i da se svaki
zahtev obra|uje nezavisno od bilo kog prethodnog ili budu}eg zahteva. Iako je HTTP veoma jednostavan protokol, ~ime je omogu}ena njegova {iroka primena, njegova osobina da ne defini{e
stanja dugo je predstavljala veliki problem programerima koji su poku{avali da kreiraju veoma
slo`ene web aplikacije, koje moraju da imaju mogu}nost da pode{avaju odgovaraju}e
funkcionisanje prema korisni~kim zahtevima i preferencijama.

445

PHP i MySQL od po~etnika do profesionalca

Da bi se re{io ovaj problem, praksa sme{tanja odgovaraju}ih informacija na korisni~koj


ma{ini, koje se obi~no nazivaju kola~i}i, brzo je prihva}ena, ~ime je pojednostavljen postupak
upravljanja korisni~kim zahtevima u toku izvr{avanja aplikacije. Me|utim, ograni~enje vezano za
veli~inu kola~i}a i broj dozvoljenih kola~i}a, odnosno razli~ita pravila koja su vezana za njihovo
implementiranje, podstakll su programere da izmisle druga~ije re{enje: rukovanje sesijama.
Rukovanje sesijama je, u su{tini, veoma pametno re{enje, koje omogu}ava da se zaobi|e problem vezan za nepostojanje stanja u HTTP protokolu. Svaki posetilac stranice dobija atribut koji
ga jednozna~no identifikuje, poznat kao identifikator sesije (skra}eno SID), a zatim se svi
neophodni podaci povezuju sa tim jednozna~nim identifikatorom sesije, pri ~emu ti podaci
mogu odre|ivati ukupan broj poseta stranici na mese~nom nivou, omiljene boje pozadine ili
srednje slovo - vi ih defini{ete. Sa stanovi{ta relacionih baza podataka, identifikator sesije mo`ete
smatrati primernim klju~em koji se koristi za pristupanje svim ostalim atributima. Ali, na koji
na~in se identifikator sesije neprekidno vezuje za konkretnog korisnika, ukoliko se zna da je
HTTP protokol, zapravo, protokol koji ne defini{e stanja? To vezivanje, za konkretnog korisnika,
mo`ete da ostvarite na dva razli~ita na~ina:


446

Kori{}enjem kola~i}a: Ovaj genijalan na~in za upravljanje informacijama o korisnicima je, zapravo, vezan za originalan metod kori{}enja kola~i}a. Kada korisnik poseti
odgovaraju}u web stranicu, server bele`i odgovaraju}e informacije o korisniku, kao {to
su pode{avanja koja je korisnik izabrao, zatim te informacije u kola~i}u {alje do korisni~kog ~ita~a, koji ih snima. Kada korisnik uputi zahtev za pristupanje nekoj drugoj
stranici, server o~itava korisni~ke informacije i koristi ih, na primer, za realizovanje
personalizovanog prikaza zahtevane stranice. Me|utim, umesto da se u kola~i}
sme{taju korisni~ka pode{avanja, sme{ta se identifikator sesije. Kako korisnik pristupa
razli~itim delovima web prezentacije, o~itava se identifikator sesije kada je to
neophodno, a zatim se koriste odgovaraju}i podaci koji su vezani za taj identifikator
sesije i korisniku se prikazuju neophodni podaci. Pored toga, po{to kola~i} ostaje na
ra~unaru korisnika i nakon zavr{etka sesije, on mo`e biti o~itan i za vreme neke
naredne sesije, {to zna~i da se odr`ava perzistentnost ~ak i u du`em vremenskom
intervalu, u kome korisnik ne pristupa odgovaraju}oj web prezentaciji. Me|utim,
vodite ra~una o tome da je prihvatanje kola~i}a isklju~ivo u nadle`nosti korisnika,
tako da morate da budete spremni i na mogu}nost da korisnik ne dozvoljava da se
podaci snimaju u kola~i} na njegovom ra~unaru, ili da je nakon nekog vremena korisnik uklonio sve kola~i}e sa svoje ma{ine.

Rukovanje sesijama

POGLAVLJE 18

Modifikovanje URL adrese: Drugi metod koji se koristi za identifikaciju sesije je vezan
za postavljanje identifikatora sesije na kraj svake lokalne URL adrese zahtevane stranice. Rezultat toga je automatsko prosle|ivanje identifikatora sesije svaki put kada
korisnik pritisne jedan od lokalnih linkova. Ovaj metod, poznat kao modifikovanje
URL adrese, uklanja mogu}nost da rukovanje sesija bude onemogu}eno zato {to korisnik ne dozvoljava upotrebu kola~i}a. Me|utim, postoje i odgovaraju}e posledice
primene ovakvog metoda. Prvo, modifikovanje URL adrese ne omogu}ava perzistentnost izme|u sesija, zato {to se proces automatskog postavljanja identifikatora sesije na
kraj URL adrese ne nastavlja kada korisnik napusti va{u web prezentaciju. Drugo, ni{ta
ne spre~ava korisnika da iskopira URL adresu u poruku i elektronskom po{tom je
po{alje nekom drugom korisniku; sve dok se ne prekine sesija, ona }e postojati i na
radnoj stanici primaoca ove poruke. Razmotrite potencijalne probleme koji mogu nastati kada oba korisnika simultano pristupaju odre|enim sadr`ajima na va{oj
prezentaciji, a da pri tome koriste isti identifikator sesije, ili ukoliko primaoc poruke
koja sadr`i link ne treba da vidi odre|ene podatke kojima se mo`e pristupati u datoj
sesiji. Zbog toga se preporu~uje metodologija u kojoj se koriste kola~i}i. Me|utim,
isklju~ivo je na vama da defini{ete sve prednosti i nedostatke oba navedena metoda, i
da na kraju odlu~ite {ta vam je ~initi.

Proces rukovanja sesijama


Po{to PHP mo`e biti konfigurisan tako da autonomno upravlja celokupnim procesom rukovanja sesijama, uz neznatnu interakciju programera, mo`da }ete veliki broj podataka smatrati nebitnim. Me|utim, postoje potencijalne varijante podrazumevane procedure, koje zahtevaju od vas
bolje razumevanje celokupnog procesa, ~emu bi trebalo da posvetite posebnu pa`nju.
Prvi zadatak koji treba da izvr{i stranica na kojoj se obavlja rukovanje sesijama je utvr|ivanje
postojanja validne sesije, {to za posledicu ima kori{}enje postoje}e sesije ili iniciranje nove sesije. Ukoliko ne postoji validna sesija, neophodno je inicirati novu sesiju i povezati je sa odgovaraju}im korisnikom, kori{}enjem jednog od metoda za prosle|ivanje identifikatora sesije, koji
su opisani u prethodnom odeljku. PHP omogu}ava identifikovanje postoje}e sesije
pronala`enjem identifikatora sesije, bilo u zahtevanoj URL adresi ili u kola~i}u. Me|utim, to
mo`ete da uradite i programskim putem. Na primer, ukoliko je naziv sesije sid, a ona je postavljena iza odgovaraju}e URL adrese, vrednost mo`ete da o~itate na slede}i na~in:
$_GET['sid']
Ukoliko je identifikator sesije zabele`en u odgovaraju}em kola~i}u, mo`ete ga o~itati na slede}i
na~in:
$_COOKIE['sid']

447

PHP i MySQL od po~etnika do profesionalca

Nakon utvr|ivanja identifikatora sesije, mo`ete po~eti da bele`ite informacije vezane za dati
identifikator sesije, a mo`ete i da o~itate prethodno zabele`ene podatke za taj identifikator sesije. Na primer, pretpostavimo da korisnik pregleda razli~ite novinske ~lanke na odgovaraju}oj
stranici. Identifikatori novinskih ~lanaka mogu da se pove`u sa odgovaraju}im identifikatorom
sesije, tako da mo`ete da napravite listu novinskih ~lanaka kojima je pristupio odgovaraju}i
korisnik, odnosno mo`ete da prika`ete tu listu ukoliko korisnik nastavi sa ~itanjem. U narednim
odeljcima }ete imati priliku da nau~ite kako da snimate, odnosno o~itavate odgovaraju}e
informacije vezane za konkretnu sesiju.
SAVET
Informacije o kola~i}ima mo`ete da o~itavate putem $_REQUEST superglobalne promenljive. Na primer, ukoliko je naziv sesije sid, tada }ete pomo}u $_REQUEST odrediti identifikator sesije, kao da ste koristili $_COOKIE['sid']. Me|utim, da bi bilo jasnije, razmotrite kori{}enje superglobalne promenljive koja se na najbolji
na~in uklapa sa mestom nastanka promenljive.

Ovaj proces se nastavlja sve dok korisnik ne zatvori Web ~ita~ ili ne pristupi nekoj drugoj web
prezentaciji. Ukoliko se koriste kola~i}i, tada se defini{e trajanje kola~i}a tako {to se odredi neki
datum u budu}nosti, uz pretpostavku da }e korisnik ponovo pristupiti va{oj prezentaciji pre isteka tog roka, ~ime }e sesija ostati nepromenjena, kao da korisnik nije ni napu{tao va{u web
prezentaciju. Ukoliko koristite modifikovanje URL adrese, sesija se zavr{ava onda kada korisnik
napusti stranicu, a nova sesija mora da po~ne slede}i put kada korisnik poseti stranicu. U narednim odeljcima }ete imati priliku da nau~ite ne{to vi{e o konfiguracionim direktivama i funkcijama koje su odgovorne za izvr{avanje prethodno opisanog procesa.

Konfiguracione direktive
Postoji skoro 30 konfiguracionih direktiva koje se koriste za rukovanje sesijama u programskom
jeziku PHP. Po{to mnoge od ovih direktiva igraju veoma zna~ajnu ulogu u utvr|ivanju
funkcionisanja celokupnog PHP okru`enja, trebalo bi da posvetite odre|eno vreme kako biste u
potpunosti ovladali ovim direktivama i mogu}im pode{avanjima. Najzna~ajnije direktive su
opisane u ovom odeljku.

Upravljanje medijumom za sme{tanje informacija o sesijama


session.save_handler direktivom se utvr|uje koli~ina informacija koja }e se bele`iti o odgovara-

ju}oj sesiji. Prototip ove funkcije je slede}eg oblika:


session.save_handler = files|mm|sqlite|user
Podaci o sesiji se mogu sme{tati na ~etiri na~ina: unutar obi~nih datoteka (files), u privremenoj memoriji (mm), kori{}enjem SQLite baze podataka (sqlite), ili putem korisni~ki definisanih funkcija (user). Iako je podrazumevano pode{avanje vezano za sme{tanje podataka o sesijama u obi~nim datotekama ne{to {to }e zadovoljiti zahteve vezane za veliki broj stranica, vodite

448

Rukovanje sesijama

POGLAVLJE 18

ra~una o tome da aktivne web stranice mogu da imaju i po nekoliko hiljada datoteka sa podacima o sesijama, pa ~ak i nekoliko stotina hiljada takvih datoteka nakon odre|enog perioda
funkcionisanja.
Opcija vezana za kori{}enje privremene memorije je nabr`e re{enje za upravljanje podacima o
sesijama, ali je problem {to se za sme{tanje koristi RAM memorija. Sqlite opcija omogu}ava
kori{}enje novog SQLite pro{irenja, kako bi se informacijama o sesijama upravljalo transparentno, kori{}enjem ove baze podataka (vi{e informacija o SQLite bazi podataka mo`ete da
prona|ete u poglavlju 22). ^etvrta opcija, iako je najslo`enija za konfigurisanje, predstavlja
najfleksibilniju i najmo}niju opciju, zato {to korisni~ki definisani rukovaoci sesijama mogu da se
kreiraju tako da se informacije o sesijama sme{taju na medijumu koji defini{e programer. U
ovom poglavlju }ete imati priliku da nau~ite kako da koristite ovu opciju za sme{tanje podataka
o sesijama u odgovaraju}oj MySQL bazi podataka.

Pode{avanje putanje za datoteke sesije


Ukoliko je pomo}u session.save_handler direktive definisano da se koriste datoteke za sme{tanje
podataka o sesiji, tada pomo}u session.save_path direktive morate da defini{ete kako }ete identifikovati direktorijum za snimanje. Ova direktiva je slede}eg oblika:
session.save_path = string
Prema definiciji, session.save_path direktiva ima vrednost /tmp. Vodite ra~una o tome da direktorijum ne sme da bude postavljen u korenom direktorijumu servera, zato {to ovi podaci mogu
veoma jednostavno da budu prikazivani u Web ~ita~u. Pored toga, ovaj direktorijum mora da
bude dostupan za upisivanje.
Zbog pove}avanja efikasnosti, session.save_path direktivu mo`ete da defini{ete kori{}enjem
sintakse N;/putanja, gde je N ceo broj koji predstavlja broj poddirektorijuma koji su na nivou N
prilikom sme{tanja podataka o samoj sesiji. To je korisno, ukoliko session.save_handler direktiva defini{e kori{}enje datoteka, a va{a web prezentacija obra|uje veliki broj sesija, po{to je
omogu}eno mnogo efikasnije sme{tanje datoteka o sesijama u nekoliko razli~itih direktorijuma,
a ne u jednom, monolitnom direktorijumu. Ukoliko odlu~ite da iskoristite ovu funkcionalnost,
PHP ne}e automatski kreirati direktorijume umesto vas. Me|utim, korisnici Linux operativnog
sistema mogu da automatizuju proces izvr{avanjem skripta mod_files.sh, koji je lociran u
ext/session direktorijumu. Ukoliko koristite Windows operativni sistem, ovaj shell skript nije
podr`an, iako kreiranje kompatibilnosg skripta pomo}u VBScript jezika predstavlja veoma jednostavan posao.

Automatsko omogu}avanje kori{}enja sesija


Prema definiciji, za odgovaraju}u stranicu }ete mo}i da koristite sesije jedino ukoliko se izvr{i
session_start() funkcija (koja }e detaljno biti opisana ne{to kasnije u toku ovog poglavlja).
Me|utim, ukoliko planirate da koristite sesije na celoj web prezentaciji, ovu funkciju mo`ete da

449

PHP i MySQL od po~etnika do profesionalca

izbegnete ukoliko setting session.auto_start direktivom defini{ete vrednost 1. Ova direktiva je


slede}eg oblika:
session.auto_start = 0|1
Jedna od posledica kori{}enja ove direktive je da se spre~ava sme{tanje objekata u toku sesije,
zato {to definicija klase mora da bude u~itana pre nego {to se po~ne sa sesijom, kako bi se
objekti ponovo kreirali. Po{to session.auto_start direktiva mo`e to da spre~i, neophodno je da
defini{ete vrednost 0 ukoliko `elite da upravljate objektima unutar sesija.

Definisanje naziva sesije


Prema definiciji, PHP koristi naziv sesije u obliku PHPSESSID. Me|utim, vi sasvim slobodno
mo`ete da menjate ovaj naziv kori{}enjem session.name direktive. Ova direktiva je slede}eg
oblika:
session.name = string

Kori{}enje kola~i}a ili modifikovanje URL adrese


Ukoliko `elite da rukujete sesijama korisnika u toku ve}eg broja poseta va{oj prezentaciji, trebalo bi da koristite kola~i}e, tako da identifikator sesije mo`e biti kasnije ponovo kori{}en. Ukoliko
se korisni~ki podaci koriste samo u toku jedne posete va{oj prezentaciji, tada }e biti sasvim
dovoljno da koristite modifikovanje URL adrese (iako i pri tome morate da vodite ra~una o
bezbednosnim problemima koji su vezani za modifikovanje URL adrese, a koji su navedeni u
toku ovog poglavlja). Metod koji }ete da koristite mo`ete da izaberete pomo}u using
session.use_cookies direktive. Ukoliko defini{ete vrednost 1 (podrazumevana vrednost), koristi}e

se kola~i}i za ~uvanje identifikatora sesije; ukoliko defini{ete vrednost 0, primenjiva}e se postupak modifikovanja URL adrese. Ova direktiva je slede}eg oblika:
session.use_cookies = 0|1
Vodite ra~una o tome da, ukoliko je omogu}ena session.use_cookies direktiva, ne postoji
potreba da eksplicitno izvr{avate funkciju za pode{avanje kola~i}a (na primer, PHP funkciju
set_cookie()), zato {to se ovo automatski defini{e pomo}u bilioteke za upravljanje sesijama.
Ukoliko izaberete da koristite kola~i}e kao metod za pra}enje korisni~kih sesija, tada morate da
uzmete u razmatranje i nekoliko drugih direktiva koje su opisane u daljem tekstu.

Automatsko modifikovanje URL adrese


Ukoliko je session.use_cookies direktiva onemogu}ena, jedinstveni identifikator sesije korisnika
mora da bude postavljen u URL adresu, kako bi se obezbedilo prosle|ivanje identifikatora. Ovo
mo`e da se realizuje ili eksplicitno, ru~nim dodavanjem $SID promenljive na kraj svake URL
adrese, ili automatski, omogu}avanjem direktive session.use_trans_sid. Ova direktiva je slede}eg
oblika:

450

Rukovanje sesijama

POGLAVLJE 18

session.use_trans_sid = 0|1
Ne iznena|uje da, ukoliko koristite modifikovanje URL adresa, treba da omogu}ite ovu direktivu, kako biste eliminisali mogu}e ljudske gre{ke u procesu modifikovanja.

Pode{avanje trajanja sesije definisane kola~i}ima


session.cookie_lifetime direktiva utvr|uje period validnosti sesije definisane kola~i}em. Ova

direktiva je slede}eg oblika:


session.cookie_lifetime = integer
Vreme `ivota je definisano u sekundama, pa ukoliko kola~i} mo`e da se koristi jedan sat,
neophodno je da ceo broj bude 3600. Ukoliko je u direktivi naveden broj 0 (podrazumevana
vrednost), tada }e kola~i} da egzistira sve dok se ~ita~ ponovo ne startuje.

Pode{avanje validne URL putanje sesije definisane kola~i}em


Direktiva session.cookie_path koristi se za definisanje putanje na kojoj se kola~i} smatra validnim. Kola~i} je validan i ukoliko se nalazi u svim direktorijumima ni`eg nivoa na definisanoj
putanji. Ova direktiva ima slede}i oblik:
session.cookie_path = string
Na primer, ukoliko je u direktivi naveden /, tada je kola~i} validan za celu web prezentaciju.
Navo|enje /books direktorijuma uzrokuje da kola~i} bude validan samo ukoliko se poziva unutar
http://www.example.com/books/ putanje.

Pode{avanje validnog domena sesije definisane kola~i}em


Direktiva session.cookie_domain utvr|uje domen za koji se kola~i} smatra validnim. Ova direktiva je neophodna zato {to spre~ava da se iz drugih domena omogu}i o~itavanje kola~i}a definisanog u va{em domenu. Ova direktiva je slede}eg oblika:
session.cookie_domain = string
U slede}em primeru je prikazano njeno kori{}enje:
session.cookie_domain = www.example.com

451

PHP i MySQL od po~etnika do profesionalca

Ukoliko `elite da odgovaraju}a sesija bude dostupna u razli~itim poddomenima va{e web
prezentacije, recimo domenima customers. example.com, intranet.example.com i www2.example.com,
tada je neophodno da direktivu iskoristite na slede}i na~in:

Validacija sesija upu}ivanjem


Primena metoda modifikovanja URL adresa za prosle|ivanje identifikatora sesije omogu}ava da
konkretno stanje sesije mo`e da bude pregledano od strane velikog broja korisnika kopiranjem i
umno`avanjem odre|ene URL adrese. session.referer_check direktiva se koristi kako bi smanjila
ovu mogu}nost, navo|enjem podstringa koji ukazuje na korisnika. Ukoliko korisnik nije sadr`an
u navedenom stringu, to zna~i da identifikator sesije nije validan. Direktiva je slede}eg oblika:
session.referer_check = string

Pode{avanje mogu}nosti ke{iranja za stranice


koje se koriste u sesiji
Prilikom rada sa sesijama, mo`da }ete po`eleti da imate vi{i nivo kontrole nad stranicama koje
se mogu koristiti u sesijama, a koje se ke{iraju u ~ita~u korisnika, kao i u svim proksijima koji se
nalaze izme|u servera i korisnika. session.cache_limiter direktiva se koristi za modifikovanje
zaglavlja ovih ke{iranih stranica, ~ime se obezbe|uju instrukcije vezane za karakteristike ke{iranja. Ova direktiva je slede}eg oblika:
session.cache_limiter = string
Mogu se koristiti slede}e vrednosti:
none: Ovim pode{avanjem se onemogu}ava prosle|ivanje svih kontrolnih zaglavlja

ke{a izme|u stranica koje se koriste u sesiji.


nocache: Ovo je podrazumevano pode{avanje. Ovim pode{avanjem se omogu}ava da
svaki zahtev bude prvo prosle|en do servera, pre nego {to bude ponu|ena potencijalno ke{irana verzija.
private: Ukoliko ke{irani dokument ozna~ite kao privatan, zna~i da }e dokument biti

raspolo`iv isklju~ivo originalnom korisniku. Ovaj dokument ne}e mo}i da se deli sa


drugim korisnicima.
private_no_expire: Ovo je varijacija prethodnog primera, pri ~emu sada ne postoji
definisano vremensko ograni~enje u ~ita~u. Ova vrednost se dodaje kako bi se prevazi{ao problem vezan za Expire zaglavlje koje se {alje kada se direktiva koristi uz
navo|enje vrednosti private, {to mo`e da zbuni neke Web ~ita~e.
public: Ovo pode{avanje omogu}ava da se ke{iraju svi dokumenti, ~ak i kada je za
originalni dokument neophodna provera autenti~nosti.

452

Rukovanje sesijama

POGLAVLJE 18

Definisanje vremena zastarevanja ke{a prilikom kori{}enja sesija


session.cache_expire direktiva koristi se prilikom definisanja vremenskog perioda, izra`enog u

sekundama (podrazumevana vrednost je 180 sekundi), u kome su ke{irane stranice raspolo`ive


pre kreiranja novih stranica. Ova direktiva je slede}eg oblika:
session.cache_expire = integer
Ukoliko session.cache_limiter direktiva ima vrednost nocache, direktiva se ignori{e.

Definisanje trajanja sesije


session.gc_maxlifetime direktiva se koristi za definisanje trajanja sesije, pri ~emu je trajanje

izra`eno u sekundama (podrazumevana vrednost iznosi 1440 sekundi), i u toku tog vremena se
sesija smatra validnom. Prototip ove direktive je slede}eg oblika:
session.gc_maxlifetime = ceobroj
Nakon {to istekne definisani vremenski interval, uklanjaju se sve informacije vezane za sesiju,
odnosno osloba|aju svi sistemski resursi, koji se mogu dodeljivati nekoj drugoj sesiji.

Kori{}enje sesija
U ovom odeljku su opisani brojni klju~ni zadaci vezani za rukovanje sesijama, koji se realizuju
pomo}u odgovaraju}ih funkcija za upravljanje sesijama. Neki od ovih zadataka podrazumevaju
kreiranje i uklanjanje sesija, definisanje i o~itavanje identifikatora sesije, odnosno sme{tanje i
o~itavanje promenljivih vezanih za sesije. U ovom uvodu su prikazane osnove neophodne za
razumevanje narednog odeljka, u kome su navedeni neki prakti~ni primeri vezani za upravljanje
sesijama.

Kreiranje sesije
Zapamtite da je HTTP protokol bez stanja, tako da ne sadr`i nikakve informacije o prethodnim
ili budu}im pona{anjima korisnika. Zbog toga je neophodno da eksplicitno inicirate sesiju, a
zatim je nastavite kada je to neophodno. Oba zadatka se realizuju pomo}u session_start() funkcije. Prototip ove funkcije je slede}eg oblika:
boolean session_start()
Izvr{avanjem session_start() funkcije kreira}e se nova sesija ukoliko nije definisan nijedan
identifikator sesije, ili }e se nastaviti prethodno zapo~eta sesija ukoliko postoji odgovaraju}i identifikator sesije. Ovu funkciju koristite veoma jednostavno, tako {to }ete je izvr{iti na slede}i na~in:
session_start();
Uo~ite da session_start() funkcija izve{tava o uspe{nom ishodu, nezavisno od rezultata. Zbog
toga je u ovoj situaciji dobro re{enje da koristite neki metod za rukovanje izuzecima.

453

PHP i MySQL od po~etnika do profesionalca

Izvr{avanje ove funkcije mo`ete da elimini{ete omogu}avanjem konfiguracione direktive


session.auto_start. Me|utim, vodite ra~una o tome da }ete time po~eti novu sesiju ili nastaviti

postoje}u sesiju za svaku PHP stranicu.

Uklanjanje sesije
Iako mo`ete da konfiguri{ete PHP direktive za rukovanje sesijama, kako bi se automatski uklonila sesija nakon isteka unapred definisanog vremena za trajanje sesije ili na osnovu verovatno}e,
ponekad je mnogo korisnije da ru~no uklonite sesiju. Na primer, mo`da `elite da omogu}ite da
korisnik samostalno napusti stranicu tako {to se izloguje. Kada korisnik pritisne odgovaraju}i
link, vi mo`ete da uklonite iz memorije sve promenljive koje su vezane za tu sesiju, pa ~ak i da u
potpunosti uklonite podatke o sesiji sa odgovaraju}eg memorijskog medijuma, {to se realizuje
pomo}u funkcija session_unset() i session_destroy(), respektivno.
session_unset() funkcija se koristi za uklanjanje svih promenljivih vezanih za trenutnu sesiju,
pri ~emu se efektivno vra}a stanje sesije, koje je bilo nakon njenog kreiranja (nisu registrovane
promenljive vezane za sesiju). Prototip ove funkcije je slede}eg oblika:

void session_unset()
Iako se izvr{avanjem session_unset() funkcije zaista uklanjaju sve promenljive vezane za
trenutno aktivnu sesiju, sesija ne}e biti u potpunosti uklonjena sa odgovaraju}eg medijuma za
sme{tanje.
Ukoliko `elite da u potpunosti uklonite sesiju, neophodno je da upotrebite funkciju
session_destroy(), koja trenutnu sesiju progla{ava neva`e}om, a zatim je u potpunosti uklanja sa
medijuma za sme{tanje sesija. Vodite ra~una o tome da na ovaj na~in ne}ete ukloniti i kola~i}e
koji su sme{teni u korisni~kim ~ita~ima. Prototip ove funkcije je slede}eg oblika:
boolean session_destroy()
Ukoliko niste zainteresovani za kori{}enje kola~i}a nakon zavr{etka sesije, jednostavno
pomo}u session.cookie_lifetime direktive defini{ite vrednost 0 (podrazumevana vrednost) u
php.ini datoteci.

Definisanje i o~itavanje identifikatora sesije


Zapamtite da identifikator sesije, zapravo, povezuje sve podatke sesije sa konkretnim korisnikom.
Iako PHP omogu}ava autonomno kreiranje i prosle|ivanje identifikatora sesije, postoje situacije
u kojima mo`da `elite da ru~no postavite ili o~itate identitikator. Funkcija session_id() mo`e da
se koristi za izvr{avanje oba zadatka. Prototip ove funkcije je slede}eg oblika:
string session_id([string sid])

454

Rukovanje sesijama

POGLAVLJE 18

Funkcija session_id() se mo`e koristiti i za definisanje i za o~itavanje vrednosti identifikatora


sesije. Ukoliko nije naveden opcioni parametar, funkcija session_id() vra}a identifikator
trenutno aktivne sesije. Ukoliko je naveden opcioni parametar sid, tada }e trenutna vrednost
identifkatora sesije biti zamenjena tom vredno{}u. Kori{}enje ove funkcije je prikazano u
slede}em primeru:
<?php
session_start();
echo "Your session identification number is ".session_id();
?>
Prilikom izvr{avanja ovog skripta dobija se slede}i rezultat:
Your session identification number is 967d992a949114ee9832f1c11c

Kreiranje i uklanjanje promenljivih sesije


Promenljive sesije se koriste za upravljanje podacima koji treba da budu vezani za korisnika, kako
on pristupa odgovaraju}im stranicama na va{oj prezentaciji. Me|utim, danas preporu~eni metod
podrazumeva jednostavno definisanje i uklanjanje ovih promenljivih na isti na~in kao {to se to
radi sa bilo kojom drugom promenljivom, osim {to je neophodno da uka`ete na njih u
kontekstu $_SESSION superglobalne promenljive. Na primer, pretpostavimo da `elite da defini{ete
promenljivu sesije koja se naziva username, {to je prikazano u slede}em skriptu:
<?php
session_start();
$_SESSION['username'] = "jason";
printf("Your username is %s.", $_SESSION['username']);
?>
Izvr{avanjem prethodnog primera dobija se slede}i rezultat:
Your username is jason.
Da biste uklonili promenljivu, neophodno je da iskoristite funkciju unset(), kao {to je
prikazano u slede}em primeru:
<?php
session_start();
$_SESSION['username'] = "jason";
printf("Your username is: %s <br />", $_SESSION['username']);
unset($_SESSION['username']);
printf("Username now set to: %s", $_SESSION['username']);
?>

455

PHP i MySQL od po~etnika do profesionalca

Izvr{avanjem prethodnog primera dobija se slede}i rezultat:


Your username is: jason
Username now set to:

UPOZORENJE
Mo`da }ete imati priliku da se susretnete sa nekim starijim dokumentima i diskusijama koje ukazuju na
funkcije session_register() i session_unregister(), koje su nekada bile preporu~eni na~in za kreiranje
i uklanjanje promenljivih vezanih za sesije, respektivno. Me|utim, zato {to ove funkcije zavise od konfiguracione direktive register_globals, koja je prema definiciji onemogu}ena po~ev{i od PHP verzije 4.2.0,
odnosno u potpunosti uklonjena u PHP verziji 6.0, umesto toga trebalo bi da koristite metode za dodeljivanje i uklanjanje promenljivih koji su opisani u ovom odeljku.

Kodiranje i dekodiranje podataka sesije


Nezavisno od medijuma kori{}enog za skladi{tenje, PHP sme{ta podatke o sesijama u standardizovanom formatu, koji se sastoji od odgovarajue}g stringa. Na primer, sadr`aj sesije sastoji se od
dve promenljive, username i loggedon, i slede}eg je oblika:
username|s:5:"jason";loggedon|s:20:"Feb 16 2008 22:32:29";
Svaka referenca na promenljivu sesije je izdvojena ta~kom i zarezom, i sastoji se od tri komponente: naziva, du`ine i vrednosti. Op{ti oblik sintakse je:
name|s:length:"value";
Na sre}u, PHP autonomno rukuje kodiranjem i dekodiranjem sesije. Me|utim, ponekad }ete
mo`da po`eleti da izvr{ite i ru~no ove zadatke. Na raspolaganju imate dve funkcije:
session_encode() i session_decode(), respektivno.

Kodiranje podataka sesije


session_encode() funkcija vam omogu}ava da na veoma jednostavan na~in ru~no kodirate sve

promenljive vezane za sesiju pomo}u jednog stringa. Prototip ove funkcije je slede}eg oblika:
string session_encode()
Nakon toga, ovaj string mo`ete da postavite u bazu podataka, odnosno mo`ete ga kasnije
o~itavati, odnosno dekodirati pomo}u session_decode() funkcije.

456

Rukovanje sesijama

POGLAVLJE 18

Na primer, pretpostavimo da kola~i} sadr`i identifikator sesije korisnika i da je sme{ten na njegovom ra~unaru. U trenutku kada korisnik zahteva u~itavanje odgovaraju}e stranice koja sadr`i
slede}i listing, identifikator korisnika se o~itava iz kola~i}a. Ova vrednost se zatim tretira kao
identifikator sesije. Kreiraju se odgovaraju}e promenljive sesije, a zatim im se dodeljuje neophodna vrednost i nakon toga se sve ove informacije kodiraju kori{}enjem session_encode() funkcije,
~ime se pripremaju za unos u bazu podataka.
<?php
// Iniciranje sesije i kreiranje nekoliko promenljivih sesije
session_start();

// Definisanje vrednosti za nekoliko promenljivih sesije.


$_SESSION['username'] = "jason";
$_SESSION['loggedon'] = date("M d Y H:i:s");

// Kodiranje svih podataka sesije u jedan string i prikazivanje rezultata


$sessionVars = session_encode();
echo $sessionVars;
?>
Izvr{avanjem prethodnog koda dobija se slede}i rezultat:
username|s:5:"jason";loggedon|s:20:"Feb 16 2008 22:32:29";
Vodite ra~una o tome da session_encode() funkcija kodira sve promenljive sesije koje su
definisane za posmatranog korisnika, a ne samo one koje su vezane za konkretan skript u kome
se izvr{ava session_encode() funkcija.

Dekodiranje podataka sesije


Kodirani podaci vezani za sesiju se mogu dekodirati pomo}u session_decode() funkcije. Prototip
ove funkcije je slede}eg oblika:
boolean session_decode(string podaci_sesije)
Ulazni parametar podaci_sesije predstavlja kodirani string kojim su predstavljene promenljive
sesije. Funkcija se koristi za dekodiranje ovih promenljivih, pri ~emu se one vra}aju u provobitni format, a izvr{avanjem ove funkcije dobija se vrednost TRUE ukoliko je dekodiranje uspe{no
obavljeno, odnosno vrednost FALSE, u suprotnom. Nastavljaju}i sa prethodnim primerom, pretpostavimo da su neki podaci vezani za sesiju kodirani i postavljeni u bazu podataka, konkretno,
identifikator sesije i promenljive $_SESSION['username'] i $_SESSION['loggedon']. Slede}i skript se
koristi za o~itavanje tih podataka iz odgovaraju}e tabele baze podataka, odnosno njihovo
dekodiranje, ~ime se oni vra}aju u prvobitni oblik:

457

PHP i MySQL od po~etnika do profesionalca

<?php
session_start();
$sid = session_id();

// Kodirani podaci, koji su ocitani iz baze podataka, predstavljeni su u sledecem


obliku:
// $sessionVars = username|s:5:"jason";loggedon|s:20:"Feb 16 2008
22:32:29";

session_decode($sessionVars);

echo "User ".$_SESSION['username']." logged on at ".$_SESSION['loggedon'].".";

?>
Izvr{avanjem prethodnog skripta dobija se slede}i rezultat:
User jason logged on at Feb 16 2008 22:55:22.
Cilj ovog hipoteti~kog primera bio je da vam demonstrira kori{}enje PHP funkcija za kodiranje i dekodiranje. Ukoliko zaista `elite da snimate podatke vezane za sesije u bazu podataka, za to
postoji mnogo efikasniji metod, koji podazumeva definisanje odgovaraju}eg rukovaoca sesijama,
odnosno postavljanje tih rukovaoca direktno u API interfejs PHP okru`enja. Kako se ovo
realizuje, prikazano je kasnije u toku ovog poglavlja.

Prakti~ni primeri vezani za rukovanje sesijama


Po{to ste sada upoznati sa osnovnim funkcijama koje se koriste prilikom rukovanja sesijama,
spremni ste da razmotrite i neke realne primere. U prvom primeru opisan je postupak kreiranja
mehanizma koji automatski proverava autenti~nost i vra}a registrovane korisnike stranice. U drugom primeru je prikazano kori{}enje promenljivih sesije u cilju kreiranja indeksa dokumenata
koje je prethodno pregledao odgovaraju}i korisnik. Oba primera su prili~no op{ta, ali to ne sme
da vas iznenadi, s obzirom na njihovu o~iglednu korist. Ono {to mo`e da vas iznenadi je jednostavnost kreiranja ovakvih skriptova.
NAPOMENA
Ukoliko niste do sada koristili MySQL bazu podataka i zbunjeni ste sintaksom koja je iskori{}ena u slede}im
primerima, obratite pa`nju na tekst koji se nalazi u poglavlju 30.

458

Rukovanje sesijama

POGLAVLJE 18

Automatsko prijavljivanje i prikazivanje korisnika


Nakon {to se korisnik prijavi, obi~no navo|enjem korisni~kog imena i {ifre, pomo}u kojih se
jednozna~no identifikuje taj korisnik, ~esto je zgodno da omogu}ite korisniku da se kasnije
ponovo vrati na stranicu, a da pri tome ne mora da ponovi postupak prijavljivanja. Ovo mo`ete
veoma jednostavno da ostvarite pomo}u sesija, nekoliko promenljivih vezanih za sesije i odgovaraju}e MySQL tabele. Iako postoji mnogo na~ina za implementiranje ove funkcionalnosti,
provera postoje}e promenljive vezane za sesiju (konkretno, $username promenljive) je sasvim
dovoljna. Ukoliko postoji ova promenljiva, korisnik mo`e automatski da pristupi stranici.
Ukoliko ova promenljiva ne postoji, prikazuje se odgovaraju}a forma za prijavljivanje.
NAPOMENA
Prema definiciji, session.cookie_lifetime konfiguraciona direktiva ima vrednost 0, {to zna~i da se kola~i}
uklanja prilikom restartovanja ~ita~a. Zbog toga bi trebalo da ovu vrednost promenite, tako da predstavlja
broj sekundi, kako biste omogu}ili da sesija postoji odgovaraju}i vremenski period.

MySQL tabela, pod nazivom users, prikazana je u listingu 18.1.


CREATE TABLE users (
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
username VARCHAR(10) NOT NULL,
pswd VARCHAR(10) NOT NULL,
PRIMARY KEY(id)
);
Kod (koji se nalazi u login.html datoteci) koji je prikazan u slede}em primeru, koristi se za
prikazivanje forme za prijavu, ukoliko ne postoji validna sesija za odgovaraju}eg korisnika:
<p>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
Username:<br /><input type="text" name="username" size="10" /><br />
Password:<br /><input type="password" name="pswd" SIZE="10" /><br />
<input type="submit" value="Login" />
</form>
</p>
Kona~no, logika koja se koristi za upravljanje procesom automatskog prijavljivanja je slede}eg
oblika:

459

PHP i MySQL od po~etnika do profesionalca

<?php
session_start();
// Da li je sesija prethodno inicirana?
if (! isset($_SESSION['username'])) {
// Ukoliko postoji prethodno inicirana sesija, da li je ona vezana
// za odgovarajuceg korisnika?
if (isset($_POST['username']))
{
$username = mysqli_real_escape_string($_POST['username']);
$pswd = mysqli_real_escape_string($_POST['pswd']);
// Povezivanje na MySQL server i selektovanje odgovarajuce baze podataka.
mysql_connect("localhost","webuser","secret");
mysql_select_db("chapter18");
// Pretraga odgovarajuceg korisnika u users tabeli.
$query = "SELECT username FROM users
WHERE username='$username' AND pswd='$pswd'";
$result = mysql_query($query);
// Da li je odgovarajuci korisnik pronadjen u users tabeli?
if (mysql_numrows($result) == 1)
{
$_SESSION['username'] = mysql_result($result,0,"username");
echo "You've successfully logged in. ";
}
// Ukoliko korisnik nije prethodno prijavljen na sistem, prikazuje se
forma za prijavljivanje.
} else {
include "login.html";
}
// Korisnik se vratio. Prikazati poruku dobrodoslice.
} else {
printf("Welcome back, %s!", $_SESSION['username']);
}
?>

460

Rukovanje sesijama

POGLAVLJE 18

Po{to su danas korisnici zatrpani razli~itim korisni~kim imenima i {iframa, koje omogu}avaju
pristupanje razli~itim sistemima i kori{}enje razli~itih usluga, od provere elektronske po{te i
produ`avanja iznajmljivanja knjiga iz biblioteke, do pregledanja stanja na bankovnom ra~unu,
obezbe|ivanje automatskog prijavljivanja, kada to situacija dozvoljava, bi}e veoma dobro prihva}eno od strane korisnika va{e aplikacije.

Generisanje indeksa nedavno pregledanih dokumenata


Koliko puta ste se vratili na neku web prezentaciju, razmi{ljaju}i gde ste ta~no prona{li odgovaraju}e uputstvo vezano za programski jezik PHP, ~iju ste adresu zaboravili da zabele`ite? Da li
bi bilo korisno da web stranica zabele`i podatke o ~lancima koje ste prethodno pregledali, i da
vam te podatke prika`e kada vam je to neophodno? U slede}em primeru prikazana je ova
funkcionalnost.
Re{enje je iznena|uju}e jednostavno, ali je veoma efektno. Da biste zapamtili koja je dokumenta ~itao posmatrani korisnik, neophodno je da pomo}u jedinstvenog identifikatora identifikujete svakog pojedina~nog korisnika i svaki pojedina~ni dokument. Kada se radi o korisniku,
ovaj zahtev ispunjava identifikator sesije. Dokumenti se mogu identifikovati na koji god na~in
`elite, ali u ovom primeru se koristi naslov rada i URL adresa, odnosno pretpostavlja se da je ova
informacija definisana podacima koji se nalaze u bazi podataka, u tabeli articles, koja je slede}eg
oblika:
CREATE TABLE articles (
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
title VARCHAR(50),
content MEDIUMTEXT NOT NULL,
PRIMARY KEY(id)
);
Jedini neophodan zadatak je sme{tanje identifikatora ~lanaka u promenljivama sesije, koji su
implementirani na slede}i na~in:
<?php
// Kreiranje nove sesije
session_start();
// Povezivanje na server i selektovanje baze podataka
mysql_connect("localhost","webuser","secret");
mysql_select_db("chapter18");
// Ocitavanje zeljenog identifikatora clanka
$articleid = mysqli_real_escape_string($_GET['id']);

461

PHP i MySQL od po~etnika do profesionalca

// Korisnik zeli da pregleda clanak, pa se ocitava iz baze podataka


$query = "SELECT title, content FROM articles WHERE id='$id'";
$result = mysql_query($query);

// Prikazivanje rezultata izvrsavanja upita


list($title, $content) = mysql_fetch_row($result);

// Dodavanje naslova clanka i linka u listu


$articlelink = "<a href='article.php?id=$id'>$title</a>";
if (! in_array($articlelink, $_SESSION['articles']))
$_SESSION['articles'][] = $articlelink;

// Prikazivanje liste zahtevanih clanaka


echo "<p>$title</p><p>$content</p>";
echo "<p>Recently Viewed Articles</p>";
echo "<ul>";

foreach($_SESSION['articles'] as $doc) echo "<li>$doc</li>";


echo "</ul>";
?>
Izvr{avanjem prethodnog primera dobija se rezultat sli~an onom koji je prikazan na slici 18.1.

SLIKA 18.1 Pra}enje dokumenata koje je pregledao korisnik

Kreiranje proizvoljnog rukovaoca sesijama


Korisni~ki definisani rukovaoci sesijama nude veliku fleksibilnost u odnosu na ~etiri metoda za
sme{tanje. Implementiranje proizvoljnog rukovaoca sesijama je iznena|uju}e jednostavno, a ostvaruje se u nekoliko koraka. Da biste po~eli njegovo kreiranje, neophodno je da izvr{ite {est

462

Rukovanje sesijama

POGLAVLJE 18

zadataka (definisanih u daljem tekstu) vezanih za kori{}enje lokacija za sme{tanje. Pored toga,
neophodno je da defini{ete parametre za svaku pojedina~nu funkciju, nezavisno od toga da li
va{a konkretna implementacija koristi parametar. U ovom odeljku definisana je namena i struktura ovih {est funkcija. Pored toga, opisana je i session_set_save_handler() funkcija, koja se koristi
za magi~no transformisanje funkcionisanja PHP rukovaoca sesijama u ono {to ste definisali
odgovaraju}im funkcijama. Kona~no, ovaj odeljak sadr`i demonstraciju ove funkcionalnosti,
koja je implementirana pomo}u MySQL baze podataka. Ovu biblioteku mo`ete da koristite u
svojim aplikacijama, koriste}i MySQL tabelu kao primarnu lokaciju za sme{tanje informacija o
pojedina~nim sesijama.
session_open($session_save_path, $session_name): Ova funkcija inicijalizuje sve elemente
koji mogu da se koriste u toku sesije. Dva ulazna parametra, $session_save_path i $session_name, ukazuju na istoimene konfiguracione direktive, koje se nalaze u php.ini
konfiguracionoj datoteci. PHP funkcija get_cfg_var() se koristi za o~itavanje ovih konfiguracionih vrednosti u nekim od primera koji slede.
session_close(): Ova funkcija funkcioni{e sli~no standardnim funkcijama za rukovan-

je, pri ~emu se osloba|aju svi resursi koji su zauzeti pomo}u session_open() funkcije.
Kao {to mo`ete da primetite, ne postoje ulazni parametri za ovu funkciju. Vodite
ra~una o tome da na ovaj na~in ne}ete u potpunosti ukloniti sesiju. To je posao session_destroy() funkcije, koja je opisana na kraju ove liste funkcija.
session_read($sessionID): Ova funkcija se koristi za o~itavanje podataka vezanih za
sesiju, koji su sme{teni na nekom medijumu. Ulazni parametar, $sessionID, ukazuje na
identifikator sesije koji }e se koristiti prilikom identifikovanja podataka vezanih za
konkretnog korisnika.
session_write($sessionID, $value): Ova funkcija se koristi za upisivanje podataka,

vezanih za odgovaraju}u sesiju, na meki medijum za sme{tanje. Ulazni parametar,


$sessionID, je naziv promenljive, a ulazni parametar $sessionID, defini{e podatke
vezane za odgovaraju}u sesiju.
session_destroy($sessionID): Ova funkcija je verovatno poslednja koju }ete izvr{avati u

va{em skriptu. Ona se koristi za uklanjanje sesije i svih promenljivih koje su vezane za
tu sesiju. Ulazni parametar $sessionID ukazuje na identifikator sesije, kojim je definisana trenutno aktivna sesija.
session_garbage_collect($lifetime): Ova funkcija se koristi za efikasno uklanjanje

svih sesija, ~ije je vreme trajanja isteklo. Ulazni parametar $lifetime ukazuje na session.gc_maxlifetime konfiguracionu direktivu sesije, koja se nalazi u php.ini datoteci.

Kori{}enje definisanih funkcija za rukovanje sesijama u PHP kodu


Nakon {to defini{ete {est funkcija za rukovanje, neophodno je da ih pove`ete u jedinstvenu
logiku za upravljanje sesijama u programskom jeziku PHP. To se realizuje prosle|ivanjem naziva ovih funkcija do session_set_save_handler() funkcije. Vodite ra~una o tome da nazive mo`ete

463

PHP i MySQL od po~etnika do profesionalca

sasvim proizvoljno da dajete, ali da morate da defini{ete odgovaraju}i broj i tip parametara,
kao {to je navedeno u prethodnom odeljku, i da oni moraju biti prosle|eni do
session_set_save_handler() funkcije, u slede}em redosledu: open, close, read, write, destroy i

garbage collect.
U slede}em primeru prikazano je kori{}enje ove funkcije:
session_set_save_handler("session_open", "session_close", "session_read",
"session_write", "session_destroy",
"session_garbage_collect");
U narednom odeljku prikazano je kreiranje rukovaoca koji upravljaju informacijama o sesijama pomo}u MySQL baze podataka.

Kori{}enje rukovalaca sesijama, koji koriste


podatke iz MySQL baze podataka
Pre nego {to koristite rukovaoce sesijama, koji koriste podatke iz MySQL baze podataka,
neophodno je da izvr{ite dva zadatka:
1.

Kreiranje baze podataka i tabele koja se koristi za sme{tanje podataka o sesijama.

2.

Kreiranje {est funkcija za rukovanje sesijama.

Slede}a MySQL tabela, sessioninfo, koristi se za sme{tanje podataka vezanih za sesije. Kada se
radi o ovom konkretnm primeru, pretpostavimo da se ova tabela nalazi u odgovaraju}im sesijama za rad sa bazama podataka, iako ovu tabelu mo`ete da postavite gde god `elite.
CREATE TABLE sessioninfo (
SID CHAR(32) NOT NULL,
expiration INT NOT NULL,
value TEXT NOT NULL,
PRIMARY KEY(SID)
);
Listing 18.2 sadr`i definisane MySQL funkcije za rad sa sesijama. Uo~ite da su definisani svi
neophodni rukovaoci, da je obezbe|en odgovaraju}i broj parametara koji se prosle|uju,
nezavisno od toga koji se parametri koriste u samim funkcijama.

464

Rukovanje sesijama

POGLAVLJE 18

Listing 18.2. Rukovalac sesijama, koji koristi podatke iz MySQL baze podataka

<?php

/*
* mysql_session_open()
* Otvara se perzistentna konekcija i selektuje baza podataka.
*/

function mysql_session_open($session_path, $session_name) {

mysql_pconnect("localhost", "sessionmanager", "secret")


or die("Can't connect to MySQL server! ");

mysql_select_db("sessions")
or die("Can't select MySQL sessions database");

} // end mysql_session_open()

/*
* mysql_session_close()
* Nista se, zapravo, ne izvrsava dok je konekcija sa serverom
* perzistentna. Vodite racuna o tome da, iako
* ne radi nista u konkretnoj implementaciji,
* ova funkcija mora biti definisana.
*/

function mysql_session_close() {

return 1;

} // end mysql_session_close()

/*
* mysql_session_select()
* Iz baze podataka ocitavaju se podaci vezani za sesiju
*/

465

PHP i MySQL od po~etnika do profesionalca

function mysql_session_select($SID) {

$query = "SELECT value FROM sessioninfo


WHERE SID = '$SID' AND
expiration > ". time();

$result = mysql_query($query);

if (mysql_num_rows($result)) {

$row=mysql_fetch_assoc($result);
$value = $row['value'];
return $value;

} else {

return "";
}
} // end mysql_session_select()
/*
* mysql_session_write()
* Ova funkcija se koristi za upisivanje podataka, vezanih za sesiju, u bazu podataka.
* If that SID already exists, then the existing data will be updated.
*/

function mysql_session_write($SID, $value) {


// Definisanje vremena trajanja sesije
$lifetime = get_cfg_var("session.gc_maxlifetime");

// Set the session expiration date


$expiration = time() + $lifetime;

466

Rukovanje sesijama

POGLAVLJE 18

// Unos podataka, vezanih za sesiju, u bazu podataka


$query = "INSERT INTO sessioninfo
VALUES('$SID', '$expiration', '$value')";

$result = mysql_query($query);

// Ukoliko upit ne da zeljene rezultate, sesija vec postoji.


// Zbog toga je neophodno samo da azurirate sesiju.

if (! $result) {

$query = "UPDATE sessioninfo SET


expiration = '$expiration',
value = '$value' WHERE
SID = '$SID' AND expiration >". time();

$result = mysql_query($query);

}
} // end mysql_session_write()

/*
* mysql_session_destroy()
* Deletes all session information having input SID (only one row)
*/

function mysql_session_destroy($SID) {

// Delete all session information having a particular SID


$query = "DELETE FROM sessioninfo
WHERE SID = '$SID'";

$result = mysql_query($query);

} // end mysql_session_destroy()

467

PHP i MySQL od po~etnika do profesionalca

/*
* mysql_session_garbage_collect()
* Deletes all sessions that have expired.
*/

function mysql_session_garbage_collect($lifetime) {

// Delete all sessions older than a specific age


$query = "DELETE FROM sessioninfo
WHERE sess_expiration < ".time() - $lifetime;

$result = mysql_query($query);

return mysql_affected_rows($result);

} // end mysql_session_garbage_collect()

?>
Nakon {to defini{ete ove funkcije, mo`ete ih povezati u PHP logiku za rukovanje izvr{avanjem
session_set_save_handler() funkcije. Slede}i kod treba da se na|e na kraju biblioteke, koja je

definisana u listingu 18.2:


session_set_save_handler("mysql_session_open", "mysql_session_close",
"mysql_session_select",
"mysql_session_write",
"mysql_session_destroy",
"mysql_session_garbage_collect");
Da biste testirali implementaciju rukovaoca sesijama, startujte sesiju i registrujte promenljivu
sesije kori{}enjem slede}eg skripta:
<?php
INCLUDE "mysqlsessionhandlers.php";
session_start();
$_SESSION['name'] = "Jason";
?>
Nakon izvr{avanja ovog skripta, pogledajte sadr`aj sessioninfo tabele, kori{}enjem mysql
klijenta:

468

Rukovanje sesijama

POGLAVLJE 18

+---------------------------------------+-------------------+------------------+
| SID | expiration | value |
+---------------------------------------+-------------------+------------------+
| f3c57873f2f0654fe7d09e15a0554f08 | 1068488659 | name|s:5:"Jason"; |
+---------------------------------------+-------------------+------------------+
1 row in set (0.00 sec)
Kao {to ste i o~ekivali, u tabelu je uba~ena odgovaraju}a vrsta, koja sadr`i identifikator sesije i
promenljivu sesije "Jason". Ova informacija je postavljena tako da istekne 1440 sekundi nakon
kreiranja; ova vrednost se izra~unava utvr|ivanjem trenutnog broja sekundi od po~etka Unix
epohe, i dodavanjem vrednosti 1440 na tu vrednost. Uo~ite da iako je 1440 podrazumevano
vreme za isticanje sesije, kao {to je definisano u php.ini datoteci, ovu vrednost mo`ete sasvim slobodno da promenite nekom vredno{}u koja vam odgovara.
Uo~ite da ovo nije jedini na~in za implementiranje ovih procedura, ukoliko se koristi MySQL
baza podataka. Ovu biblioteku mo`ete i samostalno da modifikujete, onako kako vama
odgovara.

Kratak pregled poglavlja


U ovom poglavlju razmatrane su teme vezane za rukovanje sesijama u programskom jeziku PHP.
Nau~ili ste kako da koristite odgovaraju}e konfiguracione direktive, kako biste definisali `eljeno
funkcionisanje, odnosno kako da koristite neke od najva`nijih funkcija, kojima se mo`e
realizovati rukovanje izuzecima u va{im aplikacijama. Poglavlje je zavr{eno navo|enjem realnih
primera, vezanih za implementiranje rukovaoca izuzecima u programskom jeziku PHP, pri ~emu
je prikazano kori{}enje MySQL tabele za ~uvanje podataka o sesijama.
U narednom poglavlju je opisana jo{ jedna veoma zna~ajna napredna, ali istovremeno i veoma
zna~ajna tema: kori{}enje {ablona. Izdvajanje logike aplikacije od prezentacije je tema o kojoj se
neprekidno puno govori i pi{e, i to s razlogom; ukoliko izme{ate logiku aplikacije i na~in prikazivanja podataka, stvori}ete sebi veliki problem u procesu odr`avanja va{e aplikacije. Do sada je
izdvajanje logike i prezentacije u web aplikacijama bilo veoma retko prakti~no primenjivano. Ali,
to jednostavno mora da se uradi na taj na~in!

469

470

You might also like