Professional Documents
Culture Documents
Instalacija PHP-a
Postoji više načina da se PHP instalira na operativni sistem. Ukoliko je reč o Linuxu, instalacija se vrši pri ili posle
instalacije samog OS-a pridruživanjem odgovarajućih servisa iz distribucije OS-a.
Kada je reč o MS Windows, instalacija se generalno može izvršiti na dva načina. Jedan način je ručno, komponentu po
komponentu, a drugi instalacijom nekog paketa koji u sebi sadrži ceo sistem. Ovakvi paketi su izuzetno praktični, i mi
ćemo se orijentisati na jedan od njih – WampServer. Njime ćemo pokriti tri gore pomenuta uslova (PHP, veb server i
4
bazu).
Za potrebe ovih predavanja, preuzmite i instalirajte WampServer sa interneta (http://www.wampserver.com/en/).
Instalacija alata za kodiranje
Za potrebe predavanja, preuzmite i instalirajte alat Notepad++ sa interneta (http://notepad-plus-plus.org/).
Nakon pravilnog podešavanja svih servisa i pripreme alata, moguće je početi sa upotrebom sistema i proizvodnjom
PHP aplikacija. Ipak, da bismo olakšali rad, potrebno je upoznati se sa osnovnim načinom funkcionisanja ovakvog
sistema.
Pre svega, treba pomenuti da pravila pomenuta gore nisu striktna kao što se isprva možda čine. Na primer, ukoliko čak
i ne posedujemo PHP interpreter na sopstvenom računaru, to ne znači da ne možemo da stvorimo kod, a posle ga
aktiviramo na drugom računaru. Takođe, MySql server/baza podataka ne moraju biti na istom računaru na kome je i
veb server. Veb server ne mora biti samo na jednom računaru, niti je uopšte neophodno da to bude baš Apache veb
server (moguće je PHP izvršiti i na MS IIS veb serveru)... Ukratko, postoje razne varijacije koje se mogu implementirati
prema potrebama celog sistema, ali koje su takođe irelevantne u trenutku proučavanja osnova programskog jezika.
Zato, u našem upoznavanju sa jezikom koristimo linearnu proceduru, iako možda ona ne daje najefikasnije rezultate ili
nije savršeno preslikana slika nekog realnog sistema. Ono što je bitno to je da u radnom okruženju stvorimo uslove
bliske produkcionom, kako bi implementacija prošla što bezbolnije.
Ukoliko korisnički zahtev sadrži naziv i tip dokumenta koji postoji na veb serveru u nekom statičkom obliku, veb server
će jednostavno preuzeti dokument sa fajl sistema i isporučiti ga Internetom korisniku. Ali, ukoliko zahtev ne
podrazumeva već postojeći dokument, već zahteva sadržaj koji će biti dinamički generisan, veb server mora stvoriti
odgovor tako što će startovati skriptu koju zahtev sadrži, te njen rezultat implementiran u dokument u kome se skripta
nalazi i proslediti korisniku. Na kraju, s obzirom na to da je pomenuta skripta/program implementirana u neki dokument,
korisnik će dobiti svoj rezultat u formi validnog HTML dokumenta.
Prilikom ovog procesa, veb server i klijent (a kada kažemo klijent mislimo na pretraživač IE, FireFox...) koriste isti jezik
– protokol za komunikaciju. Taj jezik naziva se HTTP (HyperText Transfer Protocol) i osnovni je način komunikacije
između računara na internetu.
Gde se u svemu tome uklapa PHP? Uloga PHP-a je u stvari da prevede i startuje pomenutu skriptu, te da prosledi
dobijeni rezultat klijentu. Treba znati da PHP nije jedini jezik koji može uraditi tako nešto. Postoje i drugi jezici koji se
dobro snalaze u ovom poslu (C#, VB, Java...), uz preduslov da server zna koji od njih i kada treba da startuje i gde da
pronađe interpretere za njih.
Ako bi hteli da ono što smo napisali u prethodnom pasusu, prikažemo kroz sliku, ona bi izgledala odprilike ovako:
Kada zahtev stigne do servera, server razmatra na koji način će ga tretirati. Vidimo da je u prvom redu zahteva,
napisano index.html. To je naziv dokumenta koji klijent traži od servera. S obzirom na to da dokument ima ekstenziju
html, server zaključuje da ne mora da aktivira serverski kod, već samo prosleđuje dokument nazad klijentu (3a).
Ukoliko bi dokument imao ekstenziju .php, server bi angažovao php interpreter i prosledio mu dokument (3b). Php
interpreter bi preveo i izvršio dokument (odnosno, php kod koji se nalazi u njemu), zatim bi kreirao HTTP odgovor (4) i
prosledio ga klijentu. HTTP odgovor nije mnogo različit od HTTP zahteva. U njemu server opisuje dokument koji šalje
klijentu. Jedan deo odgovora izgleda otprilike ovako (4):
HTTP/1.1 200 OK
Connection: close
Content-Type: text/html; charset=UTF-8
Zaključak
Iz ovog uvoda zaključuje se da će krajnji produkt učenja biti proizvodnja PHP skripti u službi HTML-a. To upravo i jeste
cilj jer PHP i dominira u pomenutoj infrastrukturi. Bez HTML-a, učenje PHP-a svelo bi se na suvoparno baratanje
brojevima i matematičkim i logičkim operacijama, uslovima i ostalim kvalifikatorima programskih jezika. Bez ovih
6
komponenti, svakako u PHP-u nećemo daleko dogurati, ali će učenje svakako biti zanimljivije uz povezivanje sa HTML-
om.
Više podataka
Nastanak PHP-a
PHP se u svom najosnovnijem obliku pojavio 1995. godine. Stvorio ga je danski programer Rasmus Lerdorf u želji da
putem skripte prati broj posetilaca veb stranice svog CV-ja. Rasmus je ovaj jezik nazvao Personal Home Pages.
Ova primitivna verzija jezika (nasleđenog od jezika C) bila je samo osnova za njegov dalji razvoj, pa je Ramus vrlo brzo
ovaj svoj projekat deklarisao kao Open Source, kako bi ga uz pomoć većeg broja programera razvio i unapredio.
Najveće unapređenje jezika izvršili su Zeev Suraski i Andi Gutman 1997. godine, preradivši kompletan glavni parser
jezika. Dodavši mu novi naziv (PHP/FI), dodali su i podršku za bazu podataka, čime je jezik dobio formu koju u manjoj
ili većoj meri poseduje i danas.
U ovom trenutku smatra se da oko 60% veb servera na svetu funkcioniše na Apache tehnologiji, pa samim tim, u
velikom broju slučajeva, podrazumeva i obradu podataka u PHP-u. Ako se ovome doda i činjenica da se PHP (doduše,
ne tako često) koristi i na drugim platformama (IIS), jasno je da je u pitanju jezik visoke funkcionalnosti.
Suraski i Gutman (ujedinjeni pod imenom Zend) i danas su glavni Developeri i evangelisti jezika PHP. Puno ime PHP-
a danas je PHP-Hypertext Processor.
Na gore pomenutoj adresi za preuzimanje instalacije PHP-a nalazi se nekoliko fajlova. Jedan od njih se
naziva installer.exe. Ukoliko preuzmete ovaj fajl, njegovim pokretanjem će biti instaliran PHP i automatski podešeni
neki od veb servera. Drugi način instalacije je pomoću .zip fajla sa iste adrese, ali tada morate sami da podešavate i
veb server. Kompletno uputstvo za instalaciju je sastavni deo ovog fajla.
8
Ovakva strana u pretraživaču znači da veb server funkcioniše.
Da biste proverili da li funkcionišu i ostali servisi (PHP i MySql) odaberite jedan od dva hiperlinka ispod podnaslova
Tools (phpinfo() za PHP i phpmyadmin za MySql).
Ukoliko su rezultati dva prozora kao na sledećim slikama, znači da oba servisa (PHP i MySql respektivno) funkcionišu i
time je instalacija uspešno izvršena.
Na kraju, poželjno je omogućiti u pretraživaču učitavanje keširanih strana iznova, kako bi se izbeglo da pretraživač ne
prikaže promene urađene u kodu strane na kojoj radimo.
Da bi se ovo ostvarilo, potrebno je otići na Tools > Internet Options stavku padajućeg menijaInternet Explorera,
9
selektovati opciju Settings iz okvira Temporably Internet Files a zatim u novootvorenom prozoru štiklirati
stavku Every visit to the page. Ovo uradite čak i ako u ovom trenutku za to ne vidite poseban značaj.
10
5.Na poslednjem koraku instalacije ostavite čekirano polje za startovanje aplikacije, i nakon startovanja, u samoj
aplikaciji podesite jezik na PHP, nakon čega je možete zatvoriti.
Nakon što je okruženje pripremljeno za rad, možete kreirati i sopstvenu PHP stranu. Pristupite direktorijumu
c:/wamp/www (uz napomenu da Vam je wamp možda instaliran i u neki drugi direktorijum). Unutar direktorijuma www
možete postaviti neki sopstveni fajl, u kome želite da se nalazi Vaš php kod. Na primer, to može biti fajl test.php.
<?php
echo "Hello!";
?>
http://localhost/test.php
Hello!
11
Rad sa konfiguracionim fajlovima
Wamp u svom korisničkom interfejsu omogućava jednostavan pristup svim konfiguracionim fajlovima servisa koji ispod
njega funkcionišu. Da biste pristupili konfiguracionom fajlu za PHP, potrebno je:
Zatim, iz konzole, locirajte fajl koji ste preuzeli (ime fajla će verovatno biti: php5.x.x.tar.gz, mada tačan naziv zavisi od
verzije PHP-a koju ste skinuli) i pozicionirajte se u taj direktorijum.
Zend Framework je open source framework za razvijanje web aplikacija i servisa korišćenjem PHP 5.3+. S obzirom na
ozbiljnost primene, koristi se u okviru objektno orijentisanih blokova koji izlaze iz okvira ovog kursa, ali nam o njegovoj
upotrebi govori podatak o preko 15 miliona downloadova.
Može se preuzeti sa linka: http://framework.zend.com/downloads/latest
CakePHP je besplatan open sorce, brz razvojni framework za php. Prioriteti razvoja su omogućavanje rada
programerima u strukturiranom i brzom načinu rada bez gubitaka fleksibilnosti. Unapređen je svim potrebnim alatima
koji omogućavaju pisanje koda i baziranje na suštinu dolaska do rešenja. Može se preuzeti sa linka: http://cakephp.org/
Tipovi podataka
Jedinica: 2 od 19
Rezime
Tipovi podataka se u osnovi dele na proste, složene i specijalne
Prosti tipovi su: integer , float, string i boolean, složeni tipovi su: array i object, a specijalni Resource i NULL.
Nizovi sadrže kolekcije podataka istog tipa, pri čemu se u promenljivoj pamti adresa početka ove kolekcije
PHP je u stanju da automatski uzajamno konvertuje proste tipove
Nije moguće konvertovati prosti u složeni tip
Postoji više vrsta notacije numeričkih tipova: oktalna, heksadecimalna, decimalna...
U ovoj lekciji naučićemo koji tipovi podataka postoje u PHP-u. Kada je reč o promenljivim i njihovim tipovima, PHP
ima veoma fleksibilan sistem funkcionisanja. Štaviše, ovaj sistem je toliko fleksibilan da praktično ne moramo ni da
znamo kojim tipovima rukujemo, niti koja su njihova ograničenja. PHP će, jednostavno, pokušati da izvuče ono što
može iz informacija koje su mu date.
No, ovakva otvorenost prema programeru ne znači da tipovi uistinu i ne postoje, već da je rad sa njima enkapsuliran u
ljušturu jednostavnosti, kako bi programiranje bilo lakše i brže.
13
Tipovi u PHP-u
U generalnoj klasifikaciji tipova podataka (i ovo važi za skoro sve programske jezike),
razlikujemoproste i složene tipove. PHP poznaje ove dve vrste tipova i kao skalarne i kompozitne tipove.
Prosti, ili skalarni tipovi, su oni tipovi koji podrazumevaju samo jednu vrednost u jednom trenutku i PHP poznaje četiri
prosta tipa podataka:
Integer: Predstavlja celobrojni tip čija vrednost zavisi od magistrale procesora i okruženja (OS). Ukoliko procesor
radi na 32-bita, veličina ovog tipa može biti od -2147483647 do 2147483647. Za 64-bitni procesor, maksimalna
vrednost ovog tipa je do 9223372036854775807.
Float: Tip float koristi se u PHP-u za sve operacije sa pokretnim zarezom.
String: Tip string sadrži tekstualne vrednosti.
Boolean: Sadrži logičku vrednost (true ili false). Boolean predstavlja dva moguća stanja – tačno i netačno.
Logičke vrednosti se uglavnom koriste za poređenje uslova. U PHP-u netačna vrednost odgovara jednoj od
sledećih vrednosti: celobrojna 0, realna 0.0, prazan string, karakter '0' i konstanta NULL. Svaka druga vrednost se
smatra za tačnu (true).
... i dva složena (kompozitna) tipa.
Složeni tipovi se obično tretiraju kao skladišta, odnosno, kolekcije drugih podataka.
Array: Sadrži niz podataka. Ovaj niz sadrži podakte istih ili različitih tipova bilo koje vrste, pa čak i samih nizova.
Ono što u sebi nosi promenljiva koja reprezentuje ovaj tip, jeste, zapravo memorijska adresa na kojoj kolekcija
ovih podataka počinje.
Object: Sadrži objekat. Što se samih objekata tiče, oni su kompleksne strukture podataka koje sadrže podatke i
funkcionalnost. Objekti su simbol objektno orjentisanog programiranja, i objektno orijentisanih programskih jezika,
u koje spada i PHP, zbog čega ćemo objekte, kroz ovaj kurs, detaljno obraditi.
Pored ove podele, postoji i podela na numeričke tipove, stringove i bulove tipove. Ovo su, zapravo, podkategorije
unutar generalne tipske kategorizacije.
Zbog čega nas ovo uopšte interesuje? Zašto bismo koristili nešto što u sebi sadrži tačnu ili netačnu vrednost, broj ili
tekst?
Pogledajmo Facebook formu za logovanje ili prijavljivanje na sistem:
14
servera, pretvorićemo ga u ovaj tip i nastaviti da radimo sa njim dalje u tom obliku. Datum rođenja se očigledno unosi
kroz tri padajuća menija (select kontrole). Svaki od njih sadrži listu brojeva. I to, celih. Za sve tri informacije, idealan će
biti upravo celobrojni tip (int/Integer), opisan ranije. Konačno, za podatke predstavljene kroz tekst boksove u formi,
veoma verovatno će biti korišćen tip string.
Numerički tipovi
U ovu grupu tipova spadaju integer i float i za njih je karakteristično da čuvaju brojnu vrednost. PHP će, na osnovu
načina na koji smo uneli vrednost, pretpostaviti i njen tip. Već smo pomenuli tip integer. Ovaj tip podrazumeva
označene vrednosti (negativne i pozitivne) u veličini koju dozvoljava sistem. Pri tom, prihvata tri različita tipa notacije:
decimalnu, oktalnu i heksadecimalnu.
Kada je u pitanju decimalna notacija, rukovanje je jednostavno, jer je to notacija kakvu poznajemo i koristimo u
svakodnevnom životu. Na primer, da bismo predstavili broj deset, napisaćemo 10.
Oktalna i heksadecimalna notacija su nešto komplikovanije za upotrebu, ali se i ne koriste tako često. Zapravo, oktalna
notacija najčešće se koristi prilikom rukovanja pravima u UNIX stilu (0666, 0667, 0777).
Obratite pažnju na oktalnu notaciju kada rukujete brojevima. Ova notacija aktivira se oznakom nula ispred broja, što
greškom možete uraditi i prilikom rukovanja decimalnim brojem. Ovo može dovesti do nepravilnih rezultata prilikom
izvršavanja programa.
Na primer 100 u PHP-u označava broj 100 ali 0100 predstavlja broj 64.
Heksadecimalna notacija podrazumeva oznaku 0x (ili 0X, pošto ovaj vid notacije nije osetljiv na velika i mala slova),
nakon koje se ispisuje heksadecimalna vrednost.
Float (naziva se još i double) takođe podrazumeva označene (pozitivne i negativne) vrednosti, ali, za razliku od
integera, ovaj tip prihvata vrednosti sa pokretnim zarezom (decimalne vrednosti).
Float poznaje dva tipa notacije – decimalnu i eksponencijalnu (Decimal i Exponential). Decimal je tradicionalni tip
zapisa: 10.5, 0.55 itd. dok eksponencijalni ima malo ređe korišćenu formu. Eksponencijalni (normalizovani) zapis ćemo
prepoznati po oznaci e (ili E - Takođe nije osetljivo na mala i velika slova), kojoj prethodi osnova broja, a sleduje broj
koji označava broj nula iza množioca.
Na primer:1e2 = 1 * 100 = 100 ili 1.2e2 = 1.2 * 100 = 120
Prilikom rukovanja sa numeričkim tipovima, treba obratiti pažnju na nekoliko sitnih, ali veoma važnih elemenata, koje
mogu drastično uticati na tok programa.
Već smo pomenuli da veličina ovih vrednosti zavisi pre svega od sistema na kome se izvršavaju. To znači da
prelaskom sa sistema na sistem naša aplikacija može dati drugačije rezultate, u zavisnosti od performansi
sistema.
Float tipovi u PHP-u mogu dati neočekivane rezultate prilikom konverzije. Na primer, ukoliko konvertujemo sledeći
izraz u tip integer: ((0.1 + 0.7) * 10), rezultat te konverzacije će, iako bi po svoj logici trebalo da bude broj 8, biti
broj 7. To je zato što je rezultat sabiranja 0.1 + 0.7 u PHP-u broj 7.999999. Prilikom konverzacije u integer, ovom
broju se jednostavno skidaju decimale.
Stringovi
String je u PHP-u tip podataka koji sadrži sortiranu kolekciju binarnih vrednosti, koja može da sačinjava bilo kakvu
binarnu strukturu (sliku, zvuk, tekst itd.). Ipak, kada se kaže string, misli se pre svega na tekstualni sadržaj, pa je
najbolje da ga i zapamtimo kao nosioca tekstualnog sadržaja.
Boolean
O boolean tipu je dosta rečeno u samom nabrajanju tipova, pa ćemo pomenuti samo neke konverzacione osobenosti:
Prilikom konverzacije iz brojne u boolean vrednost, sve vrednosti koje nisu nula, biće konvertovane u true (čak i
negativne vrednosti)
Prilikom konverzacije stringa u boolean vrednost, jedino stringovi koji nemaju sadržaj ili sadrže samo jedan
karakter (0) biće konvertovani u false
15
Pored pomenutih, PHP poznaje i dva specijalna tipa podataka.
Resource
Ovo je tip podataka koji je, u stvari, referenca na određeni izvor podataka. Ovo je poseban tip i postoje posebne
funkcije koje sa ovim tipom rukuju. Fizički, ovaj tip predstavlja jedan tok podataka. Zato se, često, promenljive ovog tipa
nazivaju i Resource Stream ili samo Stream.
Uzmimo za primer jedan tekstualni fajl. Taj fajl nije sastavni deo aplikacije, ali u njemu (na primer) postoje određeni
podaci koji su potrebni aplikaciji da bi funkcionisala. Da bi programer pristupio ovom fajlu, potrebno je da ga na neki
način tretira tokom izvršavanja programa. Ali, da bi to mogao da učini, potreban mu je objekat koji će reprezentovati taj
fajl u kodu. Taj objekat naziva se resurs.
NULL
Ovo, zapravo, i nije tip podataka, već pre fiksna vrednost, koju, obično, imaju objekti kojima vrednost još uvek nije
dodeljena ili je obrisana. Tip NULL može imati samo jednu vrednost – NULL.
Konverzije tipova
PHP se u većini slučajeva sam brine oko konverzije jednog tipa u drugi. Možete jednostavno napisati "1" + 2 i rezultat
će biti 3, iako je jedan tip string, a drugi tip broj.
Ipak, ovakve implicitne konverzije funkcionišu kada su u pitanju tipovi prostih podataka, ali ne i u slučaju složenih
tipova. Prost tip ne možete konvertovati u resurs. Sa druge strane, resurs hipotetički možete konvertovati u string, ali
ćete pri tom dobiti samo tekstualnu reprezentaciju tog resursa.
Da bi konvertovali vrednost iz jednog tipa u drugi, koristimo male zagrade, na sledeći način: (tip u koji hoćemo da
izvršimo konverziju)vrednost.
Na primer, ako bismo hteli da broj 10 pretvorimo u string, napisali bismo:
(string)10;
A ako bismo hteli da pretvorimo string u ceo broj, napisali bismo:
(int)"10"
Naravno, da bi ovakva konverzija imala smisla, trebalo bi da pod navodnicima bude nešto što može da se uspešno
prevede u broj (kao što je broj 10 u prethodnom primeru). Ali ako i ne obezbedimo ovakav podatak, php se neće
pobuniti, već će izvršiti konverziju što bolje može. U sledećem primeru, kao rezultat konverzije dobićemo broj 0.
(int)"a"
Sledeći primer konvertuje broj 015 u celobrojnu vrednost. Logično je da se praktično ništa ne dogodi, i da na izlazu
dobijemo broj 15, ali rezultat neće biti takav.
$x = 015;
echo (int)$x;
Umesto broja 15, dobićemo broj 13. Ovo je u stvari potpuno normalno ponašanje jer je vrednost $x definisana kao
oktalna (ima nulu na početku) i stoga, kada se pretvori u decimalnu nije 15, već 13. Zapravo, vrednost 13 bi dobili čak i
da ne izvršimo konverziju, osim ako ne odlučimo da formatiramo broj na drugačiji način na izlazu.
Formatiranje brojeva
Često će se pri ispisu brojeva javiti i potreba za njihovim formatiranjem, ukoliko želite da ispišete cifre razdvojene
nekim znakom ili na primer da koristite separator za decimale. Za formatiranje u obliku celog broja koristi
se funkcija number_format().
$broj= 879.22;print number_format($broj);
Ispis na izlazu biće: 879
Funkcija number_format() zaokružuje broj koji formatira na najbliži ceo broj.
Za formatiranje u obliku decimalnog broja, zadaje se broj decimalnih mesta kao drugi argument u pozivu funkcije. Ako
kroz funkciju provučemo broj 879.223456:
16
print number_format($broj, 2);
Ispis na izlazu biće: 879.22
Formatiranje novčanih iznosa biće takođe potrebno u radu pa ćemo ukratko objasniti osnove formatiranja. Upotrebom
funkcije money_format() formatira se broj tako što se umeće znak za željenu valutu, separator decimalnih mesta i
separatore grupa od po tri cifre koje odgovaraju datom regionu. Kao prvi argument funkcije poziva se %n da bi se cifra
ispisala u američkom formatu za valutu ili %i koji predstavlja standardni format za valutu koja se upotrebljava
međunarodno ili lokalno. Funkcija setlocale() podešava region i lokalne podatke.
Primer:
<?php
$broj = 2234.16;
setlocale(LC_MONETARY, 'en_US');
print money_format('%n', $broj);
print money_format('%i',$broj);
setlocale(LC_MONETARY, 'fr_FR');
print money_format('%i', $broj);
?>
Nakon izvršenja dobićemo (obratite pažnju na to da će primer raditi samo na Linux okruženju):
SAD: $2,234.16
USD: 2,234.16
2 234.56 EUR
Formatiranje je moguće izvršiti i funkcijom printf. Ovo je nešto što osobe sa iskustvom u programskom jeziku C već
znaju. U sledećem primeru definisani broj je prikazan na tri načina. Oktalno, decimalno i binarno, uz pomoć funkcije
printf.
$x = 015;
printf("Octal x is: %o, decimal is %d, and binary is %b",$x,$x,$x);
O funkciji printf će biti još reči, pa ćemo samo ukratko reći da se u delu pod navodnicima nalazi tekst koji treba da bude
prikazan, i da se u tom tekstu nalaze oznake na čijem mestu će se naći odgovarajući parametar iz liste parametara
nakon dela pod navodnicima. Ove oznake počinju znakom % čemu sledi oznaka tipa. o je oktalni numerički tip, d je
decimalni, a b binarni. U stringu imamo tri pojavljivanja, a nakon stringa tri parametra od kojih svaki odgovara poziciji u
stringu. Kao rezultat dobićemo sledeći ispis na strani:
Octal x is: 15, decimal is 13, and binary is 1101
Datum i vreme
Datum i vreme su veoma važni elementi u razvoju veb strana i aplikacija. PHP omogućava da sa ovim podacima radite
drugačije nego sa običnim stringovima. Kompjuter čuva datum i vreme u formatu koji se naziva timestamp. Ovaj format
iskazuje određeni datum i vreme preko sekundi. Obzirom na to da je takav način prikazivanja vremena nerazumljiv za
običnog korisnika, PHP ga konvertuje u neki od oblika koji ljudi koriste.
Kod koji sledi, prikazuje trenutno vreme i datum u okviru veb strane:
<?php
echo 'Danasnji datum je: '. date('d-n-Y');
echo '<br/>';
echo 'Trenutno vreme je:'. date('g:i:s a');
?>
Na izlazu nakon izvršenja ćemo dobiti:
Value Key
Seconds seconds
Minutes minutes
Hours hours
Day of the month mday
Day of the week, numeric (Sunday is 0, Saturday wday
is 6)
Month, numeric mon
Year, numeric (4 digits) year
Day of the year, numeric (e.g., 299) yday
Day of the week, textual, full (e.g., “Friday") weekday
Month, textual, full (e.g., “January") month
Seconds since epoch (what time( ) returns) 0
18
<?php
$vreme= getdate();
printf('%s,%d,%d',$vreme['month'],$vreme['mday'],$vreme['year']);
?>
Klasa DateTime
Bitno je napomenuti da korišćenje funkcija predviđenih za formatiranje i prikazivanje datuma i vremena nije jedini način
za rad sa pomenutim podacima. Klasa DateTime u PHP-u je nešto naprednijih okvira od ovog kursa, ali važno je
napomenuti mogućnosti olakšica prilikom pozivanja datuma i vremena. Klasa DateTime pripada objektno orijentisanom
stilu i navešćemo razlike između dosadašnjeg ispisa i objektno orijentisanog. U prethodnim primerima za ispis na
izlazu poput 2013- 01-01 00:00:00 služili smo se sledećim kodom:
<?php
$date = date_create('2013-01-01');
echo date_format($date, 'Y-m-d H:i:s');
?>
Prikaz objektno orijentisanog načina kodiranja:
<?php
$date=new DateTime ('2013-01-01');
echo $date->format('Y-m-d H:i:s');
?>
S obzirom na to da pred sobom imamo oba načina kodiranja, i zahteva za ispis i formatiranje datuma i vremena,
možete se odučiti za dalji rad.
Vežba 1
Problem:
U aplikaciji, identifikaciona šifra korisnika se pamti na sledeći način:
<?php
$sifra = 11793847250045684;
?>
Prilikom emitovanja ovog broja, na izlazu se pojavljuje sledeća vrednost:
1.1793847250046E+16
Nad ovim brojem (šifrom) ne vrše se nikakve aritmetičke operacije, ali je potrebno da na izlazu šifra bude adekvatno
prikazana.
Rešenje:
Najbolje je velike brojne vrednosti koje ne zahtevaju aritmetičke operacije reprezentovati u vidu stringa:
<?php$x = "11793847250045684"; ?>
Vežba 2
Problem:
U okviru PHP aplikacije nalazi se linija koja emituje podatke o tačnom vremenu:
<?phpecho "Trenutno je: " . Date("h:i") . "h, dan je: " . Date("D/M/y"); ?>
Linija emituje sledeći rezultat:
Trenutno je: 11:45h, dan je: Wed/Jan/13
Korisnik želi da prikazani datum bude u sledećem formatu:
19
Trenutno vreme je: 11:45, dan je: 16/01/2013
Rešenje:
<?php echo "Trenutno vreme je: " . Date("h:i") . ", dan je: " . Date("d/m/Y");?>
Vežba 3
Problem:
U okviru aplikacije potrebno je napraviti sistem koji će pratiti da li je korisnik ulogovan ili ne. Potrebno je odrediti tip
podatka u kome će biti skladištena ova informacija.
Rešenje:
Ovaj tip može biti boolean (true ili false), jer postoje samo dve moguće vrednosti, tačno ili netačno.
Promenljive
Jedinica: 3 od 19
Rezime
Promenljive u PHP-u moraju ispred imena sadržati znak $ ($mojaPromenljiva).
Promenljive u PHP-u kao prvi znak imena ne smeju imati broj ili specijalni karakter ($1mojaPromenljiva – ne
valja, $%mojaPromenljiva – ne valja).
Konstante u PHP-u ne moraju imati znak $ ispred imena. define("PI", 3.14);
Konstante u PHP-u mogu biti bilo kog tipa (koji je podržan od strane jezika)
U ovoj lekciji akcenat će biti na samoj definiciji promenljive i njenoj implementaciji u PHP jeziku.
Recimo da hoćemo da kažemo da u programu postoji neka promenljiva čiji je naziv $x i koja ima vrednost 10.
Napisaćemo:
$x = 10;
U nastavku programa biće nam na raspolaganju promenljiva $x sa vrednošću 10. I ako napišemo:
echo $x;
Na strani će biti ispisan broj 10.
20
Ako napišemo:
$mojaPromenljiva = "Hello!";
echo $mojaPromenljiva;
Na strani će biti napisana poruka Hello!
U PHP-u je moguće dodeliti nazivu varijable vrednost neke druge varijable. Na primer:
$mp = "mojaPromenljiva";
$$mp = "sadrzaj moje promenljive";
U ovom slučaju, dodelili smo nazivu druge varijable vrednost prve varijable (mp), tako da je sada moguće doći do
vrednosti druge varijable kroz varijablu:
$mojaPromenljiva;
Ovu vrednost takođe je moguće dobiti i kroz varijablu:
$$mp = "sadrzaj moje promenljive";
Ali i prilikom ovakvog načina definisanja promenljivih mora se pridržavati pravila o nazivima varijabli. Na primer, ako
bismo definisali varijablu 123 na sledeći način:
$mp = "1mojaPromenljiva";
$$mp = "sadrzaj moje promenljive";
Prilikom poziva te varijable ($mojaVarijabla) došlo bi do greške, zato što brojevi u početku imena varijable nisu
dozvoljeni. Ipak, i pored toga, ova varijabla i vrednost koja joj je dodeljena bile bi uskladištene u memoriji i dostupne
kroz sledeću sintaksu:
${'1mojaPromenljiva'}
Treba biti naročito oprezan prilikom ovakvog pristupa, jer ukoliko je neadekvatan, može lako doći do bezbednosnih
propusta u aplikaciji.
U PHP-u ne postoji način da se potpuno osigura postojanje neke promenljive u određenoj tački programa, što može
dovesti do funkcionalnih i bezbednosnih problema. Zato se, kako bi se ublažio problem uzrokovan ovim nedostatkom,
koristi funkcija isset(), koja ispituje postojanje neke promenljive.
Ova funkcija prihvata naziv promenljive kao parametar i vraća vrednost tipa boolean kao rezultat.
isset($mojaPromenljiva)
Ako je $mojaPromenljiva, prethodno definisana u kodu, funkcija isset će vratiti kao vrednost true. U suprotnom, ova
funkcija će vratiti vrednost false (više o funkcijama, radićemo u narednim lekcijama).
Ukoliko, ipak, budete rukovali sa nepostojećim promenljivima, PHP će biti u stanju da obradi ovakve promenljive na
adekvatan način. Na primer:
$a + 2
U slučaju da promenljiva $a ne postoji nigde u prethodnom kodu, PHP će je tretirati kao da joj je vrednost nula, pa će
rezultat ovog izraza biti 2. Slična stvar će se dogoditi i ukoliko je izraz:
$a + $b
Tada će rezultat biti nula, jer su obe promenljive tretirane kao nule, iako nisu prethodno definisane.
Ovaj rezultat će zavisiti od podešavanja u PHP.ini fajlu. Nepostojanje promenljive može izazvati grešku.
Domet promenljive
Deklarisanje promenljivih nije ograničeno na deklarisanje po vrednosti ili referenci i možete ih deklarisati bilo gde,
naravno, u okviru php skriptova. Međutim, kada je u pitanju lokacija same promenljive, može se javiti problem
dostupnosti. Problem se javlja ukoliko promenljivu deklarišete u jednom delu alikacije a pozivate je u drugom delu,
tačnije, promenljivu ste deklarisali u okviru neke petlje, funkcije ili klase i želite da joj pristupite van tih okvira, program
će se pobuniti i u reći da promenljiva ne postoji. Tako dolazimo do domenskog pristupa promenljivih.
Php promenljive mogu pripadati jednom od četiri dometa:
21
Lokalne promenljive
Parametri funkcija
Globalne promenljive
Statičke promenljive
Lokalne promenljive - Promenljive koje su deklarisane samo u okviru funkcije nazivaju se lokalnim jer mogu da se
koriste samo u okviru te funkcije. Kada bismo pokušali da promenljivoj dodelimo neku vrednost van tela funkcije PHP
bi pomenutu promenljivu tretirao kao potpuno drugačiju, novu promenljivu, koja nema veze sa deklarisanom u telu
funkcije.
Lokalne promenljive se koriste da bi eliminisale eventualne bočne efekte koji predstavljaju, između ostalog, i slučajne ili
namerne izmene globalno dostupnih promenljivih.
Na sledećoj ilustraciji vidimo promenljivu definisanu unutar php funkcije i jednu definisanu izvan nje.
Ako želite to i da dokažete na primeru, možete napisati sledeći kod (neki elementi primera još nisu razjašnjeni u ovom
delu kursa, ali su neophodni da bi primer bio kompletan):
//Definise se promenljiva sa nazivom x i vrednoscu 20
$x = 20;//definise se funkcija f
function f(){
//Unutar funkcije, definise se promenljiva x sa vrednoscu 10
$x = 10;
//Promenljiva x definisana unutar funkcije se prikazuje na izlazu
echo $x;
}
//Poziva se funkcija f. Nakon sledece linije, bice aktivrana funkcija,
//i unutar nje ce biti definisana promenljiva x sa vrednoscu 10,
//a zatim prikazana na izlazu f();
//Prikazuje se promenljiva x definisana izvan funkcije - funkcija nema nikakav uticaj na njuecho $x;
Parametri funkcija – Što se tiče funkcija, objašnjavaćemo ih u nastavku kursa detaljnije. Sada ćemo se zadržati
samo na parametrima funkcije, odnosno, argumentima funkcija. Kao što je već poznato svaka funkcija koja prihvata
neke parametre (na primer sa ulaza) u svom zaglavlju mora imati određene argumente (zapravo, ti argumenti su
parametri). Bitno je napomenuti da ovi argumenti dobijaju vrednosti izvan tela funkcije kojoj pripadaju i njima nije
moguće pristupati nakon završetka izvršavanja funkcije. Ovakvi tipovi promenljivh, parametri funkcije, deklarišu se
nakon navođenja naziva funkcije, unutar zagrada.
Primer:
//Definisana je funkcija f
function f($x)
{
//promenljivoj koja je ušla u funkciju povećava se vrednost za 5
$x = $x + 5;
}
Da bi ova funkcija bila startovana morali bi da napišemo:
f(10);
Odnosno, mogli bismo napisati:
22
//Definisana je promenljiva $x sa vrednošću 10
$x = 10;
//Poziva se funkcija f i prosleđuje joj se promenljiva $x kao parametar
f($x);
//Vrednost promenljive $x se prikazuje na izlazuecho $x;
Ako bismo startovali prethodni kod (u kombinaciji sa prethodno definisanom funkcijom), na izlazu bi bio prikazan broj
10. Upravo zbog toga što promenljiva koja je ušla u funkciju kao parametar, i tretirana je unutar nje, nema uticaja na
spoljašnju funkciju.
Globalne promenljive – Možemo reći da su globalne promenljive suprotan pojam od lokalnih promenljivih koje smo
objasnili. Globalnim promenljivima se može pristupati iz bilo kog dela programa. Da bismo imali mogućnost da
modifikujemo promenljivu moramo je eksplicitno deklarisati kao globalnu u okviru funkcije u kojoj želimo da vršimo
izmenu. Proglašavanje promenljive globalnom potrebno je da se navede pomoću ključne reči global ispred željene
promenljive.
Primer:
//Definisana je promenljiva $my_variable sa vrednoscu 10
$my_variable = 10;
//Kreirana je funkcija sa nazivom f, koja nema parametre
function f()
{
//Promenljiva my_variable se tretira na globalnom nivou
//Nakon ove linije, sve intervencije na promenljivoj my_variable unutar funkcije,
//uticace na promenljivu my_variable definisanu izvan nje
global $my_variable;
//Promenljiva my_variable povecava se za jedan
$my_variable++;
}
f();
//Rezultat se prikazuje na izlazu
echo "Result is " . $my_variable;
Rezultat nakon izvršenja funkcije je 11, međutim, kada bismo izostavili proglašavanje promenljive globalnom (global
$my_variable) promenljiva $my_variable bi imala nedefinisanu vrednost nakon izvršavanja funkcije jer se u ovom
slučaju tretira kao lokalna promenljiva ukoliko drugačije nije navedeno.
Drugi način korišćenja globalnih promenljivih je deklarisanje promenljive kao $GLOBALS polje. Sada ćemo
modifikovati prethodni primer tako da promenljiva $my_variables bude globalna uz pomoći niza $GLOBALS:
$GLOBALS["my_variable"]=10;
function f() {
$GLOBALS["my_variable"]++;
}
f();
echo "Rezultat je ". $GLOBALS["my_variable"];
Veliku primenu korišćenja statičkih promenljivih pronalazimo u okviru kreiranja rekurzivnih funkcija. Rekurzivne funkcije
su najprostije rečeno funkcije koje pozivaju same sebe dok ne bude ispunjen odgovarajući uslov koji se unapred
zadaje.
23
Korišćenje statičkih promenljivih
Kada želimo da lokalna promenljiva zadrži svoju vrednost između poziva funkcija potrebno je da je proglasimo
statičkom, odnosno deklarišemo je pomoću rezervisane reči static, na primer:
static $a = 1;
Statičke promenljive su blisko vezane za upotrebu klasa (Objektno Orjentisani Koncept).
Superglobalne promenljive
Korišćenjem PHP-a otvara se mogućnost korišćenja velikog broja predefinisanih promenljivih kojima se pristupa unutar
skripta koji se izvršava a koje vam mogu omogućiti da imate pregled dodatnim informacijama vezanim za okruženje.
Informacije takve vrste mogu biti na primer informacije o operativnom sistemu korisnika, lokalnom operativnom sistemu
itd... Pokušajte da izvršite kod iz sledećeg primera i analizirajte dobijeni zapis kako biste uočili povratne informacije od
servera:
Primer:
foreach ($_SERVER as $var => $value)
echo $var . ":" . $value . '<br />';
Izvršavanjem koda dobićete veliki broj informacija koje verovatno neće imati veliki značaj za vas, međutim, ukoliko vam
je potrebna specifična informacija na primer o IP adresi vašeg računara možete je preuzeti upravo odavde:
printf('Vasa IP adresa je: %s ', $_SERVER['REMOTE_ADDR'] );
Konstante
Kada su u pitanju korisnički definisane vrednosti, osim promenljivih, postoji još jedan tip kome je vrednost, kada ih
jednom inicijalizujemo, fiksna. Takvi tipovi se nazivaju konstante. Konstante upotrebljavamo kada znamo da se
inicijalizovana vrednost sigurno neće menjati tokom izvršavanja programa. Za konstante je, takođe, karakteristično
(osim standardnih pravila za promenljive) i to da ne moraju sadržati $ ispred imena promenljive. Najbolji primer za
vrednost konstante je 3.14 (odnosno PI).
PHP ima puno ugrađenih konstanti koje možete da koristite u svom kodu. Neke od njih su:
Prilikom inicijalizacije treba obratiti pažnju da konstanta može prihvatiti samo skalarni tip podatka.
Deklaracija promenljivih
U drugim programskim jezicima neophodno je da se promenljiva deklariše pre nego što joj se dodeli vrednost. U PHP-
u je dovoljno samo dodeliti vrednost promenljivoj. Pre samog smeštanja vrednosti u memoriju, PHP sam određuje tip
vrednosti i snima je u odgovarajućem formatu. Ukoliko je potrebno, PHP automatski i konvertuje jedan tip podataka u
drugi. Na primer:
$first_number = 1; // čuva se kao celobrojna vrednost
$second_number = 1.1; // čuva se kao realan broja
$sum = $first_number + $second_number;
24
U trećoj naredbi sabiraju se dve vrednosti različitog tipa. Pre samog sabiranja, PHP konvertuje celobrojnu vrednost u
realnu, kako bi sabiranje bilo moguće.
a nikako ne ovako:
if($my_variable=10){ ... }
Korišćenjem jednog znaka jednakosti ako je promenljiva sa leve PHP će izvršiti dodelu, , promenljivoj $my_variable
biće dodeljena vrednost 10 i samim tim unutar narednog bloka { ...... } rizikuje se sa pogrešnim rešenjem.
Vežba 1
Problem:
U postojećoj aplikaciji, postoji set promenljivih vezanih za bazu podataka kreiran na sledeći način:
<?php
$s = "localhost";
$k = "root";
$s = "";
$b = "mojaBaza";
?>
Potrebno je modifikovati promenljive u cilju bolje intuitivnosti.
Rešenje:
Ove promenljive nemaju intuitivna imena i vrlo je moguće da će se ukrstiti sa drugim promenljivima u okviru aplikacije.
Bolja imena bila bi, na primer:
25
<?php
$dbServer = "localhost";
$dbKorisnik = "root";
$dbSifra = "";
$dbBaza = "mojaBaza";
?>
Vežba 2
Problem:
Jednostavna aplikacija koja sabira dva broja i emituje ih na izlaz, ne funkcioniše. Potrebno je ispraviti grešku:
<?php
$x = 10;
$y = 20;
echo $x+$Y;
?>
Rešenje:
PHP je osetljiv na velika i mala slova, a u poslednjoj liniji aplikacije se umesto $y nalazi $Y, što dovodi do greške, jer
promenljiva $Y ne postoji.
<?php
$x = 10;
$y = 20;
echo $x+$y;
?>
Vežba 3
Problem:
Potrebno je napraviti set konstanti koje će biti korištene za rukovanje bazom podataka. U ovom trenutku, postoje
promenljive:
<?php
$dbServer = "localhost";
$dbKorisnik = "root";
$dbSifra = "mojaSifra";
$dbBaza = "mojaBaza";
?>
Rešenje:
<?php
define("_DB_SERVER_","localhost");
define("_DB_KORISNIK_","root");
define("_DB_SIFRA_","mojaSifra");
define("_DB_BAZA_","mojaBaza");
?>
26
Operatori
Jedinica: 4 od 19
Rezime
Operatori služe za dodeljivanje vrednosti, poređenje dve vrednosti, pridruživanje izraza ili vršenje aritmetičkih
operacija nad vrednostima.
Postoji više vrsta operatora. Najvažniji su: operatori poređenja, aritmetički operatori, logički operatori i operatori
dodeljivanja
Operatori poređenja su: ==, !=, <, >, <=, >=, ==, !==, operatori dodeljivanja su: =, logički operatori su &&, || i
aritmetički operatori su: +, -, /, *, %
Dodeljivanje se može izvršiti po vrednosti ili po referenci
Prilikom primene inkrementalnog ili dekrementalnog operatora nije isto ako se operator postavi pre ili nakon
promenljive
Prilikom upotrebe aritmetičkog operatora, PHP će, ukoliko je to moguće, sam izvršiti konverzaciju na
odgovarajuće tipove.
Glavna tema ove lekcije će biti operatori u PHP-u. Da bismo stvorili jedan, koliko toliko funkcionalan program u bilo
kom jeziku, potrebni su nam, pored promenljivih, i operatori. I ovde postoji generalna klasifikacija na: operatore
dodeljivanja, aritmetičke operatore, operatore poređenja i logičke operatore. Postoji još nekoliko vrsta operatora (string
operatori, type operatori, inkrement-dekrement operatori), ali se oni (kao što ćete u nastavku i videti) generalno
baziraju na pomenuta četiri osnovna operatora.
Operatori dodeljivanja podrazumevaju dodelu vrednosti određenoj varijabli.
$a=10;
$x='Moj operator';
$z=3;
Jasno je da je osnovni operator dodeljivanja znak =
Ipak, postoje i određene kombinacije znakova koje takođe imaju mogućnost dodeljivanja, ali se za njih pre može reći
da su skraćenice nego operatori (pa će o njima biti više reči kasnije):
$x+=5; //$x=$x+5;
$y-=1; //$x=$x-1;
$z++; //$z=$z+1;
++$z;
Podrazumevano dodeljivanje vrednosti promenljivima jeste po vrednosti. To znači da će, u trenutku kada dodelimo
promenljivoj vrednost, ta vrednost stvarno i biti u toj promenljivoj:
Kada uradimo sledeće:
$x=3;
Naš program je uzeo jedan delić memorije računara i u taj delić memorije smestio je broj 3. Takođe, rekao je da će se
taj delić memorije u programu odazivati na 'ime' $z.
To znači da ako napišemo
$x=3;
$y=$x;
$x=5;
27
Ovo je veoma logično. Napravili smo promenljivu x, dodelili joj vrednost 3, zatim smo napravili promenljivu y i dodelili
joj vrednost promenljive x (3) a zatim smo promenili vrednost promenljive x u 5, ali je vrednost promenljive y i dalje 3,
jer je u liniji $y=$x; izvršeno dodeljivanje po vrednosti.
Ukoliko Vam ovo i dalje zvuči komplikovano, pomislite na preusmeravanje poziva na Vašem telefonu. Ovo je upravo to.
Konačno, nemojte se opterećivati dodeljivanjem po referenci. Ovo ćete u PHP-u retko koristiti samoinicijativno. Pored
28
toga što je komplikovaniji, ovaj pristup je u PHP-u i sporiji od dodeljivanja po vrednosti (zapamtite da je PHP jedan od
retkih (verovatno jedini) u kome je prosleđivanje po referenci sporije od prosleđivanja po vrednosti).
Sa druge strane, u nekim situacijama dodeljivaćete vrednosti po referenci, a da toga niste ni svesni. Na primer, kada
budete upotrebljavali objekte ili nizove, koji jedino i mogu funkcionisati na ovaj način.
Šta se dešava u php-u u trenutku dinamičkog navođenja? Kada je prefiks $$ php se navodi da uzima vrednost sa
desne strane i to ime koristi kao ime “prave” promenljive. Ovo je zapravo vrlo logično, jer, ako imamo promenljivu koja
se zove $auto, a pri tom imamo i string čija je vrednost "auto", treba samo na neki način da sastavimo ova dva i
napišemo nešto poput: $"auto", što je upravo ono što postižemo dinamičkim promenljivima.
Aritmetički operatori
Svaka aritmetička operacija zahteva i aritmetički operator (+, -, *, /, %). Oznake za sabiranje i oduzimanje su jasne, dok
su ostala tri operatora: * za množenje, / za deljenje i % za ostatak.
Operator za ostatak predstavlja celobrojni ostatak deljenja dva broja.
10%3 daje kao rezultat vrednost 1
10%4 daje vrednost 2
Prilikom izvođenja aritmetičkih operacija treba voditi računa o redosledu njihovog izvršavanja. Matematičke operacije u
PHP-u imaju isti prioritet izvršavanja kao i u matematici. Množenje i deljenje imaju prednost nad sabiranjem i
oduzimanjem. Redosled izvršavanja operacija može da se promeni upotrebom zagrada.
Kada pokušate da primenite neki od navedenih operatora na promenljive, rezultat operacije će zavisiti od tipa podatka
koji je smešten u promenljivima. Na primer, nakon izvršavanja sledećih naredbi:
$broj1 = 1;
$broj2 = 2;
$zbir = $broj1 + $broj2;
promenljiva zbir će sadržati vrednost 3. Promenljive $broj1 i $broj2 su definisane kao brojčane promenljive, pa je
rezultat njihovog sabiranja zbir brojeva koje sadrže. Međutim, situacija je drugačija ako jednu od promenljivih kreirate
kao string promenljivu. Na primer, nakon izvršavanja naredbi:
$broj1 = "1";
$broj2 = 2;
$zbir = $broj1 + $broj2;
promenljiva $broj1 je kreirana kao string promenljiva. Pre sabiranja, PHP će automatski konvertovati tekstualnu
vrednost u broj. U ovom slučaju, vrednost "1" će biti konvertovana u broj 1, pa će rezultat sabiranja opet biti 3, kao i u
prethodnom slučaju. Međutim, u sledećim naredbama:
29
$broj1 = "x";
$broj2 = 2;
$zbir = $broj1 + $broj2;
obzirom da vrednost prve promenljive nije broj, PHP će promenljivu $broj1 da konvertuje u broj 0, pa će vrednost
promenljive $zbir biti 2. U većini slučajeva, PHP će konvertovati string vrednost u neki neodgovarajući broj. Pogledajte
sledeći primer:
$broj1 = "2,000";
$broj2 = 2;
$zbir = $broj1 + $broj2;
Vrednost prve promenljive bi trebalo da bude 2000, barem je tako ljudi razumeju, ali PHP zarez doživljava kao kraj
broja, pa će promenljiva $broj1 biti konvertovana u broj 2, a rezultat sabiranja će biti broj 4. Zbog toga se ne treba
oslanjati na automatsko konvertovanje, nego treba voditi računa da je svakoj promenljivoj dodeljena prava vrednost
prilikom kreiranja, kako bi mogle da se izvrše sve operacije nad njom.
Pored osnovnih matematičkih operatora, PHP obezbeđuje i operatore povećanja i smanjenja vrednosti (inkrement i
dekrement operatori).
++ $broj++; $broj=$broj+1;
-- $broj--; $broj=$broj-1;
+= $broj+=2; $broj=$broj+2;
-= $broj-=2; $broj=$broj-2;
*= $broj*=2; $broj=$broj*2;
/= $broj/=2; $broj=$broj/2;
Nakon izvršenih linija koda, promenljiva $x imaće vrednost 1, ali, ako drugu liniju izmenimo sa:
$x=++$a;
promenljiva $x će imati vrednost 2.
Dakle, jasno je šta se dogodilo. U prvom primeru, inkrementacija je izvršena nakon dodele vrednosti, a u drugom,
dodela vrednosti se odigrala nakon inkrementacije.
Naravno, suvišno je govoriti o tome kakve posledice može imati nepažljivo rukovanje inkrement operatorima.
30
Sem operatora, za rad sa brojevima moguće je koristiti i ugrađene funkcije PHP-a, kao što je funkcijasqrt() za
izračunavanje kvadratnog korena nekog broja, funkcija abs() za izračunavanje apsolutne vrednosti broja,
funkcija ceil() koja zaokružuje broj na prvi veći ceo broj, funkcija floor() koja zaokružuje broj na prvi manji ceo,
funkcije max() i min() koje izračunavaju maksimum i minimum i druge. Sećate li se problema sa konverzijom
decimalnog broja u ceo (kada je broj 7.999999 davao rezultat 7). Ovakvi problemi se upravo rešavaju matematičkim
funkcijama.
Spisak matematičkih funkcija, možete naći na sledećoj adresi:
http://php.net/manual/en/ref.math.php
31
Pogledajmo nekoliko primera:
Ako bi imali dve promenljive, $x i $y. Pri čemu je $x=10 a $y=20, mogli bi da uporedimo njihove vrednosti operatorom
poređenja:
Ako bi hteli da pitamo da li je $x jednako $y, napisali bi:
$x==$y
Ovako napisan kod vratiće kao rezultat boolean tip. I to, u ovom slučaju, vrednost false. Jer $x i $y nemaju istu
vrednost.
Naravno, ako bi napisali samo poređenje dve vrednosti, kod ne samo da ne bi bio sintaksno ispravan, već ne bi imao ni
neki naročit smisao. Zato se operatori poređenja najčešće koriste u kombinaciji sa uslovnim izrazima.
Na primer, ako hoćemo da napišemo poruku ukoliko je $x jednako $y, napisaćemo:
if($x==$y) echo "Hello!";
Ako startujemo prethodno napisani kod, nećemo dobiti poruku Hello, jer $x nije jednak $y.Mogli bi zato promeniti uslov
i napisati: ako $x nije jednako $y napiši poruku. Tada bi mogli iskoristiti negaciju i napisati:
if($x!=$y) echo "Hello!";
Zatim bi po istom principu mogli koristiti i sve ostale pomenute operatore.
Poslednja dva operatora su malo teža za razumevanje u ovom trenutku, pa je dobro da ih dodatno praktično
objasnimo.
Uzmimo sledeći blok:
$x = 1;
$y = "1";
$z = $x == $y;
Vrednost promenljive $z bi nakon ovog koda bila true, jer promenljive $x i $y imaju istu vrednost. Ali nakon izvršenja
sledećeg koda:
$x = 1;
$y = "1";
$z = $x === $y;
Vrednost promenljive $z će biti false, jer, iako promenljive $x i $y imaju istu vrednost, njihovi tipovi se razlikuju.
Logički operatori
Ovi operatori spajaju više izraza u određenom uslovu rezultirajući takođe konačnom vrednošću tipa boolean:
prvi izraz && drugi izraz – ako su i prvi i drugi izraz tačni rezultat je true (tačno)
prvi izraz || drugi izraz – ukoliko je prvi ili drugi izraz tačan rezultat je true
Na primer, ako bi hteli da proverimo da li korisnik ima više od 13 godina i manje od 25 godina, napisali bi:
$user_age = 20;
if($user_age>13&&$user_age<25)
echo "Korisnik ima manje od 25 i vise od 13 godina";
Mogli bi takođe proveriti da li korisnik ima 13 ili 25 godina, tada bi iskoristili logički operator ili:
$user_age = 20;
if($user_age==13||$user_age==25)
echo "Korisnik ima 13 ili 25 godina";
Takođe, možemo praviti i kombinacije ovih operatora:
if(($user_age==13||$user_age==25)&&($user_gender=="male")&&$user_loged=true)
echo "Valid user";
Dobro je znati da php uvek pokušava optimalno da tretira poređenje. Na primer, ako pitamo sledeće:
32
if($a==10||$b==20)...
Ukoliko promenljiva $a ima vrednost 10, dalja poređenja neće biti vršena (jer nema potrebe).
Sa druge strane, u sledećem kodu:
if($a==10&&$b==20)...
Ako promenljiva $a nema vrednost 10, dalja provera će takođe momentalno biti prekinuta, jer uslov nikako ne može biti
ispunjen.
Šift operatori (<< i >>) omogućavaju pomeranje bitova na levu ili desnu stranu, unutar jednog bajta. Na primer:
$a=10;
$b=$a<<1;
Vrednost promenljive $a je 10. Ovo je u binarnom zapisu broj: 1010. Kada promenljivoj $b dodelimo vrednost $a<<1,
mi smo, u stvari, pomerili sve bitove u promenljivoj $a za jedno mesto u levo i dodelili tu novu vrednost promenljivoj $b.
Ova vrednost je sada 10100 (ili ako Vam je lakše 00010100 ili 0000000000010100).
Vrednost promenljive $b sada će biti 10100, odnosno 20.
Ako želite da vidite binarnu reprezentaciju broja, najbolje da koristite printf funkciju i formatirate binarni izlaz vrednosti:
printf("%b",$b);
Binarno ne (komplement) (~) je opertor koji invertuje sadržaj bajtova aktuelne promenljive.
Ako je binarna vrednost promenljive bila 1010 sada će biti 0101. Odnosno, 11111111111111111111111111110101,
što možete isprobati sledećim primerom:
$a=10;printf("%b",~$a);
Binarno i (&) daje novu vrednost kao rezultat. Ova vrednost dobija se poređenjem bitova na istim pozicijama u oba
operanda. Ako oba poređena bita imaju različite vrednosti, ili vrednosti 0, rezultat će biti 0. Samo ukoliko oba bita imaju
vrednost 1, rezultat će biti 1.
Na primer:
0101
&1011 je
0001
Binarno ili (|) daje takođe novu vrednost kao rezultat. Ali se u ovom slučaju ta vrednost sastoji od svih bitova gde bar
jedna od poređenih vrednosti ima vrednost jedan.
Na primer:
0101 |
1011 je
1111
Konačno binarno XOR (exclusive or) (^). Ovaj operator uzima u obzir samo bitove u kojima ili jedna ili druga
promenljiva imaju vrednost 1, ali ne i ukoliko obe imaju ovu vrednost.
1010 ^
1000 je
0010
33
Error suppression operator (supresor grešaka)
Jednostavan operator, koji onemogućava emitovanje greške usled naredbe kojoj prethodi. Pokušajte da u vašem kodu
izvršite sledeću naredbu (pod uslovom da baš nemate fajl abcd u folderu gde je PHP fajl):
include "abcd";
Ako pokušate da izvršite ovu naredbu, PHP će prijaviti grešku, ali, ukoliko naredbi dodate operator @
@include "abcd";
Greška neće biti emitovana.
Koliko je ovo dobro, zavisi od situacije u kojoj se nalazite. Ponekad neemitovanje greške dosta znači, ali nekada može
i da smeta.
Nakon formatiranja, broj se konvertuje u string. Zbog toga je nephodno sve aritmetičke operacije nad brojem izvršiti pre
njegovog formatiranja.
Za komplikovanija formatiranja brojeva moguće je koristiti funkcije printf() i sprintf(). Funkcija printf() samo prikazuje
broj u određenom formatu. Funkcija sprintf() formatira broj i smešta ga u promenljivu. Ove funkcije se koriste i za
formatiranje string vrednosti.
Primeri
Napravimo jedan program koji sabira dva broja:
Primer 1
<?php
//primer 1
//sabiranje dva broja
Ne treba zaboraviti da konvencije PHP jezika važe samo unutar PHP taga. Stoga, ne treba pokušavati izvršavanje
komandi ili ispis komentara u delu koji je van tih tagova.
Primer 2
U ovom primeru izračunaćemo površinu kruga.
Znamo da nam je za to potrebna samo promenljiva r. Takođe, tokom izračunavanja, biće nam potreban i broj PI.
Obzirom da je u pitanju fiksna vrednost, možemo upotrebiti konstantu.
<?php
//primer 2
//izračunavanje površine kruga
//definicija konstante PI
define("PI", 3.14);
//definicija promenljive r
$r=10;
//definicija promenljive p kao rezultat izračunavanja površine kruga
$p = ($r*$r)*PI;
//emitovanje promenljive p koja sadrži rezultat površinu kruga sa poluprečnikom r
echo $p;
?>
Ovaj program, iako kratak, sadrži veoma zanimljive pojave. Pre svega, definisanje konstante. Procedura je dosta
jasna, funkcija define prihvata dva parametra (naziv konstante, vrednost konstante). Tako dobijamo definiciju
konstante:
define("PI", 3.14);
Umesto PI smo mogli da upotrebimo bilo koji drugi naziv (u konvencijama naziva varijabli). Svakako, pri definiciji
konstante, nismo ograničeni samo na brojne vrednosti. Konstanta može nositi bilo koji tip podatka.
define("imePrezime", "petar petrovic"); //tip string
define("godiste", 1980); //celobrojni tip
define("muskiPol", true); //boolean tip
U nastavku programa, nakon inicijalizacije promenljive r primećujemo da je pri inicijalizaciji promljive p jedan deo
iskaza odvojen zagradama, kao i da konstanta PI nema znak $ ispred imena. Ovo je normalno jer konstante i ne treba
da imaju oznaku $ ispred naziva, dok se zagrade koriste za logičko razdvajanje celina pri aritmetičkim operacijama. Na
primer, sledeće dve linije koda neće dati dva ista rezultata:
echo 2-(3*3);
echo (2-3)*3;
Na kraju, u poslednjoj liniji, program jednostavno emituje rezultat na izlaz.
Treba samo napomenuti da kvadrat u ovom programu nismo morali računati ručno, već smo mogli u tu svrhu upotrebiti
jednu iz kolekcije funkcija za rad sa matematičkim operacijama:
pow(10,2);
pri čemu je prvi broj naša ulazna vrednost, a drugi broj eksponent.
35
Vežba 1
Problem:
Potrebno je preraditi sledeću aplikaciju tako da na izlazu bude broj od dve decimale.
<?php
$cena = 527.356;
$popust = 15;
$cenaSaPopustom = $cena - (($popust/100)*$cena);
echo $cenaSaPopustom;
?>
Trenutni izlaz aplikacije je:
448.2526
Rešenje:
<?php
$cena = 527.356;
$popust = 15;
$cenaSaPopustom = $cena - (($popust/100)*$cena);
echo number_format($cenaSaPopustom,2)
?>
Vežba 2
Problem:
Aplikacija prolazi kroz brojeve od 0 do 1000. Potrebno je prikazati samo brojeve koji su deljivi sa 3 bez ostatka.
Postojeći kod izgleda ovako:
<?php
for($i=0;$i<1000;$i++)
if( OVDE JE POTREBNO UNETI USLOV )
echo $i . "<br>";
?>
Rešenje:
Može se upotrebiti modulo operator:
<?php
for($i=0;$i<1000;$i++)
if( $i%3==0 )
echo $i . "<br>";
?>
Naredbe elseif
Prilikom odlučivanja, za odluke koje donosite može postojati više od dva rešenja. Pomoću naredbeelseif imate
mogućnost da definišete redosled obrade više opcija potencijalnih rešenja. Kada zadate više uslova, vaš program
može da ispituje svaki uslov po zadatom redosledu sve dok ne nađe onaj uslov koji je ispunjen.
37
Reč elseif možete da pišete i spojeno i odvojeno (else if) jer su oba oblika ispravna i u okviru primera ćete nailaziti na
oba načina pisanja.
Kada koristite ovakav način pisanja koda treba da imate u vidu da će se samo jedan blok (jedna naredba koja je
zadata po uslovu) biti izvršena. Uslovi mogu biti uzajamno isključivi (samo jedan može biti izvršen od svih navedenih),
međutim, ako su uslovi takvi da više od njih može biti istovremeno ispunjeno izvršava se samo jedna naredba ili blok
naredbi iza prvog ispunjenog uslova.
Ugnježdeni uslovi
Ipak, semantički, stavljanje brojne vrednosti u izraz uslova nije pravilno, pa to izbegavajte.
Na primer, sledeći primer je potpuno ispravan sa stanovišta funkcionalnosti programa, ali bi u praksi bolje bilo da i broj
10 ne bude broj, već neka promenljiva (if($number<$comparer))...
<?php
$number = 15;
if ($number < 10) {
echo "Broj je manji od 10. ";
}
elseif ($number == 10) {
echo "Broj je jednak 10. ";
}
else {
echo "Broj je veći od 10. ";
}
?>
if-else uslove je moguće i ugnjezditi. Na primer:
if(true)
if(true)
echo "ovaj primer funkcionise";
Ovaj (potpuno funkcionalan) primer, osim što prikazuje ugnježđenje, prikazuje i još jedan način korišćenja ovog
operatora. A to je telo bez vitičastih zagrada. Ovakav pristup moguć je samo ako telo podrazumeva jednu liniju koda.
Ukoliko postoji više linija, bar dve, vitičaste zagrade su obavezne, inače može doći do logičkih nepravilnosti u radu
aplikacije. Pogledajmo primer:
if (true)
echo "uslovno izvrsavanje<br>";
echo "ovaj deo ce se svakako izvrsiti";
Druga linija će u svakom slučaju biti izvršena. Što je u primeru banalan problem, ali u ozbiljnijoj aplikaciji može dovesti
do značajnih grešaka.
Kada bismo prethodni kod napisali:
if (true)
echo "uslovno izvrsavanje <br>";
echo "ovaj deo ce se svakako izvrsiti";
korišćenjem nazubljivanja (nazubljivanje u smislu pisanja linija koda – neke linije su manje ili više uvučene/izvučene)
jasnije je da sada, kada nam je sintaksa if-else poznata naredba
echo "uslovno izvrsavanje <br>";
38
izlazi iz okvira uslova i izvršava se bez obzira na uslov. Preporuka je da se vitičaste zagrade koriste i kada imate samo
jednu naredbu nakon bloka da biste bili sigurni da vaša naredba pripada baš tom uslovu. Ipak, ukoliko vaš kod nije
previše opterećen možete koristiti nazubljivanje iz razloga preglednosti programskog koda.
Sa druge strane, dok god se držite pravila jedne linije po uslovnom bloku, možete pisati koliko god hoćete uslova za
redom.
if(true)
else if(true)
else if(true)
ili ih ugnjezditi kao u jednom od prethodnih primera.
Pristup pisanja uslovnih blokova bez vitičastih zagrada sretaćete i kod drugih struktura za kontrolu toka, ali ne i u
funkcijama ili klasama. Osim toga, obično će ono što ste zamislili kao jednu (uslovnu) liniju koda, eskalirati na više
linija, pa je možda najbolje, prilikom rukovanja tokom, držati se pristupa sa vitičastim zagradama.
Kada vam se javi potreba za složenijim logičkim operacijama imate mogućnost da smeštate jedne if naredbe u druge.
Međutim, postoji još jedan problem sa korišćenjem konkretno if-else struktura za kontrolu toka, a to je što se veoma
brzo (već nakon nekoliko uslova) gubi preglednost koda. Na primer:
if(true) { //USLOVNI SADRZAJ
if(true) { //USLOVNI SADRZAJ
} } else if(true) { //USLOVNI SADRZAJ
}
ili:
if( $a == 1)
echo "a je jedan";
if( $a == 2)
echo "a je dva";
if( $a == 3)
echo "a je tri";
Zato je često bolja praksa kada dođe do više srodnih uslova korišćenje switch struktura, koje ćemo obraditi u sledećoj
lekciji.
Ponekad se za uslovljavanje koristi i ternarni operator. Ovaj operator se koristi uglavnom za uslovnu dodelu vrednosti i
ne sadrži blokove koda, tako da i nije baš prava struktura za kontrolu toka, već više operator dodeljivanja. Ipak,
vrednost se dodeljuje uslovno, pa ovaj operator utiče na tok aplikacije.
$b = ( $a == 0 ) ? 10 : $a;
Recimo da negde ranije u kodu postoji promenljiva $a koja ima vrednost nula. Kada se aktivira ternarni operator,
programu smo zapravo rekli da proveri neki uslov i dali mu alternative za oba ishoda tog uslova ? ishod 1 za slučaj da
je uslov ispunjen i : ishod 2 za slučaj da nije. Ternarni operator iz primera bi bio alternativa ovakvoj if strukturi:
if( $a == 0 )
$b = 10;
else $b = $a;
39
U primeru koji sledi elementi (dan, mesec, godina) određenog datuma se pomoću funkcije explode() prebacuju u niz, a
zatim se koristi funkcija checkdate() za proveru ispravnosti datuma i ispisuje se poruka.
<?php
$orig_date = "25/01/2013";
$date = explode("/", $orig_date);
$month = $date[0];
$day = $date[1];
$year = $date[2];
$result = checkdate( $month, $day, $year);
if ($result == true)
{
echo "Datum je validan.";
}
else
{
echo "Datum nije validan.";
}
?>
Konačno, evo i najčešće greške u kreiranju uslovnih blokova. Korišćenje operatora dodeljivanja (=) umesto operatora
poređenja (==)
$a = 10;
if($a = 5)
echo "ovo ce se izvrsiti uvek";
Izvršavanje ovog koda izazvaće nekoliko posledica izuzetno bitnih po dalje izvršavanje programa, a sve zbog
ubačenog operatora dodeljivanja umesto operatora poređenja:
promenljiva $a će u uslovu dobiti vrednost 5 koju će zadržati u nastavku programa, što verovatno ne želimo
kada dođe do dodeljivanja vrednosti promenljivoj $a u uslovnom izrazu, ona će imati vrednost 5. A kako smo
rekli u prethodnim lekcijama, sve integer vrednosti osim nule, kada se pretvore u boolean tip, postaju true, pa
čak i ako su negativne. Jedini slučaj kada će boolean od integera postati false, je da je taj integer nula. U
slučaju broja 5, dobija se true, i tako ovaj će ovaj uslov zauvek biti ispunjen, ma šta mi radili ovom programu
pre i posle tog uslova.
Vežba 1
Problem:
Na stranu dolazi promenljiva $strana. U promenljivoj je dozvoljeno postojanje jedne od dve vrednosti na osnovu kojih
će biti učitana strana funkcijom include. Dve vrednosti su "index" i "proizvodi". Ukoliko je vrednost "index" - učitava se
strana index.html, ukoliko je vrednost "proizvodi" – učitava se strana proizvodi.html. Ukoliko se nijedna vrednost ne
poklapa sa traženom vrednošću, učitava se strana login.html.
Rešenje:
<?php
$strana = "index";
if( $strana == "index" )
$strana = "index.html";
else
if( $strana == "proizvodi" )
$strana = "proizvodi.html";
else
$strana = "login.html";
echo $strana;
?>
40
Vežba 2
Problem:
Na stranu dolazi promenljiva $slika koja u sebi sadrži naziv fajla sa slikom (mojaSlika.jpg, mojaSlika.png,
mojaSlika.bmp...).
Potrebno je proveriti ekstenziju slike i, ukoliko je ekstenzija png ili jpg, prikazati poruku da je slika validna. U
suprotnom, prikazati poruku da fajl sa tom ekstenzijom nije validan. Pri tom, ekstenzija mora biti ispisana u poruci o
nevalidnosti.
Npr.: »fajl sa ekstenzijom tif nije validan«
Rešenje:
<?php
$slika = "mojaSlika.gif";
$deloviNaziva = explode(".", $slika);
$ekstenzija = $deloviNaziva [sizeof ($deloviNaziva) – 1 ];
if( $ekstenzija == "jpg" || $ekstenzija == "png")
echo "Slika sa ekstenzijom $ekstenzija je validna";
else
echo "Ekstenzija $ekstenzija nije validna";
?>
Vežba 3
Problem:
U sistemu za praćenje vozila postoje četiri statusa vozila: stoji, krece se, nestao, nepoznat. Ovi statusi označeni su
respektivno brojevima 1, 2, 3 i 4.
U aplikaciju ulazi poslednji poznati status vozila, kao i trenutni status vozila u promenljvima $poslednjiStatus i $status.
$poslednjiStatus = 2;
$status = 4;
Potrebno je dodeliti vrednost promenljivoj $nazivStatusa. Ovaj naziv, sadržaće tekstualnu reprezentaciju statusa vozila
(kreće se, stoji, nepoznat...).
Pri tom potrebno je ispoštovati sledeće pravilo: ukoliko je poslednje stanje vozila bilo "kreće se", a novi status je
"nepoznat", novo stanje mora biti "nestao".
Promenljivu $nazivStatusa treba emitovati na izlaz.
Rešenje:
$poslednjiStatus = 2;
$status = 4;
$nazivStatusa = "nepoznat";
if($status == 1)
$nazivStatusa = "stoji";
else if($status == 2)
$nazivStatusa = "krece se";
else if($status == 3)
$nazivStatusa = "nestao";
else if($status == 4)
{
41
if($poslednjiStatus == 2)
$nazivStatusa = "nestao";
else
$nazivStatusa = "nepoznat";
}
echo $nazivStatusa;
Vežba 4
Problem:
Potrebno je napisati program koji omogućava korisniku da pogađa zamišljeni broj, željeni broj definišete u kodu.
Takođe, da bi korisnik znao koliko je blizu odgovora obavestite ga porukom ukoliko je razlika između pogođenog i
zadatog broja manja od 10.
Rešenje:
<?php
$tajniBroj = 765;
$_POST[ 'pogodak' ] = 754;
if ($_POST[ 'pogodak' ] == $tajniBroj )
{
echo ' <p> Cestitam!!! </p> ';
}
elseif( abs ($_POST[ 'pogodak' ] - $tajniBroj) < 10 )
{
echo ' <p> Blizu ste resenja!!! </p> ';
}
else
{
echo ' <p> Zao mi je!!! </p> ';
}
?>
Vežba 5
Problem:
U prodavnici kancelarijskog nameštaja vlasnici su utvrdili akcijske popuste u januaru za kupovinu radnih stolica prema
sledećem pravilniku:
Za manje od 10 kupljenih stolica – nema popusta,
Za 10 – 49 kupljenih stolica – popust od 5%,
Za 50 – 99 kupljenih stolica – popust od 10%,
Za kupljenih 100 ili više stolica – popust od 15%.
Potrebno je napisati programski kod koji će koristeći se if else strukturama izračunavati popuste prilikom kupovine.
Preporuka: koristite se operatorom konjunkcije ( &&).
Rešenje:
<?php
$stolice = 10;
if ( $stolice < 10)
{
$popust = 0;
}
42
elseif ( $stolice >= 10 && $stolice <= 49 )
{
$popust = 5;
}
elseif ( $stolice >= 50 && $stolice <= 99 )
{
$popust = 10;
}
elseif ( $stolice >= 100 )
{
$popust = 15;
}
echo $popust;
?>
Kao što smo ranije objasnili, u prethodnom kodu korišćena je elseif naredba sa međusobno isključivim uslovima (samo
jedan od uslova može biti zadovoljen).
Switch naredba
Ova naredba se koristi u situacijama kada uslov koji se testira može da ima više vrednosti, od kojih zavisi dalje
izvršavanje programa. Switch-case naredba ima sledeću sintaksu:
switch ( promenljiva )
{
case "izraz" :
naredbe1
break;
case "izraz" :
naredbe2
break;
default :
naredbe3;
}
Kod switch strukture prvo se izračunava izraz, a zatim se dobijena vrednost poredi sa vrednostima navedenim u Case
oznakama. Ukoliko je vrednost izraza jednaka nekoj od vrednosti iz Case oznake, izvršava se grupa naredbi koja sledi
tu oznaku. Ukoliko je vrednost izraza različita od svih navedenih, izvršava se grupa naredbi nakon default oznake.
43
Ovu strukturu je jednostavno zaobići if-else strukturom, ali u nekim slučajevima switch-Case je praktičniji i pregledniji.
Na primer, u if-else strukturi morate prilikom svake provere da smeštate promenljive i uslovni izraz, dok je kod Switch-
Case to nepotrebno. Kod Switch-Case, sa druge strane, ne možete da menjate promenljivu, već samo izraze nad
njom. Osim toga, Switch-Case, iako dosta pregledan, nije baš podoban za velike uslovne blokove. Obično se u njega
smeštaju ili kratke uslovljene akcije ili funkcije.
Pogledajmo primer:
$a = 2;
switch( $a )
{
case 1:
echo "a je jedan";
break;
case 2:
{
echo "a je dva";
break;
}
default:
echo "a nije ni jedan ni dva";
}
U primeru smo prvo inicijalizovali promenljivu $a, a zatim je postavili u switch strukturu. Switch struktura podrazumeva
blokove uslova, obavezno oivičene vitičastom zagradom. Svaki uslov započinje ključnom rečju Case, kojoj sledi
uslovna vrednost ili uslov i dvotačka koja označava početak bloka. Ovaj blok možete i ne morate smestiti u vitičaste
zagrade. Za razliku od standardnih uslovnih blokova, u slučaju Case bloka, biće izvršen kompletan uslovljeni blok (a ne
samo prvi red). Štaviše, ukoliko se uslov u nekom trenutku (slučaju) ispuni, biće izvršene sve naredne linije, sve dok
program ne dobije direktivu da napusti kompletnu strukturu ili se struktura ne završi.
$a = 1;
switch( $a )
{
case 1:
echo "a je jedan";
case 2:
echo "a je dva";
default:
echo "a nije ni jedan ni dva";
}
Ovaj kod će u PHP-u, kao rezultat, dati sve tri echo naredbe (»a je jedan je dva a nije ni jedan ni dva«), upravo zbog
toga što nigde ne postoji izlaz iz strukture. To znači da je podrazumevani deo svakog Case bloka i naredba break
(bezuslovno napuštanje strukture).
Što se Switch-Case strukture tiče, PHP je, u odnosu na druge jezike, veoma fleksibilan. Dok su u drugim jezicima ove
strukture najčešće ograničene samo na celobrojne vrednosti, PHP u strukturu može prihvatiti bilo koju vrednost i zatim
je korektno obraditi kroz “slučajeve”.
$a = "mojaVrednost";
switch( $a )
{
case 1:
echo "a je jedan";
break;
case "mojaVrednost":
echo "a radi i sa stringovima";
break;
default:
echo "nije ni jedna od dve vrednosti";
}
44
Osim skalarnih vrednosti, slučajevi mogu prihvatiti i kompletne izraze. Na primer, možemo proveriti da li je neka
vrednost jednaka, veća ili manja od ulazne:
case: $a < 1 ...
Čak, možemo proveravati i uslove koji su van konteksta:
$a = 1;
$b = 2;
switch( $a )
{
case $b == 2:
echo "b je dva";
break;
case 1:
echo "a je jedan";
break;
}
Ovaj primer u PHP-u je potpuno validan. Naravno, osim što je dobro znati da je i tako nešto izvodljivo u PHP-u, nije
preporučljivo za produkcionu upotrebu.
U Case uslov možete smestiti i funkciju:
$a = array(1, 2, 3);
switch( $a )
{
case 1:
echo "a je jedan";
break;
case is_array( $a ):
echo "a je niz";
break;
}
pa čak i kompleksniji tip, poput niza, pri čemu je moguće ne samo porediti da li je promenljiva niz ili da li su dva niza
identična, već i kreirati niz za poređenje unutar samog Case uslova:
$a = array(1, 2, 3);
switch( $a )
{
case 1:
echo "a je jedan";
break;
case $a == array(1, 2, 3):
echo "a je niz";
break;
}
Kada je u pitanju case izraz možete se služiti promenljivima tipa integer, double i string dok se nizovi i objekti ne mogu
prihvatiti kao ulazne promenljive ukoliko nisu naznačeni kao prostiji tipovi.
Naredba break
U svim dosadašnjim primerima mogli ste uočiti naredbu break na kraju svakog case bloka. Sledećim primerom
objasnićemo značenje, odnosno osnovnu ulogu break naredbe u okviru switch – case blokova naredbi.
45
<?php
$kategorija = "vesti";
switch ( $kategorija )
{
case "vesti" :
echo ' <p> Vesti iz sveta ... </p> ';
break;
case "vreme" :
echo ' <p> Vasa vremenska prognoza ... </p> ';
break;
case "sport" :
echo ' <p> Posledni sportski rezultati ... </p> ';
break;
default :
echo ' <p> Dobro nam dosli ... </p> ';
}
?>
Prikazani primer je standardnih okvira i sintakse koju smo već objasnili, svakako, podrazumeva se da je promenljiva
$kategorija u prethodnom delu koda već deklarisana, što smo i uradili na samom početku php skripte:
$kategorija = "vesti";
Naš program bi na izlazu ispisivao:
Vesti iz sveta...
Ovakav rad programa i switch – case strukture ostvaruje se upravo radom break naredbe. Evo o čemu je reč:
Prilikom izvršavanja program vrši proveru koja od case blokova zadovoljava vrednost promenljive $kategorija, kada je
pronađe, nailazi na naredbu break i zaustavlja dalje izvršavanje programa. Kada bismo izostavili break naredbe iz
predhodnog koda, naš php skript bi imao sledeću strukturu:
<?php
$kategorija = "vesti";
switch ( $kategorija )
{
case "vesti" :
echo ' <p> Vesti iz sveta ... </p> ';
case "vreme" :
echo ' <p> Vasa vremenska prognoza ... </p> ';
case "sport" :
echo ' <p> Posledni sportski rezultati ... </p> ';
default :
echo ' <p> Dobro nam dosli ... </p> ';
}
?>
Izostavljanjem breaka u okviru case blokova, naš program izvršava sve case blokove zanemarujući switch uslovnu
promenljivu, ispis na izlazu nako izvršenja biće:
Vesti iz sveta ...
Vasa vremenska prognoza ...
Posledni sportski rezultati ...
Dobro nam dosli ...
46
Naredba default
Na kraju svake Switch-Case strukture nalazi se naredba default. Kada pokrenemo program, php pokušava da pronađe
neki od case blokova koji zadovoljava unapred utvrđeni uslov; u slučaju da nijedan od ponuđenih uslovnih naredbi ne
zadovoljava predviđene kriterijume dolazi do izvršavanja upravo default naredbe. Default naredba je, najkraće rečeno,
komanda koja se izvršava kada nijedna druga nije zadovoljavajuća. Evo i konkretnog primera:
<?php
$i = 5; // primer unosa korisnika
switch ( $i ) {
case 0:
echo "i je jednako 0";
break;
case 1:
echo "i je jednako 1";
break;
case 2:
echo "i je jednako 2";
break;
default:
echo "i nije jednako ni 0, 1 ni 2";
}
?>
Nakon izvršenja programa na izlazu dobijamo ispis:i nije jednako ni 0, 1 ni 2
… što upravo predstavlja našu default naredbu.
Obratite pažnju na to da pozicija slučaja ne igra ulogu na tok strukture. Sledeći primer će dati rezultat isti kao i
prethodni, iako je redosled slučajeva drugačiji.
<?php
$i = 5; // primer unosa korisnika
switch ( $i ) {
default:
echo "i nije jednako ni 0, 1 ni 2";
break;
case 1:
echo "i je jednako 1";
break;
case 0:
echo "i je jednako 0";
break;
case 2:
echo "i je jednako 2";
break;
}
?>
Primer 1:
Često se na prodajnim sajtovima srećemo sa delom popunjavanja upitnika "Kako ste saznali za nas". Upravo ovi
upitnici funkcionišu preko switch – case struktura.
47
Figura 1 - Primer forme "kako ste nas našli"
Svakako, sam izgled i odabir načina koji se povezuje sa case blokovima pripada naprednijim kursevim i iz tog razloga
nećemo kreirati HTML stranice sa padajućim menijima koji sadrže vrednosti naše promenljive za switch uslov,
objasnićemo samo switch – case deo php skripta.
Kada postavimo da naša promenljiva $nacin koju smo deklarisali sadrži vrednosti a, b, c ... kojima se dalje služimo kao
odabranim poljima na stranici možemo da koristimo sledeći kod:
<?php
$nacin = "b";
switch ( $nacin )
{
case "a":
echo '<p> Redovana musterija ... </p>';
break;
case "b":
echo '<p> Musterija saznala preko TV reklame ... </p>';
break;
case "c":
echo '<p> Musterija dobila preporuku od prijatelja ... </p>';
break;
default :
echo '<p> Ne znamo kako nas je musterija pronasla ... </p>';
}
?>
Da bismo uočili rad programa, dodelili smo promenljivoj $nacin pre switch – case strukture vrednost "b" kako bismo
simulirali odabir načina opredeljenja mušterije. Nakon izvršenja programa na izlazu biće ispisano:
Musterija saznala preko TV reklame ...
Primer 2:
Lista naredbi u okviru case blokova može biti i prazna, i kao takva jednostavno nastavlja prolazak na sledeći case blok
koji sadrži neku naredbu za izvršenje. Bitno je napomenuti da ovako struktuiran kod neće dovesti do greške, php ga
čita kao komandu za koju nema argumente da bi je završio nego je jednostavno preskače tragajući dalje za
odgovarajućom naredbom. Primer ovako strukturiranog koda se nalazi u nastavku:
48
<?php
$i = 0;
switch ( $i )
{
case 0 :
case 1 :
case 2 :
echo " Promenljiva je veca od 3 ali nije negativna ... ";
break;
case 3:
echo " Promenljiva je jednaka 3 ";
}
?>
Primer 3:
Iz primera u nastavku možemo zaključiti da u okviru switch izraza možemo vršiti i operacije manjeg stepena kao što je,
na primer, operacija uvećavanja:
<?php
$a = 0;
switch( ++ $a )
{
case 3 :
echo 3;
break;
case 2:
echo 2;
break;
case 1:
echo 1;
break;
default :
echo "Ne slaze se!";
break;
}
?>
Nakon izvršavanja programa na izlazu dobićemo rezultat:
1
Što potvrđuje da je operacija u okviru switcha izvršena, pa je promenljiva koja na početku ima vrednost 0 nakon
prolaska kroz switch – case dobila vrednost 1.
Vežba 1
Problem:
Potrebno je napraviti kod koji će sadržati pet konstanti za radne dane nedelje (MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY).
Takođe, kod treba da sadrži deo koji proverava konstantu (dan nedelje) i na osnovu nje prikazuje opis dana putem
switch-case strukture. Ukoliko je ponedeljak, opis je "prvi dan nedelje" itd. Potrebno je izvršiti testiranje kreiranog koda.
49
Rešenje:
<?php
define( "MONDAY", 1 );
define( "TUESDAY", 2 );
define( "WEDNESDAY", 3 );
define( "THURSDAY", 4 );
define( "FRIDAY", 5 );
$day = MONDAY;
switch( $day )
{
case MONDAY:
$description = "First day of week";
break;
case TUESDAY:
$description = "Second day of week";
break;
case WEDNESDAY:
$description = "Third day of week";
break;
case THURSDAY:
$description = "Forth day of week";
break;
case FRIDAY:
$description = "Fifth day of week";
break;
default:
$description = "no description";
break;
}
echo $description;
?>
Vežba 2
Problem:
Potrebno je napraviti kod koji će na osnovu promenljivih $operator, $operand1 i $operand2 izvršiti računsku operaciju i
prikazati rezultat.
Potrebno je upotrebiti switch-case strukturu u tu svrhu.
50
Rešenje:
<?php
$operator = "-";
$operand1 = 2;
$operand2 = 3;
$result = 0;
switch( $operator )
{
case "+":
$result = $operand1 + $operand2;
break;
case "-":
$result = $operand1 - $operand2;
break;
case "*":
$result = $operand1 * $operand2;
break;
case "/":
$result = $operand1 / $operand2;
break;
}
echo $result;
?>
Vežba 3
Problem:
Potrebno je napraviti program koji će obaveštavati korisnika o aktivnostima prilikom rada na kursu. Proverava se broj
ulazaka u nastavnu jedinicu i na osnovu toga izdaju se obaveštenja o početku učenja, testu po modulu i završetku
kursa.
Koristiti switch – case strukturu i broj ulazaka na samom početku se postavlja na 0, kako bi se omogućilo brojanje
ulazaka u daljem kodu.
Rešenje:
<?php
$brojUlazaka = 0;
switch ( $brojUlazaka )
{
case 0 :
echo ' Dobro dosli, mozete poceti sa ucenjem ...';
break;
case 20 :
echo ' Vreme je za rad na testu po modulu ...';
break;
case 30 :
echo ' Kurs je zavrsen, cestitamo vam ...';
break;
default :
echo ' Rad na kursu u toku ...';
break;
}
?>
Napomena: nakon izvršavanja zadataka za vežbu preporučuje se i testiranje koda. Kod možete testirati dodeljivanjem
novih vrednosti deklarisanim promenljivima u okviru zadataka i na taj način proveriti ponašanje switch – case struktura
sa drugačijim uslovnim izrazima.
51
for petlja
Jedinica: 7 od 19
Rezime
U PHP-u postoji nekoliko vrsta petlji: for, while, foreach i njihove varijacije
for petlju upotrebljavamo kada znamo njene inicijalne vrednosti (koliko će se puta izvršiti)
For petlja podrazumeva inicijalizaciju iz tri dela: inicijalizacija brojača, uslov brojača i inkrement/dekrement
brojača
For petlja ne mora imati sva tri inicijalna parametra
Foreach petlja se koristi za čitanje nizova
Foreach petlja može čitati vrednosti ili ključeve i vrednosti iz niza
Petlja se može bezuslovno prekinuti ključnom rečju break
Iteracija petlje se može preskočiti ključnom rečju continue
U ovoj lekciji radićemo for petlje. U programiranju je često potrebno ponoviti isti blok naredbi nekoliko puta. Ovo
ponavljanje se postiže upotrebom petlji. PHP ima nekoliko tipova petlji, ali se, kada se izuzmu razne varijacije, broj
petlji svodi na dve for i while petlje. U ovoj lekciji reći ćemo nešto više o for petlji.
For petlja
For petlja se koristi kada se unapred zna tačan broj koliko puta je potrebno izvršiti neki blok naredbi. Ova petlja ima
sledeću sintaksu:
for (inicijalizacija; uslov; povećanje) {
blok naredbi;
}
Prvi parametar se koristi da kreira i postavi početnu vrednost brojaču. Drugi parametar sadrži uslov za brojač, a treći
određuje na koji način se brojač povećava. Sledeći primer koda ispisuje pozdravnu poruku četiri puta:
<?php
for ($brojac=1; $brojac < 5; $brojac++) {
echo "Dobro došli!" . "<br/>";
}
?>
Prvo se vrednost promenljive $brojac postavlja na 1. Drugi parametar sadrži uslov. Blok naredbi će se izvršavati dok
god je ovaj uslov tačan. Treći parametar povećava promenljivu $brojac za jedan.
For petlje se često koriste za prolazak kroz nizove. Na primer:
<?php
//kreira se novi niz od pet elemenata
$boje = array('crvena', 'zelena', 'plava', 'zuta','bela');
//koristi se for petlja za prolaz kroz niz i ispisivanje njegovih elemenata
for ($i = 0; $i < sizeof($boje); $i++)
{
echo "Vrednost elementa $i+1 is $boje[$i].";
}
?>
Gore kreirani niz ima pet elemenata; pri tom su indeksi elemenata u rasponu od 0 do 4. Zbog toga se, u uslovu, koristi
stroga nejednakost, da program ne bi pokušao da pristupi elementu sa indeksom 5, koji ne postoji.
Znamo da postoje tri dela inicijalizacije for petlje. U prethodnim primerima je svaki deo imao po jedan parametar, ali
ovo nije i obavezna struktura. Ponekad možemo u jednoj inicijalizaciji definisati više parametara.
52
Sledeća petlja će inicijalizovati promenljive $i i $a i dodeliti im različite vrednosti. Zatim, postavlja neki uslov (da $i bude
manje od 10), a zatim interveniše na obe vrednosti, povećavajući ih za jedan.
for($i=0,$a=5;$i<10;$i++,$a++)
echo $i . ":" . $a . "<br>"
Ali, sintaksni preduslov ne podrazumeva čak ni unos sva tri parametra. Sledeći primer će takođe biti validan:
for($i=0;$i<10;) echo $i++;
U primeru, treći parametar je izostavljen. On zapravo nije izostavljen, samo je potpuno prazan, što pokazuje oznaka ;
iza broja 10.
Nakon ovakve inicijalizacije, inkrementiranje smo izvršili u samom bloku, što može biti veoma opasno, jer, ukoliko dođe
do izostanka inkrementa, možemo pasti u takozvanu mrtvu petlju (petlja se izvršava beskrajno) koja će, u najboljem
slučaju, blokirati okruženje.
Mrtve petlje se generalno treba paziti, jer postoje razni načini da se ona proizvede. Jednostavno, pazite da vaša petlja
ne izgleda tako da njeni uslovi za izvršavanje mogu biti uvek ispunjeni. Na primer: for($i=1;$i>0;) echo $i++;
Primećujete da su prethodna dva primera napisana u jednom redu. To je zbog istog pravila koje važi i za sve ostale
strukture za kontrolu toka. Nakon uslova, možete napisati samo jedan red koda bez zagrada. Ukoliko hoćete da
napišete neki blok (dve linije i više), morate ceo blok staviti u vitičaste zagrade.
Vodite računa o tome da će vrednosti petlje ostati i nakon izvršenja petlje, tako da, ako napišete:
for($i=0;$i<10;$i++)
echo $i;
vrednost $i nakon izvršenja će biti 10. Zato je najbolje da se držite nekih standardnih naziva promenljivih, koje ćete
koristiti samo u tu svrhu. Na primer, baš slovo i. Tako ćete uvek znati da vam je to slovo rezervisano za petlju i nećete
ga upotrebljavati za aktuelne promenljive. Naravno, ovo je samo savet. Za nazive promenljivih u petljama važe ista
pravila kao i za nazive svih ostalih promenljivih u PHP-u.
For petlje možete gnjezditi jednu u drugu. Čak, kroz praksu, videćete da se veći programi upravo i sastoje iz petlji koje
se nalaze u nekim većim petljama, a koje se, opet, nalaze u nekim, još većim petljama. Kada budete i sami počeli da
pravite neke kompleksnije strukture (sa ugnježdenim petljama) pazite na redosled izvršavanja petlji. Ne zaboravite da
se vaš program, ma koliko bio kompleksan, izvršava sekvencijalno i da će, ukoliko u bilo kom trenutku započnete neki
proces, svi ostali procesi biti zaustavljeni sve dok taj proces ne završi (naravno, ovo pravilo ne važi za programiranje u
realnom vremenu i multitasking programiranje).
for($i=0;$i<10;$i++)
for($u=0;$u<10;$u++)
echo $u;
Ovaj primer će jasno ispisati promenljivu $u 100 puta. Ali, kolika će biti ta promenljiva $u u svakom trenutku
izvršavanja?
Pošto je petlja $i spoljašnja petlja, i petlja $u se izvršava unutar nje, svaki put kada se dogodi jedna iteracija petlje $i,
izvršiće se kompletan ciklus petlje $u.
prva iteracija petlje $i
prva iteracija petlje $u
druga iteracija petlje $u
...
deseta iteracija petlje $u
druga iteracija petlje $i
....
i tako, sve do poslednje iteracije petlje $i, kada će i ceo njen ciklus biti završen.
Na početku petlje smo pomenuli da se brojač petlje povećava. Ovo nije obavezno pravilo. Brojač se može i smanjivati,
pa čak (što smo videli u jednom od prethodnih primera) ne mora ni postojati.
53
for($i=10;$i>0;$i--) echo $i;
Foreach petlja
Ova petlja je varijacija for petlje, namenjena isključivo radu sa nizovima. Naročito asocijativnim. Upravo je to razlog što
nećemo previše detaljno ulaziti u opis ove petlje, već ćemo samo reći par reči o osnovama njenog funkcionisanja, jer
prosto, još uvek nismo obradili nizove.
Ona ima dva oblika. Jedan podrazumeva rukovanje vrednostima, a drugi rukovanje ključevima i vrednostima.
Foreach funkcioniše veoma jednostavno (sa strane korisnika) jer, praktično, nije potrebno ništa da znamo o nizu kroz
koji hoćemo da prođemo osim njegovog imena. Pri inicijalizaciji, unosimo naziv niza i naziv promenljive za koju želimo
da preuzima aktuelnu vrednost niza prilikom svake iteracije. Ili, u drugom obliku, aktuelne vrednosti ključa i vrednosti:
Prvi oblik podrazumeva:
foreach (niz as $vrednost)
{
blok naredbi
}
Kod prvog oblika prolazi se kroz niz i prilikom svake iteracije, vrednost tekućeg elementa se smešta u promenljivu
$vrednost. U bloku naredbi je, zatim, moguće koristiti ovu promenljivu, a da pri tom originalna vrednost sadržana u
tekućem elementu niza ne bude promenjena.
Pogledajte sledeći primer:
<?php
$boje = "";
$moj_niz = array('crvena','zelena','plava');
Tokom svakog prolaska kroz petlju, vrednost tekućeg elementa se dodeljuje promenljivoj $value. Ova vrednost se
zatim dopisuje na promenljivu $boje, zajedno sa jednim praznim karakterom. Na kraju, rezultat će biti:
Boje sadrzane u nizu su: crvena zelena plava
On ima istu funkcionalnost kao i prvi oblik, s tom razlikom što, sem vrednosti samog elementa, koristi i vrednost
indeksa i smešta ga u promenljivu $indeks.
Kao što vidite, foreach radi prilično automatski. To je nekada dobro, ali nekada i loše, jer kada radimo sa foreach ne
rukujemo članovima niza eksplicitno kroz njihove indekse, već samo dobijamo njegove vrednosti, pa se tako za foreach
može reći da je dobar kada želimo brzo i jednostavno da izvršimo čitanje nekog niza, ali ne i neke ozbiljnije intervencije
na njemu.
Iako u primerima svaka foreach petlja prethodi bloku u vitičastim zagradama, i ovde važi pravilo da ne moraju postojati
vitičaste zagrade za samo jednu liniju koda.
foreach (niz as $indeks => $vrednost) echo $vrednost;
54
Kontrola toka petlje
Kontrolu toka petlje možemo vršiti na nekoliko načina. Prvi način je, svakako, ručnom modifikacijom kontrolne
promenljive (brojača).
for($i=0;$i<10;$i++)
{
if($i>5) $i=10;
echo $i;
}
U primeru smo rekli petlji da se izvršava sve dok je promenljiva i manja od deset uz inkrement 1. A zatim smo se, u
bloku, predomislili i rekli da, ukoliko je brojač veći od 5 (dakle 6), brojač dobije vrednost 10. Pošto je brojač dobio
vrednost kojom petlja ne ispunjava uslove za izvršavanje, petlja biva napuštena. Ovo rešenje će funkcionisati, ali je
nezgrapno, jer, u tom slučaju, moramo poznavati ciljnu vrednost brojača, što često neće biti moguće (npr.
for($i=0;$i<$u;$i++)).
Drugi (pravi) način je upotreba ključne reči break. Ovu reč smo upoznali u prethodnoj lekciji, kada smo rekli da ona
bezuslovno prekida blok koda.
for($i=0;$i<10;$i++)
{
if($i>5) break;
echo $i;
}
Upotrebom ove ključne reči naša petlja nije previše izgubila na veličini, ali je zato dosta dobila na dinamici, jer sada
više ne moramo da znamo krajnju vrednost petlje.
Naredba break može imati i parametar. Ukoliko ga unesemo, break će napustiti blokove u dubini naznačenoj u
parametru.
for($i=0;$i<10;$i++)
{
for($u=0;$u<10;$u++)
{
if($u==5)
break 2;
}
echo $i;
}
Ako pokrenemo ovaj primer, na ekranu neće biti ispisano ništa, iako se break naredba nalazi u unutrašnjoj petlji, koja
nam nije neophodna za izvršavanje spoljašnje petlje. Ali, s obzirom da u trenutku ispunjenja uslova $u=5 u unutrašnjoj
petlji, spoljašnja petlja nije završila još ni jednu iteraciju i nije stigla da ispiše poruku na ekranu, a s obzirom na to da
uslov aktivira naredbu break, i da ona ima parametar 2 (znači prekida dva bloka po dubini), prekinuće izvršenje
sopstvene petlje, i petlje iznad nje.
Ali, ponekad će se dogoditi da želimo da postavimo neki uslov u toku trajanja petlje, za koji, kada se ispuni, ne želimo
da izvršimo iteraciju petlje. Na primer, zamislimo neku ogromnu listu ljudi (nekoliko miliona). Svi ti ljudi se nalaze u bazi
podataka i nama je potrebno da izdvojimo određenu grupaciju u kojoj su samo prosvetni radnici.
Recimo da čitanje podataka o zanimanju svakog člana liste traje 1 sekund, a čitanje kompletnih podataka o članu 5
sekundi.
Recimo sada da procedura čitanja podrazumeva: čitanje podataka o zanimanju, mestu stanovanja, čitanje imena,
čitanje prezimena... (što kompletno traje 5 sekundi). Ako budemo prolazili kroz kompletnu proceduru za svakog člana,
izgubićemo 5 sekundi po članu, što za sve članove iznosi mnogo sekundi. Sa druge strane, možemo odmah, na
početku, pogledati da li je član prosvetni radnik (za šta nam treba samo jedan sekund), i, ako nije, odmah preuzeti
podatke sledećeg člana sa liste i na taj način uštedeti 4 sekunde. Što je na pomenutu cifru od nekoliko miliona priličan
broj sekundi.
55
Ovaj jednostavan primer kod ljudi funkcioniše automatski, ali, programu je, da bi razmišljao na taj način, potrebno to
eksplicitno naglasiti. Ovo naglašavanje vrši se ključnom rečju continue.
Ovako bi izgledao pseudo kod pomenutog primera uz upotrebu ključne reči continue:
for($clanListe = 0; $clanListe < 1000000; $clanListe ++)
{
if($clanListe != "prosvetniRadnik")
continue;
//OGROMNI KOD KOJI CITA SVE OSTALE PODATKE O CLANU LISTE
//......
}
Vežba 1
Problem:
Potrebno je napraviti program koji će iscrtati sledeću strukturu:
XXXXXXXXXX
XXXXXXXXXX
Pomoć:
Novi red je prilikom emitovanja u HTML moguće ostvariti sledećom naredbom:
echo "<br>";
Rešenje:
<?php
$numElements = 1000;
$numColumns = 20;
for($i=0;$i<$numElements;$i++)
{
if($i%$numColumns==0 && $i>0)
echo "<br>";
echo "X";
}
?>
Vežba 2
Problem:
U aplikaciju ulazi određeni broj koji se nalazi u promenljivoj $selectedNumber. Potrebno je napraviti petlju koja se
izvršava onoliko puta kolika je vrednost promenljive $odabraniBroj i prilikom svake iteracije podiže se na eksponent
jednak broju trenutne iteracije petlje (prvi krug petlje ^1, drugi krug ^2...).
Pomoć:
PHP poznaje funkciju za eksponent: pow(vrednost,eksponent)
56
Rešenje:
$selectedNumber = 20;
for($i=1;$i<=$selectedNumber;$i++)
echo pow($selectedNumber,$i) . "<br>";
Vežba 3
Problem:
Na osnovu sledećih promenljivih:
$a = 5;
$b = 8;
i ugnježdenih petlji, potrebno je napraviti sledeći izlaz:
012345678
100000008
200000008
300000008
412345678
Rešenje:
<?php
$a = 5;
$b = 8;
for($i = 0; $i < $a; $i++)
{
echo $i;
for($u = 1; $u <= $b; $u ++)
{
if($u == $b || $i == 0 || $i == $a-1)
echo $u;
else
echo "0";
}
echo "<br>";
}
?>
Vežba 4
Problem:
U aplikaciju ulaze dve promenljive:
$numberOfCharacters = 50;
$characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
Potrebno je napraviti aplikaciju koja na osnovu prosleđenog seta karaktera i broja generiše šifru. Šifra mora sadržati
mala i velika slova iz liste karaktera $characters. Šifra takođe mora imati onoliko karaktera koliko je naznačeno u
promenljivoj $numberOfCharacters.
Šifru je potrebno emitovati na izlaz.
57
Rešenje:
<?php
$numberOfCharacters = 50;
$characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$allCharacters = $characters . strtolower($characters);
$sifra = "";
for($i=0;$i<$numberOfCharacters;$i++)
$sifra.=$allCharacters[rand(0,strlen($allCharacters)-1)];
echo $sifra;
?>
while petlja
Jedinica: 8 od 19
Rezime
While i do while vrše ponavljanje jednog istog zadatka određeni broj puta
While i do while su petlje koje kreiramo kada ne znamo koliko će tačno puta neki proces morati da bude izvršen
While petlja podrazumeva stupanje u telo petlje i njegovo izvršavanje samo ukoliko je uslov petlje ispunjen
Do while petlja podrazumeva obavezno izvršavanje bar jedne iteracije petlje, pre nego što do provere uopšte i
dođe
While i do while petlje je moguće prekinuti ključnom rečju break
Moguće je preći na sledeću iteraciju while i do while petlje ključnom rečju continue
While i do while petlja podrazumeva uslovni izraz, čija vrednost mora biti tipa boolean
Izvršenjem while i do while petlje se vrši ručno, unutar petlje i zato treba paziti da se ne upadne u mrtvu petlju
U ovoj lekciji radićemo while peltju. U PHP-u while petlja prestavlja najjednostavniju petlju. Kao i if naredba, koju smo
već obradili u prethodnim lekcijama, while petlja zavisi od uslova. Potrebno je napraviti paralelu između while i if –
pošto se često porede i programeri nisu uvek sigurni koju da koriste. Da biste znali koja je naredba ispravnija za
korišćenje pođite od naredbe koja treba da se izvrši po zadovoljavanju uslova. Osnovna razlika je upravo u tome što if
naredba izvršava blok naredbi koji sledi po zadovoljenju uslova samo jednom, dok while petlja izvršava naredbe dokle
god je uslov ispunjen.
S obzirom da se ova petlja ponavlja neki blok naredbi dok god je neki uslov tačan.
Sintaksa while petlje je:
while ( uslov )
{
blok naredbi;
}
58
Promenljiva $number na početku koda dobija vrednost 5. Zatim se proverava uslov ($number >= 2). S obzirom na to
da je ovaj uslov tačan, program počinje da izvršava blok naredbi unutar while petlje. Unutar ovog bloka ispisuje se
tekući broj, a zatim se smanjuje za 1. Nakon prvog prolaska kroz blok naredbi, ponovo se proverava uslov. Ponoviće
se izvršavanje naredbi unutar petlje, sve dok je uslov tačan. Nakon izlaska iz petlje, rezultat na izlazu će biti sledeći:
5
4
3
2
Vidimo da u inicijalizaciji petlje ne postoji nešto poput inkrementacije u for petlji. Zapravo, ova petlja čak i ne mora da
rukuje bilo kakvim brojačem. Jedino što joj je potrebno, to je da, prilikom svake sledeće iteracije, vrednost uslova bude
tačna. Ovo može da predstavlja i problem, jer ovakvu petlju moramo kontrolisati ručno.
Na primer, šta bi se dogodilo ukoliko bismo iz prethodnog primera izostavili deo:
$number -= 1;
While petlja se može podeliti na dve vrste: while i do while. Odnosno, petlju koja se ne izvršava ni jednom, ukoliko
uslov nije ispunjen (while) i petlju koja se izvršava bar jednom, čak i ako uslov nije ispunjen (do while). Prvu vrstu smo
već videli. Ništa unutar petlje iz primera se neće izvršiti ukoliko promenljiva $number pre ulaska u petlju ne bude veća
ili jednaka broju dva.
Ali, šta ako bismo želeli da telo ipak bude izvršeno, bar jednom?
Do...while petlja
Ova petlja je slična prethodnoj, s tom razlikom što se kod do ... while petlje uslov proverava nakon izvršavanja bloka
naredbi, a ne pre. To znači da će se blok naredbi unutar do ... while petlje izvršiti barem jednom, bez obzira na tačnost
uslova. Sintaksa Do ... while petlje ima sledeći oblik:
do
{
blok naredbi;
}
while ( uslov );
Kod koji sledi daje isti rezultat kao i prethodni, ali je unutar njega korišćena do ... while petlja.
<?php
$number = 5;
do {
echo $number . "<br/>";
$number -= 1;
}
while ($number >= 2);
?>
U while petlji važe ista sintaksna pravila kao i u ostalim strukturama toka. Break, continue i pravilo obaveznog
stavljanja u vitičaste zagrade ukoliko je blok duži od jedne linije.
Ovo važi i za do while. Ali prilikom pisanja bez vitičastih zagrada budite oprezni, iako deluje kao da je blok oivičen
strukturom ( poput switch-case slučajeva ), u do while petlji ne samo da se neće izvršiti više od jedne linije unutar petlje
( bez vitičastih zagrada ) već će i doći do greške:
Ovaj kod će se neometano izvršiti:
$a = 5;
do
echo $a ++;
while( $a < 5 );
Obratite pažnju i na to da ispred naredbe do nema oznake ; ali da je ovaj znak obavezan iza linije koja sadrži while
naredbu (poslednje linije).
Vežba 1
Problem:
Dat je sledeći kod:
$html = <<<HTML
<div style="#S#"> #I# </div>
HTML;
$divNum = 10;
$style = "border: 1px solid black; background: yellow; margin: 5px; padding: 4px;";
Potrebno je kroz petlju realizovati kod koji će prikazati html kod u promenljivoj $html minimum jednom i maksimum broj
puta naveden u promenljivoj $divNum.
Prilikom svake iteracije u div tagu mora umesto oznake #I# biti broj iteracije, dok umesto oznake #S# mora biti
stilizacija naznačena u promenljivoj $style.
Rešenje:
<?php
$html = <<<HTML
<div style="#S#"> #I# </div>
HTML;
$divNum = 10;
$style = "border: 1px solid black; background: yellow; margin: 5px; padding: 4px;";
$html = str_replace("#S#", $style, $html);
$i = 0;
do
{
echo str_replace("#I#", $i, $html);
$i++;
} while ($i < $divNum);
?>
Napomena:
U primeru se (kako bi on bio uspešno realizovan) pojavljuju i elementi koji u ovom delu kursa još uvek nisu obrađeni.
Možete ih samo preskočiti i sačekati da budu objašnjeni u lekcijama, a možete se ukratko informisati o njima u
narednim redovima:
Oznake <<<HTML i HTML; su deo herodoc string sintakse. Ona omogućava da se string napiše i zapamti u svom
originalnom obliku. Uključujući nove redove i ostala formatiranja. Ovde smo ovu sintaksu upotrebili da bi zapamtili
string sa div tagom.
Funkcija str_replace menja sadržaj stringa. Ona ima tri parametra. Prvi je string koji se traži (u primeru to su #S# i #I#),
drugi parametar je string kojim će nađeni string biti zamenjen. A treći parametar je sam string na kome će intervencija
biti izvršena.
61
Vežba 2
Problem:
Potrebno je napisati program koji će sabirati brojeve od 1 do 10 i ispisivati zbirove nakon svakog sabiranja broja sa
sumom, a na kraju ispisati i sumu svih suma ( Total ) iz predhodnog perioda sabiranja. Potrebno je koristiti do ... while
petlju. Nakon izvršenje, program treba da ispisuje sledeći sadržaj:
0 + 1 je jednako : 1
1 + 2 je jednako : 3
3 + 3 je jednako : 6
6 + 4 je jednako : 10
10 + 5 je jednako : 15
15 + 6 je jednako : 21
21 + 7 je jednako : 28
28 + 8 je jednako : 36
36 + 9 je jednako : 45
45 + 10 je jednako : 55
Suma, total svih brojeva od 1 do 10 je: 55
Rešenje:
<?php
$suma = 0;
$broj = 0;
do
{
$broj ++;
echo $suma. " + ". $broj. " je jednako : ";
$suma = $suma + $broj;
echo $suma. "<br />";
}
while ( $broj!= 10 );
?>
Vežba 3
Problem:
Potrebno je napraviti tabelu kao na prikazanoj slici. Program treba da izračunava korake cena u odnosu na »Količina *
Cena« u zavisnosti od koraka pomeranja količina, početna vrednost je 10 i kreće se do 100, sa korakom uvećanja za
10. Pomoć prilikom formatiranja tebele (HTML kod) nalazi se u rešenju obeležena crvenom bojom.
Kolicina Cena
10 50
20 100
30 150
40 200
62
50 250
60 300
70 350
80 400
90 450
100 500
Rešenje:
<?php
$Cena = 5;
$brojac = 10;
echo "<table border = \"1\" align = \"center\" >";
echo "<tr><th> Kolicina </th>";
echo "<th>Cena </th></tr>";
while ( $brojac <= 100 ) {
echo "<tr><td>";
echo $brojac;
echo "</td><td>";
echo $Cena * $brojac;
echo "</td></tr>";
$brojac = $brojac + 10;
}
echo "</table>";
?>
Vežba 4
Problem:
Potrebno je napisati program koji će zadavanjem željenog broja (dodeljivanje vrednosti promenljivoj pre while petlje) na
izlazu ispisivati sve brojeve u opsegu većih od 200 i manjih od 400, ukoliko se željeni broj nalazi u predviđenom
opsegu. Koristiti while petlju ...
Ispis na izlazu biće, na primer, ukoliko je vrednost željenog broja jednaka 380:
Broj izvrsenja : 380
Broj izvrsenja : 381
Broj izvrsenja : 382
Broj izvrsenja : 383
Broj izvrsenja : 384
Broj izvrsenja : 385
Broj izvrsenja : 386
Broj izvrsenja : 387
Broj izvrsenja : 388
Broj izvrsenja : 389
Broj izvrsenja : 390
Broj izvrsenja : 391
Broj izvrsenja : 392
Broj izvrsenja : 393
Broj izvrsenja : 394
Broj izvrsenja : 395
63
Broj izvrsenja : 396
Broj izvrsenja : 397
Broj izvrsenja : 398
Broj izvrsenja : 399
Rešenje:
<?php
$broj = 380;
do
{
echo "Broj izvrsenja : $broj <br>\n";
$broj ++;
}
while ( $broj > 200 && $broj < 400 );
?>
Vežba 5
Problem:
Potrebno je napisati program za aukcisku prodaju koji će početi sa izvršavanjem po dobijanju početne vrednosti (cene),
dodeljivanjem vrednosti promenljivoj pre ulaza u petlju. Program ispisuje vrednosti uvećavajući ih za jedan i izdaje
obavestenje o odobrenju artikla za prodaju, kada cena dostigne vrednost preko 1000 status artikla je obaveštenje o
mogućnosti prodaje. Ispis na izlazu (ukoliko je početna vrednost postavljena na 999) na primer može izgledati ovako:
Trenutna cena je : 999. Jos uvek nije za prodaju.
Trenutna cena je : 1000. Jos uvek nije za prodaju.
Trenutna cena je : 1001. MOZETE POCETI SA PRODAJOM ! ! !
Rešenje:
<?php
$cena = 999;
do {
echo "Trenutna cena je : " . $cena . ". Jos uvek nije za prodaju. </br>";
$cena = $cena + 1;
}
while ($cena <= 1000);
echo "Trenutna cena je : " . $cena . ". MOZETE POCETI SA PRODAJOM ! ! !"; // (if not finished, re-start
WHILE loop)
?>
Vežba 6
Problem:
Potrebno je napisati program koji će za zadatu temperaturu vršiti konverziju iz Celzijusa (C) u Kelvine (K) i Farenhajte
(F). Potrebno je rešiti problematiku u okviru while petlje i uslov za izvršenje naredbe je da zadata temperatura bude
manja od 115 stepeni.
Rešenje:
<?php
$ctemp = -10;
while ($ctemp < 115) {
print ("$ctemp degrees C converts to ");
print (32 + $ctemp / 5 * 9 );
64
print (" degrees F and to ");
print ($ctemp + 273.1 );
print (" degrees K<BR>");
$ctemp = $ctemp + 20;
}
?>
U ovoj lekciji radićemo sa fajlovima i videćemo kako jedan fajl možemo uključiti u drugi. Korišćenje već napisanog koda
je veoma korisna i česta praksa u programiranju. Na primer, ukoliko web sajt sadrži meni koji se ponavlja na svakoj
strani, tada je mnogo jednostavnije napisati kod jedanput, a zatim ga dinamički uključiti na strane na kojima treba da se
pojavi, nego pisati kod u okviru svake strane. Ovo je moguće uključivanjem fajlova od strane servera.
Fajlovi koji se uključuju obično sadrže HTML ili PHP kod i snimaju se često sa ekstenzijom .inc, iako mogu biti snimljeni
i sa drugim ekstenzijama. Sadržaj ovakvih fajlova se kodira jedanput, a zatim poziva od strane strana na kojima je
potreban. Ukoliko dođe do izmene na originalnom fajlu, one su vidljive na svim stranama na kojima se koristi.
Na primer, dešava se da sve strane jednog web sajta, na svom vrhu, treba da imaju isto zaglavlje. Neka je HTML kod
zaglavlja:
<div style = "border: ridge 1px; width: 95%; background-color: #F0F0F0; padding: 5px" >
<h3> Dobro dosli na web sajt nase organizacije! </h3>
</div>
<div style = "border: ridge 1px; width:95%; background-color: #F0F0F0; padding: 5px">
<h3> Dobro dosli na web sajt nase organizacije! </h3>
</div>
<div style = "border: ridge 1px; width:95%; background-color: #F0F0F0; padding: 5px">
<h3> Dobro dosli na web sajt nase organizacije! </h3>
</div>
Ovaj kod je moguće snimiti unutar fajla nazvanog Header.inc. Nakon kreiranja fajla zaglavlja neophodno je da se on
uključi na svaku stranu na kojoj treba da se prikaže. To se postiže pomoću naredbi za uključivanje eksternih fajlova.
<?php
require( 'header.inc' );
echo "< p > Neki tekst..... < /p >";
?>
Ukoliko fajlovi koji se uključuju sadrže neke poverljive informacije, tada bi trebalo da budu snimljeni sa ekstenzijom
.php, kako korisnici ne bi mogli da vide njihov originalan sadržaj, već samo HTML kod, koji je rezultat izvršavanja
njihovog koda.
Kao što vidite, fajl koji se importuje nije jezički ograničen (u primeru, to je html fajl), a može biti i bilo koji drugi jezik (sve
dok sintaksa ostaje ispoštovana).
65
Funkcija require nije jedina funkcija koja može da uključi eksterni fajl u aktuelni PHP skript. Zapravo, postoje četiri
funkcije koje ovo mogu da urade i svaka ima svoje osobenosti.
Require
Funkcija require() poziva fajl header.inc i čita njegov sadržaj. Ovaj sadržaj se onda prikazuje kao deo strane sa koje je
pozvan. Na primer, ako imamo jedan PHP fajl, sa sledećim sadržajem i taj fajl nazovemo mojFajl.php :
<?php
echo "Pozdrav!";
?>
Ukoliko startujemo ovaj fajl, on će prikazati na strani poruku: Pozdrav!, jer je u sebe implementirao sadržaj drugog fajla.
Prilikom implementacije fajla na ovaj način, pazite: ne implementira se njegov izlazni sadržaj, već njegov izvorni
sadržaj.
To znači sledeće:
Fajl mojFajl.php iz primera, ako se startuje zasebno, emituje poruku Pozdrav!. To je sve što će biti izlaz tog fajla, jer je
to ono što PHP interpreter emituje. Ali, ukoliko taj fajl implementiramo u drugi PHP fajl kroz funkcije za implementaciju,
u njega ulazi njegov izvorni PHP kod a to je echo „pozdrav”;.
Kada bismo, na primer, stavili u sadržaj fajla mojFajl.php sledeći kod:
<?php
$a = "moja promenljiva";
?>
i emitovali taj fajl direktno u pretraživač, strana bi bila prazna.
Ali, ako isti fajl uvrstimo u postojeći PHP kod i zatražimo promenljivu $a, ona će dati regularan rezultat.
<?php
require "mojFajl.php";
echo $a;
?>
To znači da mi fajl moramo dobaviti pre nego što ga interpreter emituje na server, odnosno, sa samog fajl sistema.
Zato, na primer, sledeći kod ne bi funkcionisao:
<?php
require "http://localhost/mojFajl.php";
echo $a;
?>
66
<?php require ('header.php'); ?>
... sadržaj stranice ....
<?php require ('footer.php'); ?>
Ovakvim načinom rada smo u mogućnosti da, iako smo napisali veliki broj stranica, njihove headere i footere menjamo
samo na jednom mestu i sadržaj će biti reprodukovan na svim stranicama.
U okviru ovakvog primera uglavnom se koristi kombinacija HTML-a i PHP naredbi koje generišu dinamičke delove
stranica. Ukoliko vam se javi potreba da sadržaj datoteka obavezno obrađuje kao običan tekst i da se ne izvršava php
kod, alternativu predstavlja funkcija koja samo učitava sadržaj datoteke bez sintaksne analize, funkcija je readfile(),
koja iščitava sadržaje fajlova.
Include
Ukoliko sadžaj strane zavisi od sadržaja fajla koji importujete (na primer, u njemu su neke ključne promenljive), onda
možete koristiti funkciju require, jer će ona, ukoliko fajl iz bilo kog razloga ne bude uvršćen u postojeći kod, prekinuti
izvršavanje programa.
Ali, ako Vam sadržaj nije od velike važnosti (na primer, fajl koji uvršćujete je neki čitač vesti, koji prikazuje neke vesti
na nekom manje bitnom delu strane), možete iskoristiti i funkciju include. Njena sintaksa je ista kao i require, samo što
će se, ukoliko učitavanje ne uspe, nastaviti izvršavanje skripte.
Najbolje je da funkciju include „zamaskirate” error suppressor operatorom, tako da problem pri učitavanju ne poremeti
definiciju izgleda strane:
@include "mojFajl.php";
Include_once i require_once()
Zamislite sledeću situaciju:
require( "mojFajl.php" );
echo $a;
$a = "neka druga vrednost: ";
require( "mojFajl.php" );
echo $a;
Ako koristimo malopređašnji sadržaj sadržaja mojFajl.php, onda će ovaj program dva puta emitovati tekst moja
promenljiva, što najverovatnije nije efekat koji bismo želeli, jer smo u toku koda izmenili vrednost promenljive.
Da se ovo ne bi događalo, koristimo naredbu include_once i funkciju require_once.
Kada PHP dođe dođe do require_once ili include_once funkcije, proveriće da li već postoji implementacija istoimenog
fajla i, ukoliko postoji, neće izvršiti ponovno uključivanje.
Imajte na umu da, za razliku od include naredbi, require ne vraćaju nikakav rezultat, obzirom da momentalno prekidaju
izvršavanje programa. To znači da sledeća izjava neće funkcionisati:
require( "nepostojeciFajl.php" ) or die( "nema fajla" );
Ako želite da postignete ovako nešto, onda je možda najbolje da upotrebite drugačiji mehanizam:
if( !@include_once "nepostojeciFajl.php" )
echo "nema fajla";
Ili, možete proveriti postojanje fajla, a zatim u odnosu na tu proveru, izvršiti narednu akciju:
$fajl = "nepostojeciFajl.php";
if( file_exists( $fajl ) )
require_once ( $fajl );
67
else
echo "fajl ne postoji";
Definisanje raznih opcija u datoteci .htaccess umesto u datoteci php.ini ili u konfiguracionoj datoteci Web servera pruža
vam veliku fleksibilnost pri radu. Konfiguracione opcije, koje se podešavaju u višekorisničkom okruženju, se mogu
podesiti tako da važe samo u direktorijumu svakog korinika posebno. Ipak, kao i kod svakog metoda, i u ovom postoje
mane. Konkretan problem se javlja kada korisnik pokuša da učita bilo koju datoteku iz tog direktorijuma, a ne samo
jednom na početku, što nam ukazuje na usporavanje izvršenja programa.
Vežba 1
Problem:
U aplikaciju ulaze sledeće dve promenljive:
$file = "test";
$validExtension = "php";
Potrebno je napisati takav kod koji na osnovu naziva fajla i dozvoljene ekstenzije učitava određeni fajl naredbom
include.
Rešenje:
<?php
$file = "test";
$validExtension = "php";
switch( $validExtension )
{
case "php":
include $file . ".php";
break;
case "html":
68
include $file . ".html";
break;
case "js":
include $file . ".js";
break;
}
?>
Funkcije
Jedinica: 10 od 19
Rezime
Funkcije su jedan od ključnih elemenata OOP-a
Postoje ugrađene i korisnički definisane funkcije
Funkcija se može definisati bilo gde u kodu, a poželjno je na početku
Funkcije primaju parametre i vraćaju parametre
Funkcije mogu imati i podrazumevane vrednosti parametara
Promenljive deklarisane u funkciji nisu dostupne van funkcije
Da bi funkcije bile dostupne van funkcije, potrebno je korišćenje ključne reči global
Funkcijama se smanjuje veličina koda
Funkcijama se povećava portabilnost koda
U ovoj lekciji radićemo funkcije. Do sada smo se, iako još uvek nismo obradili taj pojam, dosta susretali sa funkcijama
u PHP-u. Zapravo, većina naredbi koje smo do sada izvršili bile su funkcije.
Nakon sledećeg opisa, lako ćemo prepoznati kada smo se tačno u dosadašnjem radu koristili funkcijama, po njihovoj
simptomatičnosti, odnosno, karakterističnoj formi.
Pre svega, da prvo razjasnimo šta je uopšte funkcija. Funkcija je neka programska struktura, koja je u stanju da na
osnovu određenih, primljenih parametara ili bez njih uradi neki posao i na osnovu urađenog posla vrati rezultat.
Razloga za korišćenje funkcija u programiranju ima zaista mnogo. Ali, osnovne pozitivne osobenosti funkcije su:
enkapsulacija
smanjenje redundantnosti koda
brzina kodiranja
portabilnost
Funkcije zauzimaju ključnu ulogu i u modernom objektno orijentisanom programiranju, jer je, praktično, kompletna
funkcionalnost klasa (koje su osnove objektno orijentisanog programiranja) smeštena baš u metode tih klasa. A
metode klasa su, što ukoro videti, ništa drugo do najobičnije funkcije. Ali, funkcije su veoma upotrebljiv alat i nevezano
za OOP (objektno orijentisano programiranje).
Veoma je čest slučaj da se pojavi potreba za učestalom upotrebom jednog istog bloka koda u jednom programu.
Ukoliko funkcije ne bi postojale, ovaj kod bismo, u najboljem slučaju, morali da kopiramo na svako mesto gde nam je
potreban.
Npr. u kodu, na više mesta ispisujemo jedan isti tekst. Recimo, zvezdice u narednom primeru:
69
<?php
echo "**********************************************";
echo "<br> naslov <br>";
echo "**********************************************";
echo "<br> Neki tekst <br>";
echo "**********************************************";
?>
Očigledno je da se deo koji iscrtava zvezdice ponavlja tri puta, a u programiranju postoji pravilo da sve što se ponavlja
ne treba da se ponavlja.
Sledivši to pravilo, dolazimo do zaključka da je neminovno rešiti problem ponavljanja zvezdica iz prethodnog koda, a
najefikasniji način da to uradimo jeste upotreba funkcije.
Tako bi verzija prethodnog koda sa upotrebom funkcije izgledala ovako:
<?php
//kreiranje funkcije zvezdice
function zvezdice()
{
echo "**********************************************";
}
//poziv funkcije zvezdice
zvezdice();
echo "< br > naslov < br >";
//poziv funkcije zvezdice
zvezdice();
echo "< br > Neki tekst < br >";
?>
U prethodnom kodu razlikujemo dve celine. Jedna je definisanje funkcije, a druga pozivanje funkcije.
Kada je u pitanju definicija funkcije, u PHP-u moraju biti ispoštovana neka pravila. Pre svega, funkcija mora biti
započeta ključnom rečju - function. Zatim, mora posedovati naziv, za koji, što se tiče notacije, važe ista pravila kao i
za promenljive (osim znaka $ ispred naziva). Nakon naziva, u malim zagradama, potrebno je naglasiti prijem
parametara (kroz listu promenljivih odvojenih zarezima) ili zagrade ostaviti prazne, ukoliko funkcija ne prima parametre.
I, konačno, samo telo funkcije, odnosno, kod koji funkcija izvršava i koji treba postaviti u vitičaste zagrade, odmah
nakon prijema parametara:
function mojaFunkcija($parametar1, $parametar2) { echo "ovo je telo"; }
Ovakav pristup ne samo da omogućava da se smanji veličina koda, već i dovodi do centralizacije koda, odnosno,
jednostavne manipulacije raznim mehanizmima koji se u kodu izvršavaju putem funkcija.
Recimo da primer sa zvezdicama još uvek nije prikazao pravu moć funkcija, i da je još uvek lakše kopirati jedan isti red
nekoliko puta. Ali, šta ako bismo želeli da naš izlaz sa zvezdicama ima dinamički sadržaj? Na primer:
*********************** Beograd *************************
Tekst o Beogradu
*********************** Pariz ****************************
Tekst o Parizu
*********************** London **************************
Tekst o Londonu
U ovom slučaju, morali bismo, osim kopiranja zvezdica, da u svakom redu ispisujemo i naziv grada i da brišemo i
dodajemo zvezdice na kraju reda, kako bi bile poravnate.
Kod bi izgledao ovako:
70
<?php
//poziv funkcije zvezdice
echo "************************************ Beograd **************************************";
echo "<br>Tekst o Beogradu<br>";
echo "************************************* Pariz ****************************************";
echo "<br>Tekst o Parizu<br>";
echo "************************************* London **************************************";
echo "<br>Tekst o Londonu<br>";
?>
U slučaju tri grada, koliko ih ima u primeru, postavlja se pitanje svrhe ovakve funkcije. Ali, već posle nekoliko novih
gradova, kod bi se umnogostručio kada ne bi bilo ove funkcije.
Osim toga, šta ukoliko bismo poželeli da u jednom trenutku smanjimo broj zvezdica kojima je oivičen naziv grada?
U ovoj funkciji, za to bi trebalo promeniti samo dve vrednosti, dok bi, bez funkcije, trebalo menjati kod onoliko puta
koliko ima gradova.
Tipovi funkcija
Ono što je još zanimljivo u prethodnom primeru jeste da u okviru funkcije zvezdice(), pozivamo još jednu funkciju
strlen(), koja vraća dužinu nekog stringa. U našem slučaju, to je naziv grada. Funkcija strlen() nije funkcija koju smo
ručno napisali, već je implementirana u PHP, kao njegov sastavni deo, iz čega zaključujemo da PHP ima dve vrste
funkcija, korisnički kreirane i unutrašnje (ugrađene) funkcije koje su deo PHP jezika.
Korisnički definisane funkcije su one koje sami kreiramo (poput funkcije zvetdice) i one se kreiraju korišćenjem ključne
reči function, kao u prethodnom i sledećem primeru:
71
function saberi( $num1, $num2 )
{
echo "Ovo je primer PHP funkcije. Ona sabira dva broja i vraća dobijeni zbir programu koji je poziva";
return $num1 + $num2;
}
Funkcija može biti napisana bilo gde u kodu, ali je ustaljena praksa da se sve funkcije pišu na početku koda, pre ostalih
naredbi. Takođe, funkcija može biti napisana i u posebnom fajlu. Tada je potrebno da se ovaj fajl uključi na svaku
stranu koja će da koristi njegove funkcije.
Funkcije mogu biti pozvane iz bilo kog dela PHP koda. Nakon poziva funkcije, funkcija preuzima prosleđene
parametre, ukoliko ih ima, izvršava određene naredbe i vraća dobijenu vrednost programu.
<?php
function saberi( $num1, $num2 )
{
return $num1 + $num2;
}
echo "Zbir brojeva 5 i 2 je " . saberi( 5, 2 );
?>
U gornjem primeru koda funkcija se prvo definiše, ali se poziva tek kasnije, u okviru echo naredbe. Prilikom poziva
funkcije prosleđuju joj se prave vrednosti parametara (5 i 2). Funkcija preuzima ove vrednosti, smešta ih u promenljive
$num1 i $num2, obavlja zadate operacije (sabira ih) i dobijenu vrednost vraća echo naredbi.
Moguće je napraviti i funkciju koja može, a ne mora da primi parametre, a da pri tom ne dođe do greške. U tu svrhu,
postavljaju se podrazumevane vrednosti parametara:
<?php
function saberi( $num1 = 3, $num2 = 4 )
{
return $num1 + $num2;
}
echo "Zbir brojeva je " . saberi();
?>
Promenljive koje se koriste unutar tela funkcije nazivaju se lokalne promenljive. Njima ne može da se pristupa izvan
funkcije. Ukoliko je, ipak, potrebno da se jednoj istoj promenljivoj pristupa i iz tela funkcije i izvan njega, ovu
promenljivu treba deklarisati kao globalnu, upotrebom ključne reči global. Globalne promenljive postoje i izvan funkcija
u kojima su definisane.
function format_name( $first_name ,$last_name )
{
global $name;
$name = $last_name.", ".$first_name;
}
format_name( "Nikola", "Nikolic" );
echo "$name";
Promenljiva $name je kreirana unutar funkcije, ali je upotrebom ključne reči global deklarisana kao globalna
promenljiva, što znači da će postojati i izvan funkcije. Prilikom poziva funkcije, promenljiva $name biva kreirana i
dodeljena joj je neka vrednost. Ovu vrednost je moguće koristiti kasnije u kodu (echo naredba).
Funkciji je moguće proslediti parametre bilo kog tipa. Prilikom definisanja funkcije unutar zagrada se navode parametri
koje funkcija koristi. Prilikom poziva funkcije, potrebno je proslediti joj konkretne vrednosti za parametre koje očekuje.
Ove vrednosti mogu biti: brojevi, tekst, promenljive, nizovi, pa čak i izrazi koji imaju neku vrednost. Pogledajte sledeću
funkciju:
72
function add_numbers( $numbers )
{
for( $i=0; $i < sizeof( $numbers ); $i++ )
{
@$sum = $sum + $numbers[ $i ];
}
return $sum;
}
Ova funkcija sabira brojeve koji su joj prosleđeni kao niz. Ukoliko se pri pozivu funkcije ne prosledi niz, doći će do
greške. Zbog toga je uvek dobro proveriti da li su prosleđene vrednosti odgovarajućeg tipa. Na primer:
function add_numbers( $numbers )
{
if( !is_array( $numbers )
{
echo "Nije prosleđen niz!";
exit();
}
for( $i=0; $i < sizeof( $numbers ); $i++ )
{
@$sum = $sum + $numbers[ $i ];
}
return $sum;
}
Svaka funkcija očekuje određeni broj parametara. Ukoliko je, pri pozivu, prosleđeno manje vrednosti nego što funkcija
zahteva, funkcija koristi vrednost NULL za one koji nedostaju. Ukoliko prosledite više vrednosti, funkcija ih ignoriše.
U PHP-u je moguće postaviti podrazumevane vrednosti za parametre koje će se koristiti ukoliko se ne proslede sve
vrednosti parametara prilikom poziva.
function add_2_numbers( $num1=1, $num2=1 )
{
$total = $num1 + $num2;
return $total;
}
Kada prosledite neku promenljivu funkciji, u stvari se prosleđuje njena vrednost. Bilo kakva izmena koju izvršite nad
prosleđenom promenljivom neće uticati na originalnu vrednost. Na primer:
function add_1( $num1 )
{
$num1 = $num1 + 1;
}
$orig_num = 3;
add_1( $orig_num );
echo $orig_num;
Prilikom poziva, funkciji add_1() se prosleđuje vrednost sadržana u promenljivoj $orig_num. Naredbe unutar funkcije
ne utiču na samu promenljivu, pa će naredba echo da ispiše broj 3, tj. prvobitnu vrednost promenljive $orig_num.
U nekim slučajevima će biti potrebno da funkcija promeni vrednost neke promenljive kreirane izvan funkcije. Tada se
umesto vrednosti promenljive prosleđuje njena referenca pomoću operatora & na sledeći način:
function add_1( &$num1 )
{
$num1 = $num1 + 1;
}
73
Prilikom poziva ovako definisane funkcije prosleđuje se referenca do promenljive (pokazivač) umesto vrednosti koja je
smeštena u njoj. Sada će promene unutar tela funkcije uticati na originalnu vrednost. Naredbe:
$orig_num = 3;
add_1( $orig_num );
echo $orig_num;
Anonimous funkcije
Ponekad funkciju treba definisati generički u samom kodu. U tom slučaju, funkcija neće imati ime, već će se samo
aktivirati kroz kod. Ovakve funkcije nazivaju se još i anonimous funkcije.
<?php
$mojaAnonimusFunkcija = create_function( '$a,$b', 'return $a + $b;' );
echo $mojaAnonimusFunkcija ( 2, 4 );
?>
parametri funkcije create_function() predstavljaju niz, prvi član niza predstavlja njene argumente dok je drugi član samo
telo funkcije. Funkcija create_function() je kada je komplikovanije telo funkcije vrlo usporeno, pa se iz tog razloga
izbegava njeno korišćenje zbog usporavanja rada web stranice.
Anonimus funkciju takođe možemo definisati i na sledeći način:
$f = function(){
echo "Hello";
}
$f();
Vežba 1
Problem:
Potrebno je napraviti funkciju koja prihvata string i vraća njegove karaktere u obrnutom redosledu (na primer string
“moj string” postaje “gnirts jom”).
Rešenje:
function str_reverse( $str )
{
$rez = "";
for( $i = strlen( $str ) - 1; $i >= 0; $i-- )
$rez.=$str[ $i ];
return $rez;
}
$text = "my string";
echo str_reverse( $text );
Napomena:
U primeru se radi sa nizovima, kako bi se ispunila njegova svrha. Nizovi će biti obrađeni u narednoj lakciji. Ukratko, oni
su sredstvo da se u jednu promenljivu smesti više vrednosti. Vrednostima se pristupa pomoću kombinacije uglastih
zagrada i pozicije vrednosti.
74
Vežba 2
Problem:
Postoji sledeći ulaz u aplikaciju:
define( "SQUARE", 0 );
define( "RECTANGLE", 1 );
define( "CIRCLE", 2 );
define( "PI", 3.14 );
Potrebno je napraviti funkciju koja će kao parametre prihvatati tip geometrijskog oblika (kvadrat, pravougaonik ili krug )
i vrednosti a i b. U zavisnosti od tipa geometrijskog oblika izračunava se njegova površina i vraća rezultat.
Potrebno je testirati funkciju.
Rešenje:
<?php
define( "SQUARE", 0 );
define( "RECTANGLE", 1 );
define( "CIRCLE", 2 );
define( "PI", 3.14 );
function area( $type, $a, $b = 0 )
{
$rez = 0;
switch( $type )
{
case SQUARE:
$rez = pow( $a, 2 );
break;
case RECTANGLE:
$rez = $a * $b;
break;
case CIRCLE:
$rez = pow( $a, 2 ) * PI;
break;
}
return $rez;
}
echo area( CIRCLE, 4 );
?>
Rad sa nizovima
Jedinica: 11 od 19
Rezime
Podrazumevani način indeksiranja u PHP-u ako se radi o numeričkom indeksiranju počinje od 0.
Niz može biti kreiran i korišćenjem funkcije array().
count(), sizeof() vraćaju dućinu niza.
sort(), asort(), rsort(), ksort(), krsort() funkcije se koriste za sortiranje nizova.
shuffle() funkcija se koristi se za proizvoljno raspoređivanje elemenata niza.
explode(), implode() Ove dve funkcije se koriste za konvertovanje stringa u niz i obrnuto.
array_diff( $niz1, $niz2, ... ) Ova funkcija identifikuje elemente u navedenim nizovima koji se razlikuju.
array_sum() Ova funkcija sabira vrednosti koje su elementi niza.
array_unique() Pomoću ove funkcije moguće je ukloniti iste elemente jednog niza.
array_merge($imeNiza1, $imeNiza2) Ova funkcija vam omogućava da dva niza spojite u jedan.
U PHP-u je moguće kreirati novi niz kao podskup nekog već postojećeg pomoću funkcije array_slice($imeNiza,
pozicija, dužina).
75
U ovoj lekciji naučićemo kako možemo raditi sa nizovima u PHP-u.
Na ovaj način je definisan niz $klijent koji ima tri elementa numerisana brojevima počevši od broja 1. Nizovi
indeksirani brojevima nazivaju se numerisani nizovi.
Elementi nizova mogu da budu indeksirani i pomoću stringova. Ovako indeksirani nizovi se nazivaju asocijativni nizovi.
Na primer:
$grad[ 'BG' ] = "Beograd";
$grad[ 'NS' ] = "Novi Sad";
$grad[ 'KG '] = "Kragujevac";
tada će biti kreiran niz od tri elementa, pri čemu su elementi numerisani automatski brojevima počevši od broja 0.
Indeksiranje brojevima počevši od 0 je podrazumevan način indeksiranja u PHP-u, ukoliko eksplicitno ne navedete
drugačije.
Niz može biti kreiran i korišćenjem funkcije array(), na jedan od sledećih načina:
$grad = array ( "Beograd", "Novi Sad", "Kragujevac" );
$grad = array ( 12 => "Beograd", "Novi Sad", "Kragujevac" );
$grad = array ( “BG” => "Beograd", "NS" => "Novi Sad","KG" => "Kragujevac" );
Prva naredba kreira niz od tri elementa indeksiranih brojevima 0, 1 i 2. Druga naredba kreira niz čiji su elementi
indeksirani brojevima 12, 13 i 14. Trećom naredbom se kreira niz i elementima se dodeljuju stringovi za indekse.
Svi do sada navedeni načini kreiranja nizova podrazumevaju da programer mora da navede vrednosti svakog
elementa niza. Ponekad je to potpuno nepraktično i nepotrebno. Na primer, ukoliko želimo da u jednom nizu čuvamo
brojeve od 1901 do 2000, dovoljno je da koristimo funkciju range() na sledeći način:
$dvadesetiVek = range( 1901, 2000 );
Ovom naredbom kreiran je niz od sto elemenata čije su vrednosti redom brojevi od 1901 do 2000. Ovi elementi su
indeksirani automatski indeksima od 0 do 99.
Kada je niz jednom kreiran, njegovim elementima se pristupa preko njihovih indeksa. Svaki element niza se koristi u
kodu kao i bilo koja druga promenljiva.
<html>
<head>
<title> Nizovi </title>
</head>
<body>
<p>
76
<?php
$boje = array( 'crvena', 'zelena', 'plava' );
echo "Prva boja u nizu je " . $boje[0] . "<br>";
echo "Druga boja u nizu je " . $boje[1] . "<br>";
echo "Treca boja u nizu je " . $boje[2] . "<br>";
?>
</p>
</body>
</html>
Promenljiva $boje[0] odgovara prvom elementu niza i ima vrednost 'crvena'. Izlaz prethodnog koda će biti
Prva boja u nizu je crvena
Druga boja u nizu je zelena
Treca boja u nizu je plava
Indeksi su automatski dodeljeni elementima niza prilikom njegovog kreiranja, pri čemu prvi element ima indeks 0.
Nekada je potrebno, nakon što je niz kreiran, ukloniti neki od njegovih elemenata. Ovo se postiže naredbom unset().
Na primer, unset($klijent[2]) će ukloniti drugi element iz niza kreiranog u prvom primeru. Niz klijent će se tada sastojati
samo od elemenata $klijent[1] i $klijent[3]. Obratite pažnju da se uklanjanjem jednog elementa niza ne menjaju indeksi
ostalih.
Elementi su sortirani po abecedi, pa su tako gradovi Kragujevac i Novi Sad zamenili mesta. Ukoliko koristite
naredbu sort() za asocijativne nizove, elementima se prvo dodele brojevi kao indeksi, niz se sortira, a zatim se
elementima ponovo vrate stari indeksi. Ovo praktično znači da naredba sort()menja raspored samo vrednostima
elemenata, a ne i indeksima.
Ukoliko želite da sortirate asocijativni niz, a da pri tome svaki element zadrži postojeći indeks, koristite
funkciju asort(). Funkcija rsort() uređuje niz u opadajućem redosledu. Funkcija ksort() uređuje niz prema indeksima u
rastućem, a funkcija krsort() u opadajućem redosledu.
77
shuffle()
Koristi se za proizvoljno raspoređivanje elemenata niza
Novi niz $subArray će sadržati dva elementa niza $testArray i to počevši od onog sa indeksom 1, tj.
[ 0 ] => green
[ 1 ] => blue
Prilikom korišćenja ove funkcije za spajanje dva asocijativna niza treba voditi računa o tome da u tim nizovima nema
elemenata sa istim indeksom. Ukoliko dva elementa imaju isti string indeks, drugi od njih će biti prekopiran preko
prvog.
U kodu koji sledi demonstrirana je upotreba gore navedenih funkcija.
<html>
<head>
<title> Nizovi </title>
</head>
<body>
<p>
<?php
//Kreiranje dva niza
$numbers = array( 50, 20, 18, 30, 10, 7 );
$colors = array( 'red', 'blue', 'green' )
// utvrđivanje veličine niza
$array_size = sizeof( $numbers );
// sortiranje elemenata – niz postaje array( 7, 10, 18, 20, 30, 50 )
sort( $numbers );
// spajanjem dva niza dobija se
array( 7, 10, 18, 20, 30, 50, 'red', 'blue', 'green' )
$merged_array = array_merge( $numbers, $colors );
// brojevi 18 i 20 se ubacuju u novi niz
$slice = array_slice( $numbers, 2, 2 );
78
?>
</p>
</body>
</html>
explode(), implode()
Ove dve funkcije se koriste za konvertovanje stringa u niz i obrnuto.
Funkcija explode() ima sledeću sintaksu
$imeNiza = explode( "znak", $string )
Prvi argument ove funkcije ( znak ) određuje karakter koji će biti korišćen za razdvajanje stringa. Drugi argument je
tekst koji se deli na delove. Svaki deo postaje jedan element niza.
Slično, moguće je elemente niza spojiti u string pomoću funkcije implode():
$tekst = implode( "znak", $imeNiza )
array_sum()
Ova funkcija sabira vrednosti koje su elementi niza
array_unique()
Pomoću ove funkcije moguće je ukloniti iste elemente jednog niza.
Vežba 1
Problem:
Definisan je sledeći niz:
$arr = array( 2, 5, 1, 7, 4, 3, 8 );
Potrebno je napraviti aplikaciju koja će sortirati ovaj niz tako da vrednosti budu poređane od manje ka većoj.
Potrebno je prikazati sortirani niz na izlazu.
Rešenje:
Ovo rešenje podrazumeva selection sort algoritam, ali je moguće upotrebiti i različite druge algoritme sortiranja.
<?php
$arr = array( 2, 5, 1, 7, 4, 3, 8 );
for( $i = 0; $i < sizeof( $arr ); $i++ )
{
$min = $i;
for( $u = $i; $u < sizeof( $arr ); $u++ )
{
if( $arr[ $u ] < $arr[ $min ] )
$min = $u;
}
$tmp = $arr[ $i ];
$arr[ $i ] = $arr[ $min ];
79
$arr[ $min ] = $tmp;
}
print_r( $arr );
?>
Sortirani niz na izlazu je:
Array ( [ 0 ] => 1 [ 1 ] => 2 [ 2 ] => 3 [ 3 ] => 4 [ 4 ] => 5 [ 5 ] => 7 [ 6 ] => 8 )
Vežba 2
Problem:
Dat je niz:
$arr = array( 0, 1, 2, 3, 4, 5, 6, 7, 8 );
Potrebno je napraviti kod koji će prikazati svakog člana niza pomnoženog sa prethodnim članom niza.
0
0
2
6
12
20
30
42
56
Rešenje:
<?php
$arr = array( 0, 1, 2, 3, 4, 5, 6, 7, 8 );
for( $i = 0; $i < sizeof( $arr ); $i++ )
{
if( $i > 0 )
echo $arr[ $i ] * $arr[ $i –1 ]."<br>";
else
echo $arr[ $i ]."<br>";
}
?>
Vežba 3
Problem:
Data je sledeća promenljiva:
$lipsum = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the
industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it
to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting,
remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem
Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of
Lorem Ipsum.";
Potrebno je napraviti program koji će prebrojati tačan broj svake reči u ovom stringu i emitovati rezultat na izlaz u
sledećem formatu:
80
Lorem : 4
Ipsum : 3
is : 1
simply : 1
dummy : 2
text : 2
of : 4
Rešenje:
<?php
$lipsum = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the
industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it
to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting,
remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem
Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of
Lorem Ipsum.";
$arr = explode(" ", $lipsum);
$words = array();
$counts = array();
for( $i = 0; $i < sizeof( $arr ); $i++ )
{
if( !in_array( $arr[ $i ], $words) )
{
$words[] = $arr[ $i ];
$counts[] = 1;
}
else
{
for( $u = 0; $u < sizeof( $words ); $u++ )
if( $words[ $u ] == $arr[ $i ])
$counts[ $u ]++;
}
}
for( $i = 0; $i < sizeof( $words ); $i++ )
echo( $words[ $i ] . " : " . $counts[ $i ] . "<br>");
?>
Vežba 4:
Problem:
Potrebno je napisati program koji će pristupati elementima niza pomoću foreach petlje i sistema key=>value za niz
mlečnih proizvoda (mleko, jogurt, pavlaka) i njihove cene redosledno u vrednosti od 89, 75,105.
Rešenje:
<?php
$cena[ 'mleko' ] = 89;
$cena[ 'jogurt' ] = 75;
$cena[ 'pavlaka' ] = 105;
foreach ($cena as $key => $value) {
echo $key . '=>' . $value . '<br/>';
}
?>
81
Nakon izvršenja programa na izlazu biće sledeći ispis:
mleko=>89
jogurt=>75
pavlaka=>105
... pri čemu vrednost sa leve strane znaka => predstavlja ključ, a vrednost sa desne strane predstavlja vrednost tog
ključa.
Dobijanje vrednosti određenog ključa u ovakvom nizu prilično je jednostavno:
<?php
echo $niz[ "srbija" ];
?>
Ova linija koda emitovaće vrednost za ključ »srbija« što je u ovom slučaju Beograd.
Za razliku od većine ostalih jezika, php neće prijaviti grešku prilikom unosa duplih ključeva, ali, treba znati da će PHP
vratiti samo poslednji iz niza duplih ključeva, pa treba obratiti pažnju da svi ključevi budu unikatni.
Višedimenzionalni niz
Osim jednodimenzionih nizova, koji su obrađeni u prethodnoj lekciji, php je u stanju da prepozna i takozvane
višedimenzionalne nizove. Ovakvi nizovi korisni su za rad sa podacima koji imaju matričnu ili tabelarnu formu.
Na primer, recimo da želimo da uskladištimo podatke u vidu tabele, tako da ta tabela sadrži sledeće kolone: ID, Ime,
Prezime, Matični broj.
U tom slučaju mogli bismo iskoristiti dvodimenzionalni niz.
82
<?php
//inicijalizacija niza
$niz = array();
//kao vrednost u člana niza, inicijalizujemo jos jedan niz
$niz[ 0 ] = array( 1, "jovan", "jovanovic", "1111111111111" );
$niz[ 1 ] = array( 2, "petar", "petrovic", "2222222222222" );
$niz[ 2 ] = array( 3, "stojan", "stojanovic", "3333333333333" );
//emitujemo sadržaj željenog člana niza
echo $niz[ 0 ][ 1 ];
?>
Dakle, ukoliko bi želeli da dobijemo iteraciju kroz sva imena ove tabele, napisali bismo kod:
<php
for( $i = 0; $i < sizeof( $niz ); $i++ )
echo $niz[ $i ][ 1 ]."<br>";
?>
Ova rešenja su praktična kada imamo fiksan broj članova podniza (u ovom slučaju to su kolone naše tabele), međutim,
ne i ukoliko želimo da rukujemo nekim dinamičkim podacima, čija količina nije unapred poznata. Na primer, program
koji rukuje slikama u kome korisnik može da učita sliku bilo kog formata. U tom slučaju, morali bismo da radimo sa
nizovima nepoznate veličine i morali bismo da upotrebimo nešto drugačiji metod za iteraciju kroz njegove članove.
Npr. matrica koja ima vrednosti:
1234
5678
9012
Ova matrica bi u formi niza izgledala ovako:
<?php
$niz = array(
array( 1, 2, 3, 4 ),
array( 5, 6, 7, 8 ),
array( 9, 0, 1, 2 ));
?>
... i lako bi bilo napraviti iteraciju kroz nju, izvedenu iz malopređašnjeg primera.
Ali, ukoliko zamislimo da smo, umesto ove poznate strukture, dobili samo jednu promenljivu $niz, čije podatke ne
znamo (osim da je dvodimenzionalni niz), morali bismo da pribegnemo drugoj tehnici.
83
//vrši se iteracija nad spoljašnjim nizom
for( $sp = 0; $sp < sizeof( $niz ); $sp++ )
{
//za svakog člana spoljašnjeg niza, vrši se iteracija elemente njegovog podniza
for( $up = 0; $up < sizeof( $niz[ $sp ]); $up++ )
//ispisuje se vrednost trenutne koordinate u nizu
echo $niz[ $sp ][ $up ];
//ispis novog reda, nakon svake iteracije spoljnog niza
echo "<br>";
}
Ali, ni ovo nije dovoljno da bi se sačuvali podaci o nekoj slici, jer slika na svakoj koordinati poseduje određeni set
podataka (o boji). S obzirom na to da se boja najčešće sastoji od tri vrednosti (ukoliko se radi o RGB modelu), za
svaku tačku moraćemo da odvojimo još jedan niz od tri člana.
Postoje, naravno, i druge, mnogo efikasnije metode da se rukuje ovakvom vrstom podataka (npr. objekti).
Da bismo ispunili pomenuti zahtev, potrebno je malo izmeniti dosadašnji kod. Pre svega, recimo da niz koji smo dobili
parsiranjem neke slike izgleda ovako:
$niz = array(
array(
array(0,0,0), array(255,255,255), array(0,0,0), array(255,255,255)),
array(array(255,255,255), array(0,0,0), array(255,255,255), array(0,0,0)), array(array(0,0,0), array(255,255,255),
array(0,0,0), array(255,255,255)));
... tako da je svaki podniz glavnog niza jedan red, a svaki podniz u jednom redu, jedna tačka.
Za iteraciju kroz ovako serijalizovane podatke, mogli bismo iskoristiti sledeći kod:
//prolaz kroz spoljasnji niz
for( $sp = 0; $sp < sizeof( $niz ); $sp++ )
{
//prolaz kroz unutrasnji niz
for( $up = 0; $up < sizeof( $niz[ $sp ]); $up++ )
//prolaz kroz clanove unutrasnjeg niza
for( $up1 = 0; $up1 < sizeof( $niz[ $sp ][ $up ]); $up1++ )
echo $niz[ $sp ][ $up ][ $up1 ] . " ";
echo "<br>";
}
Jedna od olakšica koju je moguće koristiti prilikom rada sa višedimenzionalnim nizovima je foreach petlja. Ova petlja
sama vodi računa o veličini i pozicijama članova niza prilikom iteracije, pa je tako dobra za neke jednostavnije
operacije. Sa druge strane, ovakav pristup smanjuje kontrolu nad samim članovima niza. Foreach petlja će biti
detaljnije opisana u jednoj od narednih lekcija.
Ovako bi izgledalo kretanje kroz melopređašnji niz, korišćenjem foreach petlje:
84
<?php
$niz = array(
array(array(0,0,0),array(255,255,255),array(0,0,0),array(255,255,255)),
array(array(255,255,255),array(0,0,0),array(255,255,255),array(0,0,0)),
array(array(0,0,0),array(255,255,255),array(0,0,0),array(255,255,255))
);
foreach($niz as $red)
{
foreach($red as $tacka)
{
foreach($tacka as $boja)
echo $boja;
}
echo "<br>";
}
?>
Napredne funkcije nad nizovima
Za prikaz članova niza, bez kretanja kroz pojedinačne članove (kako je rađeno u prethodnim primerima) moguće je
koristiti funkciju print_r. Ova funkcija razlaže niz, prikazujući njegove ključeve ili brojeve indeksa i vrednosti koje se
nalaze ispod njih.
Na primer:
<?php
$niz = array( "srbija" => "beograd", "francuska" => "pariz", "engleska" => "london", "usa" => "vasington" );
print_r( $niz );
?>
imaće sledeći rezultat:
Array ([ srbija ] => beograd [ francuska ] => pariz [ engleska ] => london [ usa ] => vasington)
Array_walk()
Ova funkcija vrši kretanje kroz niz i izvršavanje određene funkcije na svakom članu tog niza. Na primer:
<?php
$niz = array( "srbija" => "beograd", "francuska" => "pariz", "engleska" => "london", "usa" => "vasington" );
array_walk( $niz, "printf" );
?>
Funkcija će proći kroz niz i startovati funkciju printf nad svakim članom niza.
Umesto printf, moguće je kao parametar priložiti i bilo koju drugu funkciju. Recimo, funkciju koja proverava vrednost i,
ukoliko ta vrednost ispunjava neke uslove, smešta je u drugi niz.
Array_fill()
Ukoliko želimo da formiramo niz ispunjen nekom statičkom vrednošću, možemo upotrebiti ovu funkciju, pri čemu je prvi
parametar - početni indeks niza, drugi parametar - broj ubačenih članova, a poslednji parametar - vrednost koja se
ubacuje.
<?php
$x = array_fill( 0, 10, "pozdrav" );
print_r( $x );
?>
85
Ovaj kod vraća:
Array ( [0] => pozdrav [1] => pozdrav [2] => pozdrav [3] => pozdrav [4] => pozdrav [5] => pozdrav [6] => pozdrav
[7] => pozdrav [8] => pozdrav [9] => pozdrav )
Na ovaj način moguće je jednostavno kopirati više nizova u drugi niz, odnosno, napraviti višedimenzionalni niz, s
obzirom na to da ova funkcija kao parametar može primiti i sam niz.
Array_flip()
Menja položaje ključeva i vrednosti. Ukoliko je niz sastavljen od ključeva i vrednosti, napraviće zamenu ključeva i
vrednosti, a ukoliko niz nema ključeve, već samo indekse, zameniće indekse članova za vrednosti članova.
Kod:
<?php
$niz = array( "srbija" => "beograd", "francuska" => "pariz", "engleska" => "london", "usa" => "vasington");
$x = array_flip( $niz );
print_r( $x );
?>
emituje:
Array ( [beograd] => srbija [pariz] => francuska [london] => engleska [vasington] => usa )
Array_pop()
Da bismo razumeli ovu i sledeću funkciju nad nizovima, potrebno je prvo da razumemo dva načina za pristup bilo
kakvim kolekcijama podataka u programiranju – FIFO i LIFO. FIFO, što je skraćenica za First In First Out (prvi unutra
prvi napolje) podrazumeva da je element, koji je prvi pristupio kolekciji, prvi i napušta kolekciju podataka. Dok LIFO,
Last In First Out (poslednji unutra prvi napolje), podrazumeva da element koji je poslednji pristupio kolekciji, prvi
napusti kolekciju.
Često se ova dva pristupa porede i sa radnim stolom i redom u pošti.
Radni sto (LIFO):
Ukoliko stavimo gomilu papira na sto, onaj koji smo stavili poslednji, biće na vrhu gomile i prvog ćemo ga uzeti.
Red u pošti (FIFO):
Onaj ko je poslednji stao u red, poslednji će doći do šaltera.
Identično je i u programiranju: stack (sto) i queue (pošta). Obično se (generalno u programiranju) za ova dva tipa
punjenja kolekcije podataka, vezuju i dve funkcije. Za stack to su pop i push, a za queue, dequeue i enqueue.
Array_pop() će dakle, izvući i obrisati poslednji element iz niza. Ali i postaviti marker na prethodnu poziciju.
Dakle, sledeći kod će emitovati vasington kao rezultat:
<?php
$niz = array( "beograd", "pariz", "london", "vasington" );
echo array_pop( $niz );
?>
ali će sledeći kod emitovati: vasingtonlondonparizbeograd
<?php
$niz = array( "beograd", "pariz", "london", "vasington" );
echo array_pop( $niz );
echo array_pop( $niz );
echo array_pop( $niz );
echo array_pop( $niz );
?>
86
Da bi po istom principu dodali element u niz, koristimo funkciju:
Array_push()
<?php
$niz = array("beograd", "pariz", "london");
array_push( $niz, "vasington" );
print_r( $niz );
?>
Rezultat je:
Array ( [0] => beograd [1] => pariz [2] => london [3] => vasington )
Ova funkcija daje rezultat identičan onome koji bismo dobili kada bi vrednost uneli direktno, naredbom:
$niz[] = "vasington";
Ali, korišćenje array_push() funkcije daje nešto brži rezultat, zbog čega je bolja pri radu sa većim količinama podataka.
list()
Dodeljuje vrednosti niza prosleđenoj listi varijabli.
<?php
$gradovi = array("beograd", "pariz", "london");
list($srbija, $francuska, $engleska) = $gradovi;
echo $francuska;
?>
Ovakav pristup dobar je za malu količinu, statičkih podataka.
Rezultat koda će biti:
pariz
Vežba 1
Problem:
Dat je sledeći niz:
$table = array("format" => array(7, 7),"positions" => array(array(3, 5),array(1, 4),array(4, 6),array(3, 7)));
Potrebno je uz pomoć petlji proći kroz odgovarajuće nizove, tako da se kreira tabela dimenzija navedenih u podnizu
format, niza table.
Potrebno je nacrtati tabelu, tako da sva prazna polja budu prikazana oznakom 0, a sva polja koja se nalaze u podnizu
positions niza table, budu prikazana oznakom X. Za zadati niz, izlaz treba da izgleda ovako:
0000000
0000000
0000000
0000000
0X00000
000X000
0000X00
87
Rešenje:
for( $y = 0; $y < $table[ "format" ][ 0 ]; $y++ )
{
for( $x = 0; $x < $table[ "format" ][ 1 ]; $x++ )
{
$pointExists = false;
for($p = 0; $p < sizeof( $table[ "positions" ]); $p++ )
{
if( $table[ "positions" ][ $p ][ 0 ] == $x && $table[ "positions" ][ $p ][ 1 ] == $y)
$pointExists = true;
}
if( $pointExists )
echo "X";
else
echo "0";
}
echo "<br>";
}
Vežba 2
Problem:
Dat je sledeći niz:
$population = array("London" => 7556900,"Belgrade" => 1500000,"New York" => 19541453, "Paris" => 11836970);
Potrebno je napraviti program koji će na osnovu podataka o broju stanovnika formirati primitivni grafikon i u njemu
prikazati broj stanovnika u skali od 1 do 10 prema postotcima. Postotke formirati tako da grad sa najvećim brojem
stanovnika bude 100%.
U grafikonu treba delove koji su obuhvaćeni skalom prikazati oznakom #, dok delove koji ne pokrivaju vrednost ne
treba prikazati (ove oznake su proizvoljne).
Na dnu liste treba vertikalno prikazati nazive gradova.
Konačan izgled primera:
#
#
# #
# #
# #
# # #
# # #
# # #
# # # #
# # # #
L B N P
o e e a
n l w r
d g i
o r Y s
n a o
d r
e k
88
Rešenje:
<?php
$population = array("London" => 7556900, "Belgrade" => 1500000, "New York" => 19541453, "Paris" => 11836970);
$max = 0;
$longestCityName = 0;
foreach($population as $k => $v)
{
if($v > $max)
$max = $v;
if(strlen( $k ) > $longestCityName)
$longestCityName = strlen( $k );
}
$percent = 100 / $max;
for($i = 10; $i >= 0; $i--)
{
foreach($population as $k => $v)
{
$currentPercent = ceil(($percent * $v)/10);
if($currentPercent >= $i)
echo "#" . " ";
else
echo "<span style='color:white;'>#</span>" . " ";
}
echo "<br>";
}
for($i = 0; $i < $longestCityName; $i++)
{
foreach($population as $k => $v)
{
if(strlen( $k ) > $i)
{
$cityArr = str_split( $k );
echo $cityArr[ $i ] . " ";
}
else
echo " ";
}
echo "<br>";
}
?>
Obrada stringova
Jedinica: 13 od 19
Rezime
print( ) i echo() su najjednostavnije funkcije za ispis teksta
printf() koja prikazuje statički tekst i dinamičke
Funkcija sprintf() tekst smešta u novu promenljivu
trim( ) – uklanja prazna mesta na početku i na kraju stringa
ltrim( ) – uklanja prazna mesta na početku stringa
dtrim( ) – uklanja prazna mesta na kraju stringa
str_word_count( ) – razbija tekst na reči i smešta ih u niz
strpbrk(string, char) – traži karakter char u tekstu string
strtoupper(string) – prebacuje sva slova u velika
strtolower(string) – prebacuje sva slova u mala
89
U ovoj lekciji radićemo stringove. Najjednostavnije funkcije za ispis teksta su print i echo. Njihova primena je gotovo
identična, s tim što je echo za nijansu brža pri izvršavanju. Što se tiče sintakse, svejedno je da li ćete pisati
print " Dobar dan ";
ili
echo " Dobar dan ";
Kada je potrebno nešto komplikovanije ispisivanje tekta koristi se funkcija printf() koja prikazuje statički tekst i
dinamičke informacije i njena primena izgleda ovako:
printf("Danas je prodato $d artikala. ", 100 );
nakon izvršavanja funkcije biće ispisan sledeći tekst:
Danas je prodato 100 artikala.
Specijalni karakateri će biti interpretirani na ovaj način samo ukoliko koristite dvostruke navodnike. Ukoliko se koriste
sa jednostrukim navodnicima, biće prikazani bukvalno, kao niske karaktera.
Slična je situacija i sa prikazom promenljivih. Na primer:
$ime = "Marko";
$output1 = "$ime";
$output2 = '$ime';
echo $output1;
echo $output2;
Ponekad je potrebno da se karakteri unutar stringa tretiraju kao obični karakteri. Na primer, ukoliko želite da ispišete
poruku:
Cena proizvoda je $100.00.
90
Na ovaj način dajete instrukciju PHP-u da znak za dolar u ovom tekstu ne označava ime promenljive, već da samo
treba da ga prikaže.
Primer:
Funkcija str_word_count( ) se može koristiti na više načina. Takođe koristi se zajedno sa funkcijom za ispis print_r()
koja vrši ispis nizova, ali tako da podaci budu čitljivi korisniku. Pogledajmo sledeće primere upotrebe:
<?php
echo str_word_count("Dobar dan!");
?>
Nakon izvršenja, funkcija vraća rezultat:
2
Što predstavlja broj reči u stringu.
Primer u kome se kao drugi argument uključuje i broj:
<?php
print_r(str_word_count("Dobar dan!",1));
?>
Primer:
91
Sada ćemo prikazati upotrebu funkcija za rad sa stringovima u slučaju pretvaranja u velika ili u mala slova. Pogledajmo
primer koda:
<?php
$str = " Dobar Dan Php Programeri ! ! ! ";
echo "Bez upotrebe funkcija : " . $str;
echo "<br />";
echo "Sa upotrebom funkcije za velika slova : " . strtoupper( $str ) ;
echo "<br />";
echo "Sa upotrebom funkcije za mala slova :" . strtolower( $str );
?>
Upotrebom funkcija strtoupper( string ) i strtolower( string ) nad string promenljivom
" Dobar Dan Php Programeri ! ! ! ". Nakon izvršenja programa na izlazu dobijamo sledeći ispis:
Bez upotrebe funkcija : Dobar Dan Php Programeri !
Sa upotrebom funkcije za velika slova : DOBAR DAN PHP PROGRAMERI !
Sa upotrebom funkcije za mala slova : dobar dan php programeri !
I jedna i druga funkcija formatiraju tekst na osnovu argumenta format, s tom razlikom što ga funkcija printf() samo
prikazuje, a funkcija sprintf() ga smešta u novu promenljivu. Prvi argument ovih funkcija, "format", predstavlja
instrukcije za formatiranje. Svaka instrukcija za formatiranje ima sledeći oblik:
%pad - duzina.dectip
ispisaće poruku:
3 decaka i 2 devojcice
Primer 2.
$cena = 30000;
$proizvod = "Samsung TV";
$poruka1 = sprintf("%s kosta %06.2f dinara.\n", $proizvod, $cena);
92
$poruka2 = sprintf("%'.-20s%6.2f", $proizvod, $cena);
echo $poruka1;
echo $poruka2;
ispisaće poruku:
Samsung TV košta 030000.00 dinara.
SamsungTV........... 30000.00
U prvoj poruci prva instrukcija za formatiranje je %s i ona se odnosi na prvu promenljivu, $proizvod. Ova instrukcija će
samo da ispiše vrednost promenljive. Druga instrukcija za formatiranje je %06.2f i odnosi se na drugu
promenljivu, $cena. Ona govori da broj treba da bude predstavljen sa 6 karaktera i dva decimalna mesta, pri čemu je 0
karakter sa kojim se popunjavaju prazna mesta.
U drugoj poruci prva instrukcija za formatiranje naziva proizvoda je %'.-20s. Ona govori da promenljivu $proizvod treba
prikazati poravnato u levo, sa dvadeset karaktera, pri čemu se prazna mesta popunjavaju tačkom. Cena se prikazuje
na sličan način kao i u prvoj poruci, s tom razlikom što nije naveden karakter koji popunjava prazna mesta, pa se koristi
podrazumevani space karakter.
Kada želite da stringove preklapate jedne drugima, koristi se funkcija substr_replace() koja ima osnovni oblik:
substr_replace(Promenljiva, „ karakteri kojima se menja string ”, broj početnog karaktera, broj poslednjeg karaktera)
Argumenti broj početnog i broj poslednjeg karaktera predstavljaju numeričke vrednosti koje čine opseg od početnog do
krajnjeg karaktera koji se menja.
Primer upotrebe:
<?php
$brojevi = "123456789123456789";
echo substr_replace($brojevi, "#########",0,8);
?>
Nakon izvršenja biće ispisano:
#########123456789
Vežba 1
Problem:
U aplikaciju ulaze sledeće promenljive:
$userName i $password
Potrebno je proveriti validnost ovih promenljivih, i obezbediti da ne budu prazne, kao i da ne sadrže sledeće karaktere:
<> i ‘
U slučaju da je neka od promenljivih prazna, izvršenje se prekida, dok u slučaju postojanja neželjenih karaktera, dolazi
do izbacivanja tih karaktera iz vrednosti promenljive.
Inicijalne vrednosti promenljivih treba da budu:
$userName = "myName<";
$password = "myPa>sswo'rd";
93
Rešenje:
<?php
function clean_string($string)
{
$string = str_replace("<", "", $string);
$string = str_replace(">", "", $string);
$string = str_replace("'", "", $string);
return $string;
}
$userName = "myName<";
$password = "myPa>sswo'rd";
$userName = clean_string(trim($userName));
$password = clean_string(trim($password));
if(trim($userName) == "" || trim($password) == "")
die("invalid credentials");
echo "valid credentials";
?>
Ispis na izlazu:
valid credentials
Vežba 2
Potrebno je formatirati tekst tako da se formira novi red nakon svakog 15. karaktera:
Rešenje 1:
Ovo rešenje funkcioniše samo kod kontrola koje imaju mogućnost prepoznavanja novog reda u tekstu):
<?php
$lipsum = "Lorem Ipsum is simply dummy text of the printing and typesetting industry.";
echo wordwrap($lipsum, 15);
?>
Rešenje 2:
<?php
$lipsum = "Lorem Ipsum is simply dummy text of the printing and typesetting industry.";
$lipsumArr = explode(" ", $lipsum);
$tmpContent = "";
for( $i = 0; $i < sizeof( $lipsumArr ); $i++ )
{
if((strlen($tmpContent . " ") + strlen($lipsumArr[$i])) < 15)
$tmpContent .= " " . $lipsumArr[$i];
else
{
if($tmpContent != "")
{
echo $tmpContent . "<br>";
}
94
$tmpContent = $lipsumArr[$i];
}
}
echo $tmpContent;
?>
Vežba 3
Problem:
Dat je sledeći string:
$lipsum = "Lorem Ipsum is simply dummy text of the printing and typesetting industry.";
Potrebno je formatirati string, tako da, ukoliko ima više od 15 karaktera, bude isečen, tako da poslednja tri karaktera do
15. karaktera budu tačke. Na primer:
Lorem Ipsum ...
Rešenje:
<?php
$lipsum = "Lorem Ipsum is simply dummy text of the printing and typesetting industry.";
$izlaz = (strlen( $lipsum ) > 15) ?substr( $lipsum, 0, 12 )."...": $lipsum;
echo $izlaz;
?>
Vežba 4
Problem:
Potrebno je napisati program koji će za navedeni string vraćati broj reči koji se nalazi u njemu, string promenljiva ima
sadržaj:
" Ovo je primer koji broji reci u okviru naseg stringa!"
Rešenje:
<?php
echo str_word_count(" Ovo je primer koji broji reci u okviru naseg stringa ! ");
?>
Rešenje nakon izvršenja programa je 10!
odnosno:
echo "moja promenljiva $x";
Rezultat će, u oba slučaja biti: moja promenljiva 2 (dva je u primeru proizvoljan broj. Biće, naravno, emitovana vrednost
promenljive $x). PHP prilikom ovog postupka nije svemoćan. I treba paziti da promenljive, koje želimo da tretiramo kao
promenljive, ne izgube kontekst.
Pogledajmo sledeći primer:
echo "$a bcd";
Promenljiva $a će biti regularno emitovana, jer je razdvojena od ostatka sadržaja stringa. Ali u slučaju da linija izgleda
ovako:
echo "$abcd";
Neće biti emitovana ni promenljiva $a, ni ostatak teksta, jer će interpreter tražiti promenljivu pod nazivom $abcd.
Ukoliko želite da implementirate string tako da promenljiva i ostatak stringa budu spojeni, možete upotrebiti vitičaste
zagrade kao separatore:
echo "{$a}bcd";
emitovaće:
96
'moj' tekst
Ali će zato:
echo ""moj" tekst";
prijaviti grešku.
Naravno, uvek možete staviti navodnik iza escape karaktera i tako ga emitovati: \"
Vratimo se sada na interpolaciju promenljivih. Tu, takođe postoji razlika kada su tipovi navodnika u pitanju. Videli smo
da dvostruki navodnici dozvoljavaju parsiranje promenljive. Sa druge strane, jednostruki navodnici ne parsiraju ni
promenljive, kao ni specijalne karaktere, pa će sve što u njih stavite biti tako i emitovano:
echo '$a bcd';
emituje:
$a bcd
echo '\n'; emituje \n...
Herodoc sintaksa
Iako specijalni karakteri i html oznake omogućavaju veliku slobodu prilikom emitovanja teksta (možete napraviti formu
kakvu god želite), ovo često i nije najjednostavniji način da se tekst formatira. Naročito ako želite da kopirate neku već
gotovu tekstualnu formu. U ovom slučaju, mnogo je praktičnije upotrebiti herodoc string. Uz pomoć ove sintakse,
možete formatirati čak i najkompleksnije stringove. Upotrebljava se na sledeći način:
Početak stringa obeležava se se oznakom <<< kojoj sledi identifikator, što može biti bilo koji naziv koji ne odstupa od
standardnih pravila za imenovanje promenljivih. Obično se, zbog preglednosti, identifikator piše velikim slovima. Nakon
identifikatora obavezan je novi red, odakle može početi i sam tekst.
Kraj teksta se označava takođe identifikatorom, kome mora prethoditi novi red, a sledi oznaka ;
<<<MOJTEKST
Naslov<br>
Sadrzaj...
MOJTEKST;
Ovako formatiran sadržaj možete smestiti u promenljivu ili poslati direktno na izlaz:
$a=<<<MOJTEKST
Naslov<br>
Sadrzaj...
MOJTEKST;
echo<<<MOJTEKST
Naslov<br>
Sadrzaj...
MOJTEKST;
Herodoc stringovi su veoma moćni alati. Pokušajte da otvorite izvorni kod neke web strane i da ga kopirate u svoj
herodoc string. Videćete da će kompletan kod biti obrađen bez problema ili grešaka.
S obzirom na to da omogućava pamćenje velike količine teksta, nemojte zaboraviti da postoji memorijski limit koji je
PHP-u dozvoljen da koristi za skriptiranje. U slučaju da preterate sa količinom, PHP jednostavno neće biti u stanju da
obradi Vaš string i doći će do greške.
97
Dužina stringa
Jedna od najčešće korišćenih funkcija nad stringovima je funkcija kojom se određuje dužina stringa. Ova funkcija se
zove strlen.
Da bismo upotrebili ovu funkciju (koja je inače vrlo jednostavna), pogledaćemo prvo od čega se uopšte sastoji string.
Npr, tekst: moj string, sastoji se od karaktera. A svaki od tih karaktera je, zapravo, jedan bajt. To znači da je naš string,
u stvari, ništa drugo nego jedan niz bajtova. Da li to znači da bismo, kada bismo se obratili nekom stringu kroz njegov
niz, dobili kao članove tog niza karaktere našeg stringa? Da.
Na primer:
$a = "moj tekst";
echo $a[2];
posle sledećeg koda, na ekranu će biti ispisan karakter j, što je drugi (ako se koristi zero based indeksiranje) karakter u
našem stringu.
S obzirom na to da smo ustanovili da je string jedan niz karaktera, funkciju strlen možemo tretirati kao funkciju
koja broji članove tog niza.
echo strlen("moj string");
Ono što je važno da znate prilikom korišćenja ove funkcije jeste da, za razliku od nekih drugih jezika, ona nema zero
terminated mehanizam i kada naiđe na prazan karakter ona ne prekida automatski brojanje, nego nastavlja, sve dok
postoje bilo kakve vrednosti za karaktere u promenljivoj koju broji.
To u praksi znači da će ovaj primer:
$a=" ";
echo strlen($a);
koji bi u nekom drugom jeziku (sa drugom funkcijom) dao rezultat 0, ovde dati rezultat 5, jer se string sastoji od pet
praznih karaktera.
Evo primera kako da se rešimo spejsova u nekom tekstu:
$s = "moj tekst";
for ($i = 0; $i < strlen ($s); $i++) {
if($s[$i] != " ")
echo $s[$i];
}
Poređenje stringova
Osnovni način za poređenje stringova je uz pomoć operatora poređenja.
echo "moj string"=="moj string";
Ovaj način je dobar, ukoliko rukujemo sa hard kodiranim vrednostima. Ali, pogledajte sada sledeći primer:
echo "1moj string"==1;
Ovaj primer, kao i malopređašnji, daje tačan rezultat. Iako naizgled, dve poređene strane nemaju nikakve bliskosti.
PHP je prvo pregledao operande i video da se radi o poređenju stringa sa int-om, što je nemoguće. Zato je implicitno
konvertovao levi operand u int, što je vrednost levog operanda svelo na 1 (jedini broj koji postoji u stringu), što je
konačno dovelo do poređenja 1 i 1, koje, naravno, daje tačan rezultat. Možda, na prvi pogled, ne deluje kao da bi do
ovakve greške moglo doći, ali, ne zaboravite da u programima na ovakva poređenja obično dolaze dinamički kreirane
vrednosti (na primer $a==$b).
98
Poređenje stringova možete izvršiti i na drugi način. Funkcijama strcmp i strcasecmp. Ove funkcije, kao parametre,
primaju dva stringa koja se porede, a kao rezultat vraćaju nulu, ako su stringovi identični ili broj različitih karaktera.
echo strcmp("moj string","moj string");
Primer emituje vrednost 0.
Razlika između strcmp i strcasecmp je u tome što funkcija strcasecmp nije osetljiva na velika i mala slova.
echo strcmp("Moj string", "moj string"); // rezultat je 1
echo strcasecmp("Moj string", "moj string"); // rezultat je 0
Pretraga stringa
Postoji mogućnost traženja određenog karaktera ili sekvence karaktera unutar samog stringa. Za ovo se koristi
funkcija strpos.
Ova funkcija prihvata, kao parametre, inicijalni string i sekvencu koju tražimo, a kao rezultat vraća početnu poziciju
(indeks) tražene sekvence. Odnosno, ne vraća ništa, ukoliko tražena sekvenca ne postoji.
echo strpos("moj string", "str");
U primeru se ne uzimaju u obzir pojave traženog karaktera pre petog karaktera stringa. Znači da prvo pojavljivanje
neće biti uzeto u obzir. Rezultat funkcije će biti deset, jer se prvo sledeće pojavljivanje događa na desetom karakteru
stringa.
Izmena stringa
U PHP-u je moguće jedan deo stringa zameniti drugim. Ovako nešto možete uvek uraditi uz pomoć do sada pomenutih
funkcija, ali i korišćenjem funkcija posebno pisanih za tu namenu: str_replace i str_ireplace (ista funkcija neosetljiva na
velika i mala slova):
echo str_replace("moj", "tvoj", "moj tekst");
funkcija str_replace prihvata tri (ili četiri) parametra. Prvi parametar je traženi deo stringa, drugi je deo koji će biti
ubačen umesto traženog stringa, a treći je string na kome se vrši intervencija. Četvrti, opcioni parametar omogućava
da se u neku promenljivu smesti broj pronađenih slučajeva traženog stringa.
$a=0;
echo str_replace("moj", "tvoj", "moj tekst", $a);
echo $a;
Ovaj primer daće vrednost jedan, pošto se reč moj pojavljuje samo jednom u stringu.
Na ovaj način, možete zameniti i više slučajeva u jednom stringu, uz pomoć nizova:
$cilj = array("ja ucim", "ti ucis", "on uci");
$zamena = array("mi ucimo","vi ucite","oni uce");
echo str_replace($cilj, $zamena, "ja ucim php",$a);
Ovaj primer promeniće tekst u: "mi ucimo php".
Nekada ćete želeti da izmenite string na određenoj poziciji (indeksu). Na primer, ako ste gradili neku listu na osnovu
nekih podataka koje ste dobijali sekvencijalno. Lako se može desiti da ti podaci završe u sledećem obliku:
1,2,3,4,5,
jer, s obzirom da listu kreirate dinamički, ne znate koji je njen poslednji član, pa ostanete sa jednim zarezom (ili nekim
drugim separatorom) viška. U tom slučaju, substr_replace funkcija je odlično rešenje:
99
$x = "1,2,3,4,5,";
echo substr_replace($x, "", strlen($x)-1);
Funkcija kao parametre prihvata string, string koji ćete umetnuti kao zamenu i poziciju odakle će početi zamena. S
obzirom na da dužinu stringa ne znamo (lista može biti od 1-5 ali može biti i 1-1000), za poziciju uzimamo dužinu
umanjenu za jedan (znači, poslednji element).
Primer će emitovati tekst nakon sedmog karaktera. Rezultat je www.google.com. Kada se ne unese treći parametar,
preuzima se kompletan string, od početne pozicije. Ukoliko se unese treći parametar, preuzima se onoliko karaktera
koliko je naznačeno u trećem parametru:
$x = "http://www.google.com";
echo substr($x,7,3);
Formatiranje stringa
Formatiranje stringova smo već pomenuli kroz funkciju number_format. Ova funkcija omogućava raznovrsnost
prilikom ispisa brojeva (pre svega decimalne notacije):
echo number_format(30.4000,3);
Prvi parametar ove funkcije je sam broj. Drugi parametar je maksimalan broj prikazanih decimala. Izlaz ovog koda je:
30.400.
Ova funkcija može prihvatiti i dva opciona parametra (isključivo oba parametra), koja predstavljaju karakter, koji će
odvajati decimale broja i karakter koji će odvajati hiljade.
echo number_format(30000,3,".",",");
Izlaz je:
30,000.000
Neke formate možete deklarisati i putem identifikacije lokalizacije, funkcijom setlocale. Za to Vam je potreban naziv
grupe za formatiranje i naziv lokalizacije. Sledeći primer formatiraće sve zapise grupe LC_MONETARY, po lokalizaciji
en_US:
setlocale(LC_MONETARY, "en_US"); ili setlocale(LC_MONETARY, "ja_JP");
Generičko formatiranje
Sa ovim načinom formatiranja već smo upoznati kroz prethodne lekcije. Funkcije su printf, sprintf i fprintf (razlike ove tri
funkcije su isključivo u tipu izlaza: prva ima standardan izlaz – strana ili konzola – sprintf ima može vratiti rezultat, a
fprintf ima izlaz u fajl).
Sintaksa formatiranja je sledeća:
printf("Moj broj: %d", 100);
100
Prvi parametar ove funkcije (string »moj broj: %d) je ono što će otići na izlaz, dok je drugi (pa i svi ostali) parametar
vrednost koja će zameniti identifikator u stringu (%d). U ovom slučaju, identifikator je d, što znači da će na izlazu biti
decimalna vrednost, ali mogli smo upotrebiti i neke druge identifikatore. Na primer: %b, bi dao binarni izlaz:
printf("Moj broj: %b", 10);
Prilikom formatiranja stringa na ovaj način niste ograničeni samo na jedan identifikator.
printf("Moj decimalni broj: %d, moj binarni broj: %b, moj broj sa pokretnim zarezom: %f", 10,10,10);
Regularni izrazi
Kada, jednostavno, nemate uslova da rešite neku operaciju na stringu standardnim putem (kod je, na primer,
prekompleksan) onda se možete poslužiti i regularnim izrazima.
Regularni izrazi su setovi pravila po kojima se neki string pretražuje.
Na primer, ako bismo želeli da budemo sigurni da je neki string zapisan u formi e-maila, mogli bismo da kažemo da za
njega postoji nekoliko pravila:
Mora imati neki tekst na početku, bez specijalnih karaktera
Mora imati karakter @ nakon početnog teksta
Mora imati tekst nakon oznake @
Zatim, mora imati tačku i tekst nakon tačke
Sve unutar delimitera predstavlja sadržaj regularnog izraza, odnosno obrazac za poređenje.
101
Funkcija koja poredi regularni izraz sa stringom naziva se preg_match. Ova funkcija prihvata (u osnovi) dva parametra,
regularni izraz i string koji se poredi, a vraća kao rezultat 1, ako se tekst poklapa sa izrazom i 0, ako se ne poklapa.
Zapravo, funkcija vraća broj. Sledeći primer vraća rezultat 1.
echo preg_match("/mojstring/","mojstring");
Ovako banalno poređenje mogli smo izvršiti i standardnim funkcijama, dok regularne izraze obično koristimo kada ne
možemo da rešimo poređenje ni na jedan drugi način. Ne samo zato što su komplikovani za upotrebu, već i zato što po
brzini zaostaju za standardnim funkcijama.
Da bi regularni izraz imao neku funkciju, potrebno je uvesti mu još neke elemente osim delimitera.
Metakarakteri
Metakarakteri su delovi regularnog izraza, koji na neki način idenitifikuju određeni deo teksta.
. - Označava bilo koji karakter u tekstu
echo preg_match("/moj.tring/","mojKtring"); //vraća 1
ˆ - Označava početak stringa
$ - Označava kraj stringa
\s - Označava spejs
echo preg_match("/moj\sstring/","moj string"); //vraća 1
\d – Označava bilo koji broj
echo preg_match("/broj \d/","broj 5); //vraća 1
\w – Označava reč u stringu
echo preg_match("/moj \w/","moj string"); //vraca 1
Moguće je grupisanje više uslova za određeni deo teksta, uz pomoć uglastih zagrada:
echo preg_match("/a[bcd]e/","abe");
U prethodnom primeru dozvoljena je jedna od tri alternative (b, c ili d) između karaktera a i e.
Dozvoljene su i kombinacije određenih opsega karaktera sa metakarakterima. Sledeći primer podrazumeva početno
slovo a, zatim slova b ili c, kojima sleduje broj.
echo preg_match("/a[bc\d]/","ab2"); //vraca 1
Kvantifikatori
Kvantifikatori određuju koliko će se puta određeni uslov ponoviti u regularnom izrazu.
- Karakter može da se pojavi jednom ili više puta
echo preg_match("/moj s*tring/","moj sssstring"); // vraca 1
echo preg_match("/moj s*tring/","moj string"); // vraca 1
102
{n,m} Karakter mora da se pojavi minimum n puta a maksimum m puta.
echo preg_match("/moj s{1,3}tring/","moj ssstring"); // vraca 1
echo preg_match("/moj s{1,3}tring/","moj sssstring"); // vraca 0
U primeru, rekli smo da želimo da naš obrazac mora da počinje rečju moj, zatim mora uslediti prazan prostor, a zatim
moraju uslediti tri karaktera ab i bilo koji karakter. Na kraju, izraz smo završili sa rečju string, kojom prethodi jedan
prazan prostor.
Ovo smo mogli uraditi i bez malih zagrada, ali, šta ako želimo da na kompletan obrazac (ab.) primenimo neki
kvantifikator. Na primer, da mora da se ponovi jednom ili više puta (+), mogli bismo, jednostavno, izmeniti izraz:
echo preg_match("/moj (ab.)+ string/","moj abcabdabe string"); // vraca 1
Sada kada ste upoznali strukturu regularnih izraza, možete ih koristiti za proveru stringova (što ste već naučili) ili
direktnu zamenu stringova:
$tekst = "[mojTag]Dobro dosli[/mojTag]";
$regEx = "@\[mojTag\](.*?)\[/mojTag\]@i";
$noviTekst = "<b>$1</b>";
echo preg_replace($regEx, $noviTekst, $tekst);
U prethodnom primeru vidimo da je moguće čak izvršiti i parametrizaciju u regularnim izrazima. U ovom slučaju,
vrednost $1 predstavlja vrednost prvog slučaja poklapanja.
Regularni izrazi su posebna dimenzija programiranja, i nemojte se mnogo opterećivati njima. Iako su veoma efikasni,
retko da će Vam ustrebati uzorak regularnog izraza koji već ne postoji. Tako da ćete, veći deo rada na regularnim
izrazima, provesti u traženju odgovarajućeg uzorka, nego sopstvene izgradnje istog.
Vežba 1
Problem:
U aplikaciju ulazi sledeća promenljiva:
$string = "myMail@mail.ml";
Potrebno je napraviti regularni izraz kojim će se proveriti da li je vrednost promenljive mail adresa.
Rešenje:
<?php
$string = "myMail@mail.ml";
$pattern = "/^[a-zA-Z0-9]+\@[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/";
echo preg_match($pattern,$string);
?>
103
Vežba 2
Problem:
Data je sledeća promenljiva:
$string = "http://myPage.php?id=25&cat=18&user=34";
Rešenje:
<?php
$string = "http://myPage.php?id=25&cat=18&user=34";
$pars = explode("?",$string);
$pars = explode("&",$pars[1]);
$parsedPars=array();
for($i=0;$i<sizeof($pars);$i++)
{
$currentParam = explode("=",$pars[$i]);
$parsedPars[$currentParam[0]] = $currentParam[1];
}
print_r($parsedPars);
?>
Vežba 3
Problem:
Dat je sledeći url string:
$string = "http://myDomain/home/index.php?id=25&cat=18&user=34";
Rešenje:
<?php
$string = "http://myDomain/home/index.php?id=25&cat=18&user=34";
$pars = preg_replace("/http:\/\//","",$string);
$pars = preg_replace("/\?[a-zA-Z0-9=&]+/","",$pars);
print_r($pars);
?>
104
Bezbednosni koncepti (uvod u bezbednost, nacini pristupa, crne i
bele liste...)
Jedinica: 15 od 19
Rezime
Bezbednost PHP veb aplikacije najranjivija je na ulazu
Korisnički ulaz vrši se putem korisničkih kontrola
Svaki nesiguran podatak koji ulazi u PHP aplikaciju treba filtrirati
U procesu filtracije razlikujemo pojmove crne i bele liste
Na ulazu treba proveravati kontrole i referera
Na izlazu treba proveravati korisnički definisane sadržaje
Kod baze podataka treba proveravati SQL upite
Register globals omogućava automatsko kreiranje promenljivih po nazivu parametra
Da bi aplikacija bila bezbednija register globals treba da bude isključen
Prilikom uključenja postojećeg koda, treba vršiti proveru uključenih fajlova, najbolje putem bele liste
U ovoj lekciji upoznaćemo se sa bezbednosnim konceptima na vebu. Veb sajtovi se, kao što znamo, sastoje od
klijentskih i serverskih komponenti. Pri toj klasifikaciji, možemo reći da, sve dok se naš sajt nalazi u kontekstu klijenta,
sistem je potpuno bezbedan jer zapravo i nema nikakve veze sa serverom. Ali, u trenutku kada se odvija neki korisnički
definisan proces na serveru, jedan sajt postaje ranjiv.
Pogledajmo šta se događa u procesu emitovanja jedne statičke HTML strane. Klijentska aplikacija šalje zahtev veb
serveru i veb server odgovara tako što pronalazi i emituje traženi HTML dokument. U ovakvom procesu nema prostora
ni za šta, osim za pomenuti niz aktivnosti, pa je zbog toga ovakva aplikacija praktično neuništiva.
U procesu kreiranja i emitovanja dinamičke veb strane ovaj proces ima još nekoliko koraka. Na početku, i ovde
klijentska aplikacija traži određeni dokument, ali server, umesto da pronađe i prosledi taj dokument, prosleđuje
serverskoj skripti ceo zahtev i ona ga onda obrađuje i emituje na izlaz (klijentu). Ova obrada je ključna tačka za
bezbednost jedne veb aplikacije, jer ukoliko korisnik uspe da infiltrira svoj deo koda u serversku skriptu, imaće
neograničene mogućnosti za manipulaciju serverom.
Dakle, aplikacija je najranjivija na ulazu. Zbog toga je i najbitnije da budemo sigurni u to šta u nju ulazi; a tu sigurnost
ćemo postići tako što ćemo kontrolisati sve ulaze.
Šta su uopšte ulazi u veb aplikaciju?
Da bi korisnik uspeo da dođe do serverskog koda neke aplikacije (kroz tu aplikaciju), potrebno je da joj se obrati putem
nekih parametara. Ovi parametri obično dolaze do aplikacije kroz forme (post) ili parametrizovani URL string (get).
Kada neki od ovih parametara dođe do servera, server ga smešta u odgovarajuću promenljivu. Ove promenljive su
jedinstvene i dostupne su kompletnom kontekstu aplikacije, te se zato nazivaju superglobalne promenljive.
Većina superglobala, prilikom svakog zahteva i odgovora, prelazi put od klijenta do servera i obrnuto, pa se zato
smatraju nečistima, i potreban im je poseban tretman kako bi njihova upotreba bila zagarantovano bezbedna.
Pošto u ovom trenutku ne znamo sve što nam je potrebno da bismo obradili sve što se tiče bezbednosti u PHP-u (jer,
zapravo, još uvek nismo ni počeli da obrađujemo veb aplikacije), na bezbednost ćemo se vraćati više puta kroz
kurseve.
105
Kada filtriramo podatke, možemo reći aplikaciji jednu od dve stvari:
ne puštaj nikoga ko nema određene uslove
puštaj samo one koji imaju određene uslove
Ulaz
Prva ranjiva tačka u sistemu je, rekli smo, superglobalna promenljiva. A to je ujedno i mesto gde naš serverski kod ima
mogućnost neke kontrole.
Prvo što možemo prekontrolisati jeste da li nam je korisnik validan ili ne. U slučaju da se radi o korisniku koji nije
registrovan u našem sistemu, možemo proveriti odakle je došao (ukoliko treba da obradimo podatke iz neke forme, ta
forma mora doći sa nekog sigurnog i poznatog izvora). Lokacija sa koje je korisnik došao na našu stranu naziva
se referer.
Ukoliko očekujemo da korisnik bude registrovan u sistemu, vršimo sistemsku proveru (putem cookieja, sessiona ili
baze).
Kada je korisnik proveren, sledeća tačka je sam unos. Odnosno, superglobali koji taj unos sadrže. U veb aplikacijama,
korisnik može ozbiljno da nam naudi jedino putem serverskog ili SQL skripta. Zato je takav unos najčešće potrebno
preduprediti; najbolje tako što ćemo ograničiti korisnika na unos isključivo validnog sadržaja.
Na primer, ako naša aplikacija poseduje jednu kontrolu za unos teksta, i u tu kontrolu treba uneti ime ili prezime, mi
možemo na serveru proveriti da li je korisnik uneo isključivo slova. Ukoliko tekst sadrži specijalni karakter ili broj,
možemo eliminisati podatak i zatražiti novi unos.
ctype_alpha("mojeime");
Ova funkcija vratiće rezultat true, ukoliko parametar sadrži samo alfabet karaktere ili ukoliko korisnik treba da unese
neku brojnu vrednost:
is_numeric("1234");
Funkcija vraća true ukoliko je unešeni parametar broj. Oba primera su primeri bele liste i veoma su efikasni.
Izlaz
U PHP-u verovatno će izlaz naše aplikacije biti sam HTML dokument ili eventualno neka serijalizovana struktura
podataka. U bilo kom slučaju, trenutak u kome će naša aplikacija prikazati svoje nedostatke upravo je izlaz.
Na primer, ukoliko je korisnik uneo klijentsku Cross Site skriptu (o kojima će biti više reči u narednoj lekciji), ona će biti
manifestovana baš na izlazu, dok na sam sistem neće imati veliki uticaj. Sa druge strane, klijentska skripta može
naneti posledice klijentu.
Zato je potrebno izvršiti neku vrstu filtracije i na samom izlazu. Ova filtracija, pre svega, podrazumeva uklanjanje svega
što može da bude izvršeno u vidu skripte, što bi bilo jednostavno kada ponekad na strane ne bi trebalo da bude
emitovan baš sadržaj neke takve skripte. Na primer, forum koji se bavi klijentskim skriptiranjem i svi na taj forum šalju
kodove svojih skripti. Ako bismo napravili takvu filtraciju koja bi eliminisala sve skripte, postovi na ovom forumu ne bi
imali svrhu. Zato se, u ovakvim situacijama, vrši takozvani HTML enkoding (i o ovome će biti više reči u sledećoj
lekciji), koji emituje HTML sadržaje (klijentske skripte i sl.), ali u onesposobljenoj formi, tako što će njihove tagove
emitovati kroz njihovu HTML enkodiranu reprezentaciju. Ovo funkcioniše jednostavnije nego što zvuči. Znamo da se
skripte nalaze u tagovima <script>. Kada pretraživač naiđe na ovakav tag, on emituje klijentsku skriptu. Ali, ako naiđe
na sledeći tag: <script> emitovaće tekst: <script> a da taj tekst tretira kao početak skripte.
106
Naravno, za ovako nešto možete kreirati sopstvenu funkcionalnost koja će obrađivati stringove na način koji Vam
odgovara ili koristiti neke već gotove funkcije:
htmlspecialchars("<script>");- Pretvoriće zadati string u <script>
htmlspecialchars_decode("<script>"); - i obrnuto... Pretvoriće HTML enkodirani string u običan.
Ali, često Vam gotova rešenja neće odgovarati (jer, na primer, nešto ipak želite da propustite). Konkretno, funkcija iz
primera ne enkodira jednostruke navodnike koji umeju da nanesu probleme prilikom rukovanja sa bazom (mada to
možete uvesti kao parametar (htmlspecialchars("'''", ENT_QUOTES))).
Register globals
Ovo može biti, bezbednosno, veoma slaba tačka veb aplikacije. Register globals je opcija koja se nalazi u php.ini fajlu,
ali je moguće podesiti i kroz ini_set() funkciju (koja podešava parametre kroz samu aplikaciju).
Pogledajmo šta ova opcija omogućava i zbog čega u svakom trenutku treba da bude isključena.
Ukoliko u aplikaciju unesete neki parametar (a register globals je uključen). Na primer, parametar je ime=LinkGroup, na
nivou aplikacije biće automatski inicijalizovana promenljiva pod nazivom $ime (i, naravno, sa vrednošću LinkGroup).
Zamislite sada sledeći tok neke aplikacije:
prvo se izvršavaju sigurnosne provere:
provera korisnika iz baze, sesije, cookieja, fajla... – uspešno
provera nivoa pristupa – uspešno (korisnik je npr. administrator)
inciijalizuje se sledeća promenljiva:
$admin = true;
nakon toga, u zavisnosti od nivoa pristupa, korisniku se emituje određeni sadržaj:
if($obicanKorisnik)
...sadržaj za običnog korisnika...
if($admin)
...sadržaj za administratora...
U ovom slučaju (ako je register globals uključen), korisnik može da startuje aplikaciju sa sledećim parametrom
(?admin=1), koja će automatski biti inicijalizovana i bez obzira na ishod svih provera, proći u administratorski deo
aplikacije.
Ovo je moguće preduprediti i ukoliko na početku koda postavite inicijalnu vrednost promenljivoj ($admin=0), ali je
svakako najbolje opciju register globals deaktivirati.
U trenutku pisanja ovog kursa, aktuelna verzija PHP-a je 5.x (tačna verzija je 5.3). Ovo je ujedno i verzija sa kojom je
kurs potpuno kompatibilan. Već od sledeće verzije (5.4, koja je objavljena 2012. godine) opcija register globals ne
postoji u konfiguraciji PHP-a.
Baza podataka
Još jedna kritična bezbednosna tačka jedne PHP aplikacije je i izvor podataka (govorimo o ozbiljnijoj aplikaciji koja
podrazumeva i izvor podataka). Sami izvori mogu biti baza, fajlovi ili mreža.
Kada je baza u pitanju, njena najranjivija tačka su upiti koje joj upućujemo, pa je zato naročito bitno dobro isfiltrirati
korisničke podatke pre nego što ih prosledimo bazi, da ne bi došlo do SQL injectiona (takođe nešto više reči i o ovome
u sledećoj lekciji). Za filtraciju možemo koristiti već pomenute ili sopstvene funkcije.
Često se, za sadržaj koji služi za proveru (šifre) koristi i neki jednosmerni algoritam za enkodiranje. Ovo je odlična
bezbednosna praksa, jer, nakon što je šifra jednom enkodirana na ovaj način, više se nikako ne može doći do nje
(osim ako je poznata).
$sifra=md5("mojaSifra");
Ovako enkodiranu šifru ne možete više povratiti, već samo proveriti, i to tako što ćete je za proveru ponovo enkodirati:
107
$sifra=md5("mojaSifra");
if($sifra=="ab6890bf5bb25b645a5c671d9ff61a3a")
.... neka bezbednosna logika aplikacije
Vaš kod neće naravno nikada izgledati ovako (jer je ovde šifra hardkodirana u program), već će kriptovani deo biti
izvlačen iz nekog izvora (baze) i na taj način poređen.
Fajl sistem
Kao što znamo, PHP može direktno pristupati fajl sistemu, što može omogućiti potencijalnom napadaču razne
neželjene intervencije na našoj aplikaciji. Ono što je najopasnije jesu trenuci kada uključujemo fajlove u aplikaciju
(include, require itd.). Ako, na primer, naša aplikacija funkcioniše tako što, na osnovu parametra, učitava određeni fajl,
korisnik može lako kroz taj parametar proslediti sopstveni fajl (na sopstvenom serveru), koji će, iako će biti emitovan sa
potpuno druge lokacije, funkcionisati u kontekstu našeg servera i aplikacije i tako imati sva prava kao i bilo koja naša
aplikacija.
Na primer, ako naša aplikacija gradi stranu, tako što na osnovu parametra učitava određeni fajl:
include = $GET_['strana'] + ".php"; // $GET je asocijativni niz parametara iz url stringa
Tada bi korisnik mogao, jednostavno, umesto našeg URL stringa (koji je npr. ?strana=mojaStrana)
http://korisnikovdomen.com/korisnikovFajl (pri čemu na tom serveru stvarno postoji fajl: korisnikovFajl.php).
Tada bi korisnikov Fajl.php bio implementiran u našu stranu, a njegov sadržaj bi, radeći u konetkstu naše aplikacije,
mogao biti toliko loš po nas, kolika bi bila i mašta našeg napadača.
Kao i za prethodne vrste napada, i za ovaj postoje jednostavna rešenja, koja se baziraju na crnim ili belim listama. U
ovom slučaju možemo napraviti belu listu dozvoljenih fajlova i proveravati je prilikom svakog učitavanja eksternog fajla.
Na primer:
$dozvoljeneStrane = array("mojaStrana","tvojaStrana");
if in_array($_GET['strana'],$dozvoljeneStrane);
include $strana + ".php";
U ovoj lekciji smo se dotakli nekih bezbednosnih koncepata, koji se tiču PHP-a i njegovog okruženja. Za sada je
dovoljno da znate samo kako bezbednost u PHP-u funkcioniše, kao i najosnovnije načine primene bezbednosnih
mehanizama, a kasnije, kroz ostale kurseve i lekcije obrađivaćemo usputno bezbednosne tehnologije kroz trenutno
obrađivanu tehnologiju.
Ovo su standardni bezbednosni koncepti PHP-a i pre se mogu svrstati u savladavanje dečjih bolesti, nego prave
opasnosti (ne zato što nema opasnosti, već zato što smo te opasnosti svesni i znamo kako da je uklonimo), pa ih tako i
tretirajte - kao vakcine za vaše aplikacije protiv poznatih bolesti.
Vežba 1
Problem:
U aplikaciju ulazi promenljiva:
$strana = "allUsers.php";
Potrebno je napraviti mehanizam koji će putem bele liste obezbediti bezbedno učitavanje ove strane sa sistema.
Rešenje:
<?php
$allPages = array("allUsers.php","anyOtherPage.php");
$strana = "allUsers.php";
if(in_array($strana,$allPages))
include $strana;
else
echo "nepostojeca strana";
?>
108
Vežba 2
Problem:
Potrebno je napraviti validaciju sesije na osnovu User Agenta. Nakon uspešne validacije, potrebno je regenerisati ID
sesije. Ukoliko validacija nije dobra, potrebno je prekinuti izvršenje aplikacije i emitovati poruku da korisnik nije validan.
Rešenje:
<?php
if(!isset($_SESSION))
session_start();
if(!isset($_SESSION['ua']))
die("Invalid user");
$currentUserAgent = $_SERVER['HTTP_USER_AGENT'];
$sessionUserAgent = $_SESSION['ua'];
if($sessionUserAgent != $currentUserAgent)
die("Invalid user");
echo "valid user";
session_regenerate_id(true);
?>
Naomena: U primeru se pominje superglobalna promenljiva $_SESSION. U njoj se obično skladište podaci o akvitnoj
sesiji korisnika. O sesijama će biti više reči u narednim kursevima i za sada je možete tretirati samo kao najobičniji
asocijativni niz. Funkcija session_start pokreće sesiju, a funkcija session_regenerate_id ponovo generiše broj sesije.
109
Zatim, style.display Properties HTML objekta. Ukoliko se vrednost ovog Propertiesa postavi da bude none, objekat
neće biti vidljiv, ali će i dalje biti u izvornom HTML kodu.
Naročitu pažnju (i to na nekoliko mesta) treba obratiti prilikom rukovanja sa AJAX-om. Pre svega, iako AJAX nije vidljiv
u pretraživaču, vidljiv je u HTML Sourceu kao i informacije koje prosleđuje (osim ako su generisane urealnom
vremenu, ali i tada je moguće analizom koda doći do njih). Sa druge strane, AJAX obično koristi serversku aplikaciju za
punjenje podacima, pa i ta aplikacija treba da bude zaštićena od direktnog pristupa.
Druga stvar na koju treba obratiti pažnju su mesta gde korisnik ima pravo unosa podataka. Pod ovim se obično
podrazumevaju forme, odnosno kontrole formi.
Posebna su (i ogromna) tema načini na koje korisnik može poremetiti aplikaciju. Na primer, zamislimo da naša kontrola
prima dva parametra: korisničko ime i šifru, i da ih proveravamo putem upita ka bazi podataka. Korisniku će biti
dovoljno da u jedno od ova dva polja unese i kao vrednost, na primer: ' OR 1=1 ' i da ispuni uslov ulaska u zaštićeni
deo sajta.
Ili pak ukoliko korisnik ima mogućnost unosa podataka na sajt (npr. forum). Ukoliko se ne izvrši validacija tih podataka,
korisnik bi mogao bez problema uneti svoju skriptu, koja će, kada bude emitovana na stranu, biti i izvršena.
Ova dva najčešća i najjednostavnija načina za neželjeni ulazak na sajtove (a respektivno, nazivaju se SQL injection i
Cross Site Scripting), trebalo bi preduprediti određenim merama. Protiv hakovanja se, naravno, ne može, ali bar treba
uraditi sve što je u moći programera da svoju aplikaciju što bolje zaštiti.
Safe režim
Kada budete u situaciji da PHP izvršavate u okruženju u kome delite server potrebno je da znate nešto o safe modu.
Kada je ovaj režim omogućen takođe je omogućeno i poređenje vlasnika skripta koji se izvršava i vlasnika datoteke
koju skript prilikom izvršavanja pokušava da otvori. Na ovaj način je onemogućeno nepredviđeno izvršavanje,
pregledanje i izmena od strane korisnika koji na to nemaju pravo čime se omogućava precizno definisanje privilegija
korišćenja. Omogućavanje safe režima ima veliki uticaj na i na izvršavanje php okruženja u velikoj meri da dovodi do
mogućnosti da se mnoge php funkcije skrivaju, pa čak i onemogućavaju.
Da budemo malo određeniji: kada želimo da definišemo safe režim, definisaćemo i sledeća ograničenja:
Upotrebu svih ulaznih i izlaznih funkcija (na primer, funkcije koje rade sa datotekama) ograničavaju se na
upotrebu od strane istog vlasnika kao i skript koji izvršava ove funkcije. Zamislimo da je omogućen safe mod i
da pokušavate da izvršite funkciju fopen() nad datotekom čiji je vlasnik vaš kolega, ta operacija neće moći da
se izvrši. Međutim, ukoliko ste vi vlasnik skripta koji poziva funkciju i vlasnik datoteke koju funkcija pokušava da
otvori biće omogućena operacija koja treba da se izvrši.
Kreiranje datoteke od strane korisnika biće omogućeno samo u slučaju da je korisnik i vlasnik direktorijuma u
kome želi da kreira datoteku.
HTTP provera autentičnostije dodatno poboljšana zbog identifikatora korisnika koji se vezuje za vlasnika
skripta.
Ukoliko ste korisnik MySql servera beze podataka, korisničko ime koje koristite za povezivanje na MySql
server mora da bude identično korisničkom imenu koje predstavlja i vlasnika datoteke u kojoj se izvršava
mysql_connect() metoda.
Potrebno je napomenuti i da će se ova mogućnost od verzije PHP 5.4 izgubiti, pa obratite pažnju da ukoliko želite da
ga koristite radite sa verzijama koje prethode ovoj verziji.
Klijentska validacija
O klijentskoj validaciji nećemo mnogo govoriti. Jednostavno, potrebno je preduprediti unos neželjenih podataka u
kontrole na klijentskom delu. Ovo, naravno, moramo uraditi uz pomoć JavaScripta, pri čemu ćemo pre prosleđivanja
podataka iz kontrole na server izvršiti validaciju. Na primer:
110
<script type = "text/javascript">
function validacijaMail(field, alerttxt)
{
with (field)
{
apos = value.indexOf("@");
dotpos = value.lastIndexOf(".");
if (apos < 1 || dotpos-apos < 2)
{alert(alerttxt); return false;}
else {return true;}
}
}
function validacijaForma(thisform)
{
with (thisform)
{
if (validacijaMail(email,"Nije e-mail adresa") == false)
{email.focus();return false;}
}
}
</script>
</head><body>
<form action=""
onsubmit="return validacijaForma(this);"
method="post">
Email: <input type="text" name="email" size="30">
<input type="submit" value="Submit">
</form>
Problem je što ovakva validacija nema baš neku suštinu, osim da korisniku pomogne prilikom unosa podataka. Jer,
korisnik može celu stranu prebaciti na svoj server, promeniti joj sadržaj, izbaciti validaciju i proslediti podatke koje želi.
Zbog toga, glavna validacija treba da se odvija na serverskom delu aplikacije.
Serverska validacija
Provera referera
Korisnik na serveru već ne može da ostvari takvu kontrolu kao na klijentu. Naime, korisnik podatke do servera mora
poslati putem nekog sistema, a na programeru je da taj sistem osmisli tako da ukloni sve moguće pretnje.
U prethodnim lekcijama smo već pominjali „referera”. Ovo je lokacija sa koje je pretraživač došao na trenutnu lokaciju.
Dobra je praksa, pre izvršavanja koda na „sigurnoj” stranici, proveriti odakle je došao i nastaviti izvršenje samo ako je u
pitanju željena lokacija. Ovo možemo isprobati na najjednostavnijem primeru. Napravimo jedan PHP dokument
test.php, sa sledećim sadržajem:
<?php
echo($_SERVER['HTTP_REFERER']);
?>
<br>
<a href = "test.php">provera refera</a>
Ukoliko otvorimo ovu stranu prvi put, u pretraživaču će biti prikazan samo link “provera referera”. Ali, ako kliknemo na
link, na strani će biti prikazan i referer, odnosno, strana sa koje je pretraživač došao, što je u ovom slučaju ista strana.
Ostaje samo da odlučite kojom ćete logikom proveriti dolazak (da li će biti samo provera domena ili baš određene
lokacije) i uslovno izvršite ili ne izvršite ostatak strane.
111
HTML encode/disarm
Pomenuti Cross Site Scripting, sa početka lekcije, veoma je jednostavno detektovati i eliminisati u serverskom kodu.
Dovoljno je da svaki korisnički unos propustimo kroz funkciju koja će konvertovati opasne karaktere u bezbedniji format
(ASCII kod) i u takvom obliku ih pustimo da idu dalje.
Na primer:
function srediTekst($tekst)
{
$tekst = str_replace("<", "<", $tekst);
$tekst = str_replace(">", ">", $tekst);
}
Validacioni filteri
PHP ima i ugrađene filtere za validaciju koji se mogu ostvariti funkcijom filter_var(). Ova funkcija funkcioniše tako što joj
se, kao parametri, proslede string i tip validacije. Zapravo, funkcija filter_var() ima dva oblika funkcionisanja. Jedan je
validacija podataka koja vrši validaciju i daje rezultat o toj validaciji, a druga je sređivanje (Sanitize) podataka, koja
jednostavno sređuje podatke; nešto poput malopređašnjeg pasusa, gde smo to uradili ručno. Način na koji će
funkcionisati funkcija zavisi od prosleđenog validacionog tipa.
Ovaj primer proverava da li je string validan URL:
<?php
$url = "http://www.mojsajt.com";
if(filter_var($url, FILTER_VALIDATE_URL))
echo("jeste");
else
echo("nije");
?>
112
FILTER_SANITIZE_NUMBER_INT
Izbacuje slova, ostavlja samo brojeve i aritmetičke operatore
FILTER_SANITIZE_NUMBER_FLOAT
Izbacuje slova, ostavlja samo brojeve, aritmetičke operatore, tačku i znak E za eksponent
FILTER_SANITIZE_MAGIC_QUOTES
Dodaje backslash ispred dvostrukih navodnika
FILTER_VALIDATE_INT
Proverava da li je vrednost integer
FILTER_VALIDATE_BOOLEAN
Proverava da li je vrednost boolean
FILTER_VALIDATE_FLOAT
Proverava da li je vrednost float
FILTER_VALIDATE_REGEXP
Proverava vrednost po regularnom izrazu
FILTER_VALIDATE_URL
Proverava da li je vrednost zapisana kao validan URL string
FILTER_VALIDATE_EMAIL
Proverava da li je vrednost zapisana kao validan e-mail
FILTER_VALIDATE_IP
Proverava da li je vrednost zapisana u formatu validnog IP-ja
Moguće je izvršiti čitav niz validacionih uslova, nad nizom podataka, naredbom filter_var_array().
Enkripcija na web serveru je bez smisla ukoliko se skriptovi koji koriste šeme za enkripciju ne nalaze na serveru koji
dozvoljava SSL (Secure Sockets Layer – protokol koji se koristi za enkripciju informacija preko interneta). SSL
omogućava da sve podatke koje klijent unese na svojoj strani, browser kriptuje pre prosleđivanja serveru, a zatim da
iste te podatke server dekriptuje kada dođu do njega.
113
Primer:
Pređimo sada na primer da bismo utvrdili o čemu se radi pored nešto komplikovanijeg objašnjenja. Ukoliko želite da
kodirate šifru korisnika u trenutku njegovog registovanja možete to rešiti primenom funkcije mhash() . Funkcija mhash()
koristi parametre koje smo naveli pri čemu heš parametre definiše algoritam koji ćete primenjivati, dok parametar
podataka predstavlja šifru na koju se primenjuje izabrani algoritam, kao sto možemo uočiti u sledećem primeru:
<?php
$sifraKorisnika = "mysecretpswd";
$sifraHash = mhash( MHASH_SHA1, $sifraKorisnika );
echo 'Sifra korisnika nakon enkripcije je : '. bin2hex( $sifraHash );
?>
Nakon izvršenja koda na izlazu dobijamo sledeći rezultat:
Sifra korisnika nakon enkripcije je : 07c45f62d68d6e63a9cc18a5e1871438ba8485c2
U primeru koristili smo i bin2hex() funkciju kako bismo mogli da konvertujemo heš iz binarnog u heksadecimalni oblik,
tako da možemo formatirati da naš kod bude pregledno prikazan u okviru web čitača.
Putem uključivanja opcionog parametra ključ u okviru funkcije može se primenjivati i za utvrđivanje integriteta poruke i
njene autentičnosti. Ukoliko prosledite tajni ključ poruke, mhash() funkcija će proveriti validnost poruke na osnovu
definisane vrednosti Hashed Message Autentication( HMAC ) kod poruke. HMAC kod je neka vrsta čeksuma za
kodiranje poruke. Ukoliko se HMAC vrednost poklapa sa onom koja je objavljena zajedno sa porukom, poruka je
pristigla bez modifikacije originalnog sadržaja.
Rukovanje greškama
Jedinica: 17 od 19
Rezime
Najčešći uzrok grešaka jeste problem u pristupu spoljnim resursima (fajlovi, baza, korisnički ulaz, strim)
Greške se predupređuju logikom u kodu, obradom izuzetaka, obradom grešaka
Moguće je ručno aktivirati grešku
Moguće je napraviti sopstveni hendler za rukovanje greškama, koji će hvatati sve greške ili one određenog tipa
i tim hendlerom prepisati ugrađeni hendler.
Moguće je izbaciti sopstveni izuzetak tokom izvršavanja koda
Moguće je napraviti sopstvenu klasu izuzetaka koja nasleđuje klasu Exception
Izuzecima se rukuje tako što se glavni kod stavlja u try blok a alternativni kod u catch blok, pri čemu oba bloka
moraju postojati i catch blok mora prihvatiti promenljivu koja je tipa izuzetak.
U ovoj lekciji biće objašnjeni pojmovi koji se odnose na greške koje se mogu javiti u toku programiranja, kao i načine
na koje se može rukovati njima.
Rukovanje greškama veoma je bitan element u svakom programskom jeziku na praktično svim platformama. Nikada
ne možemo biti potpuno sigurni šta će i kada korisnik uraditi, kao ni kada će sistem i njegovi resursi, iz nekog razloga,
omesti naš program u pravilnom izvršavanju.
Upravo iz tog razloga, obaveza programera je da predvidi koje tačke u programu predstavljaju potencijalnu opasnost
po njegovo izvršavanje i da te pozicije obezbedi dodatnim zaštitnim sistemima.
Najbolnije tačke jedne aplikacije su trenuci kada se ta aplikacija obraća resursima. A ti resursi, odnosno, njihovo
poreklo, najčešće su baza podataka ili fajl sistem. Pored njih, kritični trenuci događaju se i prilikom svakog korisničkog
ulaza u aplikaciju (unos podataka), zatim striminga, komunikacije sa uređajima i slično.
114
Osnovno rukovanje greškama je dosta jednostavno. Treba samo ispoštovati sledeći set pravila:
Staviti kritičan deo u poseban blok
Staviti alternativni deo u poseban blok
To možemo uraditi ručno ili putem try - catch blokova, u zavisnosti od tipa greške koji očekujemo i toga da li je u stanju
da bude obrađena kao izuzetak.
Programske greške
Bez obzira koji se programski jezik koristi razlikujemo tri najopštije vrste grešaka, a to su:
Sintaksne greške
Greške pri izvršavanju koda
Logičke greške
Sintaksne greške – PHP kao i svaki drugi programski jezik poštuje osnovno pravilo koje predstavlja sintaksu jezika.
Ukoliko neka od naredbi ne poštuje pravila jezika reći ćemo da ima sintaksnu grešku. Kada PHP skript sadrži sintaksnu
grešku PHP – analizator koda neće moći da obradi deo skripta ili čak ceo skript u zavisnosti od ozbiljnosti greške.
Pogledajmo sledeći kod:
<?php
if (true)
{
echo 'greska je prijavljena ovde';
?>
Greška koja će se generisati nakon izvršenja imaće sličnu strukturu:
Parse error: parse error, unexpected $end in ~putanja do vašeg fajla~ on line 2
Sintaksnu grešku čini zatvorena vitičasta zagrada koja nedostaje. Tačnije, zagrada je otvorena i započeta naredba za
izvršavanje, ali, s obzirom na to da zagrada nije zatvorena, analizator nailazi na problem jer ne zna gde da završi naš
skript.
Greška pri izvršavanju koda – Otkriti i ispraviti grešku koja se javlja prilikom izvršavanja koda može biti teže od
očekivanog. Ako vas kod sadrži sintaksnu grešku analizator će je otkriti čim pokušate da izvršite taj kod. Međutim,
greška koja se javlja prilikom izvršavanja koda ne potiče uvek iz vašeg skripta, pa je nekada nije tako lako uočiti.
Razlozi ovakvih grešaka mogu biti razni događaji i naredbe, ali se mogu nalaziti i između uzajamnih delovanja skripta.
Često će se desiti da preuzimanjem podataka i obradom nekih već izgenerisanih informacija dodje do računske greške
koja će ispisati:
Warning: Division by zero.... ..... on line ...
Moramo priznati da bi retko ko poželeo da deli sa nulom, ali i da se često desi ovakav problem koji predstavlja grešku
pri izvršavanju.
Logičke greške – Najteže greške koje je najteže i otkloniti iz razloga što se vodite vašom logikom i očekujete da vaš
kod radi ono što ste zamislili, međutim i najmanja greška može izazvati apsolutni preokret izvršene naredbe. Uzrok
može biti obična greška pri kucanju, na primer:
for ( $i = 0; $i < 10; $i++ );
{
echo ' pisi <br/ >';
}
Kod koji smo prikazali u primeru je sasvim ispravan i izvršava se bez problema. Problem se javlja u samom izvršenju
naredbe i krije se u ; na kraju for naredbe. Rešenje naredbe biće izvršenje for petlje 10 puta bez ikakvog rezultata i
izvršenje echo naredbe samo jednom. Verujemo da je korisnik pisanjem ovog koda očekivao rezultat u kome će
naredba echo sa tekstom 'pisi' biti izvršena u okviru for petlje i ispisana deset puta na izlazu.
115
Ručna obrada grešaka na najnižem nivou
Pre nego što pristupimo nekom resursu, najbolje je ispitati da li taj resurs postoji i na osnovu toga nastaviti delovanje
programa. Na primer:
<?php
$file = fopen("mojFajl.txt", "r");
?>
Ukoliko se fajl mojFajl.txt ne nalazi u folderu aplikacije, ovaj kod će izazvati grešku. Zato bi prethodno trebalo proveriti
da li fajl postoji i, u odnosu na to, obezbediti ga:
<?php
if(!file_exists("mojFajl.txt"))
{
$file = fopen("mojFajl.txt", "w");
//ovde bi trebalo proći kroz punjenje fajla podacima
fclose( $file );
}
$file = fopen("mojFajl.txt", "r");
?>
die()
Ova funkcija trenutno prekida izvršenje programa uz emitovanje (ili bez njega) korisnički definisane poruke. Ukoliko,
naime, dalje izvršenje programa zavisi od resursa koje treba da pročitamo (na primer, od fajla mojFajl.txt u prethodnim
primerima), onda svakako treba prekinuti dalje izvršavanje programa, ukoliko tog resursa nema.
U ovom primeru, ukoliko fajla nema, biće ispisana poruka greške, zatim poruka funkcije die (kraj) i izvršavanje će biti
prekinuto.
<?php
$file = fopen("mojFajl.txt ", "r") or die("kraj");
?>
Ručno emitovanje grešaka
U prethodnom primeru prekidali smo izvršavanje programa funkcijom die(). Takođe, moguće je i emitovanje sopstvene
poruke o grešci bez prekidanja izvršavanja. Ova linija koda će na poziciji na kojoj se nalazi emitovati poruku o grešci.
trigger_error("Moja greška");
Tip na ovaj način emitovane greške će biti 1024 (Notice), što možda nije nivo ozbiljnosti koji želimo da predočimo
korisniku. Da bismo ovo promenili, možemo eksplicitno, kao drugi parametar, uneti jedan od tri tipa grešaka koje ova
funkcija prihvata i čije konvencije bi trebalo da poštujemo pri korišćenju:
116
E_USER_WARNING (512) – Greška koja utiče na rad aplikacije (npr. nismo pronašli resurse), ali aplikacija
može da nastavi sa radom
E_USER_NOTICE (1024) – Samo obaveštenje; koristi se kada želimo korisnika da upozorimo na neku
anomaliju u aplikaciji
E_USER_ERROR (256) – Ova greška treba da prethodi prekidu izvršavanja programa.
Na primer:
trigger_error("Moja greška", E_USER_WARNING);
Nakon što napravimo funkciju koja želimo da rukuje greškama, potrebno je da joj dodelimo inicijalnu vrednost kao
podrazumevani rukovalac greškama:
set_error_handler("mojHendler");
Nakon toga, sve greške će biti, umesto u ugrađeni rukovalac, prosleđivane u našu ručno kreiranu funkciju.
Lista kodova (brojeva) greške, u odnosu na funkciju trigger_error, ovde je malo proširena i sastoji se od 7 kodova:
E_WARNING (2) - Greška koja ne prekida rad aplikacije ali utiče (nema resursa...)
E_NOTICE (8) – Samo obaveštenje
E_USER_ERROR (256) – Fatalna greška, prekida se izvršenje
E_USER_WARNING (512)
E_USER_NOTICE (1024)
E_RECOVERABLE_ERROR (4096) – Fatalna greška, koju je moguće obraditi i koja ne ostavlja trajne
posledice po aplikaciju
E_ALL (8191) – Sve vrste grešaka
Greške iz ove liste, možemo priključiti čak i samom hendleru, kroz parametar funkcije set_error_handler:
set_error_handler("mojHendler", E_USER_NOTICE);
U ovom slučaju, kroz naš hendler, proći će samo greške tipa E_USER_NOTICE, dok će ostale greške biti obrađivane
kroz ugrađeni hendler
117
Evo primera kompletnog koda:
<?php
//kreacija funkcije-hendlera
function mojHendler( $brojGreske, $porukaGreske )
{
echo $brojGreske . " " . $porukaGreske;
}
//prepisivanje sistemskog hendlera korisnickim
set_error_handler("mojHendler");
//izazivanje greske unosom neinicijalizovane varijable
echo( $mojaVarijabla );
?>
Nakon uhvaćene greške najbolje je proslediti je u neki log u bazi ili na fajl sistemu. Loger za neki specifičan sistem (na
primer, da pamtimo logove u bazi) možemo napisati ručno, dok za standardne tipova loga možemo koristiti i ugrađenu
funkciju error_log().
Ova funkcija prima do četiri parametra: poruku greške, tip logovanja, destinaciju i zaglavlje.
Poruka greške je bilo koja korisnička poruka, za koju želimo da bude zapamćena u logu. Tip logovanja predstavlja,
zapravo, destinaciju slanja ovog loga, pri čemu je:
0 – Default (koristi se sistemski definisan log),
1 – Mail (log entry se šalje na mail),
3 – Fajl (log entry se upisuje u fajl)
U slučaju da je tip destinacije 1 i 2 (mail ili fajl), potrebni su i dodatni parametri (zaglavlje i destinacija za mail i
adresu destinacioni fajl za fajl).
<?php
error_log("Moja greska", 1, "ciljniMail@mail.com", "From:mojMail@mail.com");
?>
<?php
error_log("Moja greska", 1, "c:/mojfajl.log");
?>
Klasa Exception
U okviru PHP-a postoji ugrađena klasa Exception. Konstruktor klase Exception prihvata dva parametra, prvi čini tekst
poruke o grešci, dok drugi parametar predstavlja broj greške.
Osim samog konstruktora klasa Exception ima na raspolaganju i sledeće metode:
getCode() – vraća broj greške koji je bio prosleđen konstruktoru
getMessage() – vraća tekst poruke koja je bila prosleđena konstruktoru
getFile() – pozivajućem kodu vraća punu putanju datoteke u kojoj je generisan izuzetak
getLine() – vraćabroj reda u kodu u kome je generisan izuzetak
getTrace() – vraća niz s podacima o stablu pozivanja (ili backtrace pokazuje koje su se sve funkcije izvršavale
u trenutku generisanja izuzetka) koji omogućavaju utvrđivanje mesta na kome je generisan izuzetak
getTraceAsString() – vraća iste podatke kao getTrace(), formatirane kao znakovni niz
_toString() – omogućava da se naredbi echo direktno prosledi sadržaj objekta Exception, sa svim podacima
koje daju navedene metode.
118
Napomena: Kako bi ispratili kontekst lekcije, pomenuli smo i klasu Exception, koja je inače deo objektnog koncepta koji
se ne obrađuje u ovom kursu. Zbog toga će neki pojmovi ostati nedorečeni.
Rukovanje izuzecima
Nije uvek moguće rešavanje problema sa resursima (i sličnih) putem uslovnih izvršavanja koda. Ponekad je
jednostavno potrebno pokušati nešto da bi se znalo da li to nešto može da se uradi. U tom slučaju, treba nam
mehanizam koji će reagovati tek nakon dolaska do greške, a da pri tom ne poremeti normalan rad programa. Ovakav
mehanizam postoji i naziva se rukovalac izuzecima.
Rukovalac izuzecima je pojam blisko vezan za objektno orijentisano programiranje, jer, u stvari, izuzetak jeste nešto
što je karakteristično za određeni događaj određene klase.
Vratimo se na primer sa početka lekcije, gde smo pokušali da pročitamo nepostojeći fajl:
<?php
$file = fopen("mojFajl.txt", "r");
?>
... gde smo problem nepostojećeg fajla rešili tako što smo postavili uslov ispred čitanja:
if(file_exists("mojFajl.txt"));
Recimo da je sve ovo sada deo jedne klase koja rukuje fajlovima.
<?php
function citaj($fajl)
{
if(file_exists($fajl))
$file = fopen($fajl, "r");
}
?>
Poziv funkcije citaj() ove klase neće prikazati grešku, što je očekivano. Takođe, mogli smo i ubaciti logiku, koja bi
izbacila poruku o nepostojanju fajla. Ali, da bi naša greška o nepostojećem fajlu bila u konvenciji izuzetaka, odnosno,
da bi korisnici klase (ukoliko je izuzetak izbačen iz klase) ili mi sami mogli da je uhvate kao standardan izuzetak,
standardnim metodama za hvatanje izuzetaka potrebno je da i objekat koji emitujemo prilikom obrade ove naše greške
bude tipa izuzetak.
<?php
function citaj($fajl)
{
if(!file_exists($fajl))
throw new Exception("Fajl ne postoji");
else
$file = fopen($fajl, "r");
}
//izazivanje izuzetka
citaj("mojFajl.txt");
?>
Ovako emitovanu grešku (izuzetak) lako hvatamo upotrebom try-catch bloka. Potrebno je samo da naznačimo u kom
delu predviđamo događanje izuzetka (u ovom slučaju to je poziv metode citaj()) i stavimo ga u try blok, a zatim dodamo
alternativni kod (koji treba da se izvrši ako try blok ne uspe) u catch blok. Catch blok prihvata parametar tipa Exception,
koji sadrži svojstva i metode za razotkrivanje određenih detalja vezanih za sam Exception.
119
try
{
citaj("mojFajl.txt");
}
catch(Exception $e)
{
echo $e;
}
Umesto new Exception, koji smo izbacili iz funkcije citaj(), mogli smo da izbacimo i instancu sopstvene klase izuzetaka.
Naravno, ukoliko smo je prethodno napravili; a možemo je napraviti nasleđivanjem klase Exception i dodavanjem
svojih elemenata:
class mojIzuzetak extends Exception
{
public function errorMessage()
{
return "moj izuzetak";
}
}
Vežba 1
Problem:
Data je sledeća promenljiva:
$whiteList = array("index.php", "index1.php", "index2.php");
Potrebno je napraviti funkciju includeFile, koja će prihvatati naziv fajla, proveriti da li taj naziv postoji u nizu i da li
postoji fajl sa tim imenom. Ukoliko fajl ne postoji u nizu ili na fajl sistemu, potrebno je prekinuti funkciju emitovanjem
izuzetka. U suprotnom, treba učitati fajl funkcijom include ili require.
Potrebno je izvršiti poziv funkcije u try catch bloku.
Rešenje:
<?php
$whiteList = array("index.php","index1.php","index2.php");
function includeFile($file)
{
global $whiteList;
if(!in_array($file, $whiteList))
throw new Exception("No file in whitelist");
else if(!file_exists($file))
throw new Exception("Filename is not valid");
else
include $file;
}
try
{
includeFile("index.php");
}
catch(Exception $ex)
{
echo $ex->getMessage();
}
?>
120
Rukovanje mysql-om
Jedinica: 18 od 19
Rezime
Projekat SQL Buddyja je akcentovan tako da se bazira na lakoj instalaciji, u okviru Wamp Servera i jednostavnom
korisničkom interfejsu.
Odabirom “Insert” opcije imate mogućnost da unosite podatke u tabele koje ste kreirali.
Ono što je potrebno prilikom promene passworda da uradite jeste da podesite password za root korisničko ime i
uklonite anonimus korisnika, i kreirate novog korisnika, ukoliko je potrebno.
Importom Baze u MySql moguće je da uvedete vašu, već postojeću bazu.
Baza je preporučljivo da ima .sql ekstenziju.
Export baze podataka predstavlja izvoz baze iz SQL Buddy okvira.
Biblioteka funkcija koju koristi php za uspostavljanje veze sa MySql-om zove se mysqli (slovo i je dodato od
engleske reči improved, što znači poboljšan).
mysqli_connect_errno() vraća broj grešaka u slučaju neuspešnog izvršavanja, u slučaju da je uspešno izvršena
vraća nulu.
Imena funkcija sa proceduralnim verzijama počinju sa ’mysqli_’ i tim funkcijama se mora proslediti resurs koji ste
prethodno dobili od funkcije mysqli_connect().
Potrebno je da bazu podataka sa kojom želite da se povežete navedete kao parametar funkcije mysqli_connect().
Izvršavanje upita ka bazi podataka obavlja se preko mysqli_query() funkcije.
Skup rezultata možete možete osloboditi pozivom metode: mysqli_free_result( $rezultati );
Funkcija mysqli_close(veza sa bazom) se koristi za raskidanje veza sa bazom.
Ova lekcija biće posvećena komunikaciji sa bazom podataka, kao i manipulaciji upitima i tabelama.
SQL Buddy je open sorce aplikacija bazirana na webu pisana u PHP-u sa namerom da vrši administrativne poslove
nad MySql i SqlLite korišćenjem Web browsera. Projekat SQL Buddyja je akcentovan tako da se bazira na lakoj
instalaciji, u okviru Wamp Servera i jednostavnom korisničkom interfejsu.
U okviru Wamp servera o kome smo već govorili, nalazi se i podrška za MySql bazu podataka. U okviru baze i
opcije sqlbuddy možete jednostavno kreirati i manipulisati vašom bazom podataka i tabelama u njoj. S obzirom na to
da je u okviru Wamp Servera nećete imati dodatne komplikacije prilikom pozivanja vaše baze i pronalaženja njenog
sadžaja.
Takođe preporučljivo je i korišćenje phpmyadmin radnih okvira koji su ozbiljniji i specijalizovani za rad sa MySql-om i
koje ćemo koristiti u našem radu. Za objašnjenje korišćenja sqlbuddyja opredelili smo se da biste videli koje jos
alternative imate i opredelli se za najpogodniju u vašim aplikacijama. phpMyAdmin je najčešće korišćena web
aplikacija za upravljanje MySql-om.
Što se tiče SQL Buddyja sada ćemo pokazati osovne mogućnosti koje vam pruža.
Objasnićemo kako da kreirate vašu željenu bazu u sledećim koracima:
121
1. Pokrenite Wamp server u okviru vašeg web browsera unosom localhost u prostor za adresu ili klikom direktno na
localhost u meniju Wamp severa
2. Odaberite iz menija (na dnu stranice) opciju sqlbuddy
3. Biće vam prikazana stranica kao na slici. I moći ćete odmah da kreirate vašu bazu podataka unosom njenog imena
u predviđeno polje.
4. U donjem delu prikazane stranice nalazi se i spisak prečica koje će vam olakšati kretanje i kreiranje vaših podataka.
5. Kreiranje baze podataka se izvršava unosom njemog imena i odabirom pisma koje se koristi. Klikom na Submit
6. Kada ste kreirali vašu bazu dobijate pregled kao na slici u nastavku i imate više mogućnosti za rad.
122
7. Nakon potvrđivanja unosa tabele i prvog polja u njoj prikazaće vam se stranica u nastavku sa prikazanim poljima u
tabeli i otvara vam se mogućnost da dalje unosite polja i manipulišete primarnim i sekundarnim ključevima tabele…
8. Kreiranim poljima takođe možete manipulisati. Nakon kreiranja sva vaša polja biće tabelarno prikazana, na stranici
iznad njih možete uočiti manji meni za rad. Odabirom na Edit otvoriće vam se polja za manipulaciju, tačnije izmenu
vašeg polja koje ste selektovali.
9. Takođe, selektovanjem Delete opcije zahtevaće se od vas da potvrdite brisanje označenog polja i izvršenja
operacije brisanja.
123
Odabirom “Insert” opcije imate mogućnost da unosite podatke u tabele koje ste kreirali.
124
Ne bi trebalo da koristite glavnog korisnika „root“ za osnovne operacije. „root“ bi trebalo da bude upotrebljen samo za
kreiranje novih korisnika. Takođe, možete kreirati novog korisnika za upotrebu i rad na standardnim operacijama. Za
kreiranje novog korisnika zvanog “wampuser“ potrebno je da uradite sledeće:
1. Ulogujte se na SQL Buddy sa korisničkim imenom “root“
2. Odaberite opciju “Users“
3. U delu ADD NEW USER , unesite “localhost“ u polje za unos koje pripada Hostu, a “wampuser“ u polje za
unos koje pripada Name i “xxxx“ u polje za unos koje pripada Passwordu. Za početak nemojte čekirati “Grant
Option“, samo potvrdite klikom na dugme “Submit“.
Import
Importom Baze u MySql moguće je da uvedete vašu, već postojeću bazu. Baza je preporučljivo da ima .sql ekstenziju.
Bazu možete uvesti na sledeći način:
1. Klikom na Odaberi datoteku birate fajl koji želite da uvezete
2. Potvrdom na Submit vaša baza biće importovana i nalaziće se na spisku baza za korišćenje sa leve strane.
Export
Export baze podataka predstavlja izvoz baze iz SQL Buddy okvira. Baza će biti “spakovana“ u .sql fajl i kao takva moći
će da se uveze u neke druge okvire baza podataka. Export se vrši na sledeći način:
1. Iz ponuđene liste odaberete željenu bazu koju želite da izvezete.
2. U odeljku Export: možete odabrati da li izvozite strukturu baze i bazu, najbolje je da čekirate obe opcije i
upotpunite bazu.
3. U Options: delu birate da li želite komaktan, smanjeni insert ili kompletan odnosno ceo insert iz baze
podataka.
4. I u poslednjem delu Output to: Browser ili Text file su opcije koje možete odabrati u zavisnosti od broja
redova u odabranoj bazi podataka, kada imate veći broj redova preporučuje se odabir Text file.
5. Klikom na Submit potvrđujete i završavate vaše exportovanje baze.
125
Query
U svakom trenutku, ukoliko želite da komunicirate sa bazom podataka možete pozvati Query opciju i u okviru polja za
unos pisati svoje upite. Klikom na Submit potvrđujete izvršenje ispisanog upita.
U ovom trenutku sve što je nama potrebno za rad sa bazom nalazi se u olakšanom delu SQL Buddyja bez potrebe da
znate sintaksu kreiranja upita nad vašom bazom.
Biblioteka funkcija koju koristi PHP za uspostavljanje veze sa MySql-om zove se mysqli (slovo i je dodato od engleske
reči improved, što znači poboljšan). Sa korišćenjem ove biblioteke imate mogućnost da koristite i objektno orijentisanu i
proceduralnu sintaksu.
Sada ćemo koristit proceduralnu sintaksu za pristu bazi podataka. Evo i primera:
Kao rezultat ove funkcije dobićemo vezu sa bazom podataka tipa resurs. Ako koristimo proceduralnu sintaksu kao u
primeru i dobijeni rezultat kao resurs, potrebno je da dobijeni resurs prosledite svim daljim funkcijama iz biblioteke
mysqli koje upotrebite. Imena funkcija sa proceduralnim verzijama počinju sa ’mysqli_’ i tim funkcijama se mora
proslediti resurs koji ste predhodno dobili od funkcije mysqli_connect().
Potrebno je da uvek proverite rezultat pokušaja uspostavljanja veze. Razlog tome je što preostali deo skripta neće
raditi bez funkcionalne povezanosti sa bazom podataka. Ovakvu proveru možete izvršiti sledećim kodom:
if(mysqli_connect_errno())
{
echo 'greska prilikom konekcije na bazu. Molimo vas pokusajte kasnije';
exit;
}
Funkcija koju smo upotrebili mysqli_connect_errno() vraća broj grešaka u slučaju neuspešnog izvršavanja, u slučaju
da je uspešno izvršena vraća nulu.
Takođe, preporuka je da kada uspostavljate vezu sa bazom podataka red koda u kome se nalazi konekcija na bazu
podataka započnete sa ’@’ kako biste imali mogućnost da potencijalne greške obradite kako smatrate da treba.
Kada radite na konekcijama sa bazom, potrebno je da znate i da postoji ograničen broj istovremenih veza koje se
mogu uspostaviti sa MySql serverom. U okviru MySql-a postoji i parametarmax_connections kojim se određuje
maksimalan broj veza. Ovaj parametar svojim radom sprečava preopterećenje servera iz razloga prevelikog broja
zahteva ili lošeg rada softvera. Standardnu vrednost ovog parametra možete izmeniti u datoteci my.ini.
126
u ovom primeru možemo uočiti poziv resursa kao parametra funkcije mysqli_ koji smo spominjali.
U ovom upitu .$jmbg predstavlja promenljivu koju je korisnik definisao (dodelio joj vrednost) u okviru aplikacije.
Promenljiva se dalje poredi sa poljem u bazi i na taj način filtrira rezultat upita.
Parametari funkcije su tekst upita koji želimo da izvršimo i veza sa bazom podataka je $db.
Rezultati pozivanja željenog upita smeštaju se u promenljivu $rezultat da bismo kasnije mogli da manipulišemo njima.
Ukoliko dođe do greške prilikom izvršenja i funkcija se ne izvrši kako je planirano, rezultat će biti logička vrednost false.
Izvršenjem funkcije, broj redova koji ste dobili kao rezultat dalje možete korisno upotrebiti ukoliko želite ili obradite
rezultat upita. Kada znate koliko redova imate, možete upotrebiti petlju for na sledeći način:
mysqli_free_result( $rezultati );
i nakon toga možete upotrebiti metod:
mysqli_close(veza sa bazom );
Da biste prekinuli vezu sa bazom podataka nije uvek potrebno da uvek koristite ovu metodu jer će se veza svakako
prekinuti po izvršavanju skripta.
127
Vežba 1
Problem:
Potrebno je napraviti kraću bazu podataka koristeći SQL Buddy razvojno okruženje i koristeći se proceduralnom
sintaksom (funkcije iz biblioteke mysqli() ... ) napisati otvaranje konekcije, ispisivanje upita, pozivanje upita i zatvaranje
konekcije.
Rešenje:
<?php
// otvaranje konekcije
@ $db = mysqli_connect('localhost', 'root', '','testbaza');
// provera da li je uspešna konekcija, i poruka o gresci ukoliko nije uspešna knekcija
if(mysqli_connect_errno())
{
echo ' Greska prilikom konekcije na bazu. Molimo vas pokusajte kasnije ';
exit;
}
// dodeljivanje vrednosti promenljivoj
$jmbg = '1111111111111';
// kreiranje upita za izvršenje nad bazom
$upit = “select * from polaznici where ”. $jmbg. “like JMBG”;
// izvršavanje upita nad bazom i smeštanje rezultata u promenljivu
$rezultat = mysqli_query( $db, $upit );
// oslobađanje skupa rezultata
mysqli_free_result( $rezultati );
// zatvaranje konekcije
mysqli_close($db );
?>
PHP i MySQL
Jedinica: 19 od 19
Rezime
PHP obezbeđuje podršku za Open Database Connectivity (ODBC) i na taj način je moguće da PHP program
pristupi bilo kojoj bazi podataka koja podržava ODBC.
odbc_connect(dsn/dsn-less connection string, username, password) – funkcija koja se koristi za uspostavljanje
konekcije sa bazom
odbc_exec(connection_id, SQL query_string) – ova funkcija se koristi za izvršavanje SQL naredbi
odbc_fetch_array(recordset name) – korsti se za smeštanje skupa slogova u asocijativni niz.
odbc_num_rows(recordset name) – vraća broj slogova koji se nalaze u rezultujućem setu
odbc_close(connection_id) – zatvara konekciju
U ovoj lekciji ćete imati prilike da naučite sa kojim sve bazama i na koji način možete raditi u PHP jeziku.
PHP i ODBC
PHP obezbeđuje podršku za Open Database Connectivity (ODBC). Na taj način je moguće da PHP program pristupi
bilo kojoj bazi podataka koja podržava ODBC, kao što su Oracle, DB2, MS SQL Server ili MS Access. PHP
obezbeđuje metode koji mogu da pristupe bazi na osnovu njenog DSN-a, ali i da ostvare tzv. DSN-less konekcije. Ovaj
drugi vid konekcija se koristi u slučajevima kada ne postoji DSN ili on nije poznat. Na primer, u slučaju MS Access
baze.
128
Najčešće korišćene funkcije za ODBC konekcije su:
odbc_connect(dsn/dsn-less connection string, username, password) – funkcija koja se koristi za
uspostavljanje konekcije sa bazom. Ova funkcija ima tri argumenta, pri čemu prvi od njih predstavlja DSN baze ili
DSN-less string i ovaj argument je neophodan. Druga dva argumenta predstavljaju korisničko ime i šifru. Ukoliko
nije potrebno njihovo prosleđivanje bazi, moguće je jednostavno proslediti prazan string. Nakon uspostavljanja
konekcije, ova funkcija vraća identifikacioni broj konekcije koji koriste druge ODBC funkcije.
odbc_exec(connection_id, SQL query_string) – ova funkcija se koristi za izvršavanje SQL naredbi. Ukoliko
dođe do greške, funkcija vraća vrednost FALSE. Ukoliko se SQL naredba izvrši uspešno, funkcija vraća skup
slogova koji zadovoljavaju upit.
odbc_fetch_array(recordset name) – korsti se za smeštanje skupa slogova u asocijativni niz.
odbc_num_rows(recordset name) – vraća broj slogova koji se nalaze u rezultujućem setu. Ukoliko dođe do
greške vraća vrednost -1. Za naredbe INSERT, UPDATE ili DELETE, ova funkcija vraća broj slogova izmenjenih
ovim naredbama. Za naredbu SELECT ova funkcija vraća broj selektovanih slogova.
odbc_close(connection_id) – zatvara konekciju
PHP i MySQL
Najčešće korišćena baza podataka na internetu je svakako MySQL. Ovaj format baze je zbog svoje brzine, velike
pouzdanosti i jednostavnosti korišćenja za kratko vreme postao primaran kada su u pitanju internet aplikacije. PHP
obezbeđuje podršku za MySQL baze pomoću niza klasa i funkcija koje mogu biti korišćene za manipulaciju
podacima.U PHP-u je moguće rukovati bazom podataka na više načina. Najrasprostranjeniji način je upotreba
biblioteke php mysql, odnosno php mysqli, pri čemu je php mysqli unapređeni naslednik biblioteke php mysql. Treba
znati da, iako će u nastavku biti obrađena upotreba biblioteke php mysql, ona polako izlazi iz upotrebe i biva
zamenjena svojom naslednicom.
U biblioteci php mysql kompletno rukovanje bazom se obavlja proceduralno, dok se u php mysql ono može obavljati
proceduralno ili objektno.
Sledeće funkcije su najvažnije za rukovanje bazom, ako koristimo biblioteku php mysql:
mysql_connect( MySQL server name, username, password ) – otvara konekciju ka MySQL serveru
mysql_select_db( database name, connection id ) – selektuje bazu koja se nalazi na MySQL serveru
mysql_query( sql query ) – šalje upit trenutno aktivnoj bazi
mysql_fetch_array(recordset id) – vraća niz koji odgovara rezultujućem skupu slogova
mysql_num_rows( recordset ) – utvrđuje broj slogova sadržanih u rezultujućem skupu podataka dobijenog nakon
izvršavanja SELECT naredbe
mysql_affected_rows( connection ) - utvrđuje broj slogova izmenjenih naredbama INSERT, DELETE ili UPDATE
mysql_close( connection id ) – zatvara konekciju
129
Kreiranje podataka
Sve izmene i pretraživanja podataka u bazi realizuju se korišćenjem odgovarajućih SQL naredbi, koje se prosleđuju
bazi ili pomoću mysql funkcija ili pomoću odbc funkcija, u zavisnosti od formata baze koja se koristi i tipa konekcije.
U nastavku ćemo mysql serveru poslati dve naredbe. Jednu za kreiranje baze podataka, a drugu za kreiranje tabele.
Rezultat će biti kreirana baza ili tabela sa podacima.
Prvi korak je, naravno, kreiranje konekcije. To ćemo uraditi funkcijom mysql_connect ili mysqli_connect. Na primer:
$conn = mysqli_connect("localhost","root","");
Drugi korak će biti izvršavanje upita. Upit treba da kreira bazu podataka, pa će cela linija glasiti:
mysqli_query($conn,"create database first_php_test_db");
Zatim ćemo pristupiti kreiranoj bazi i u njoj napraviti jednu tabelu uz pomoć sql upita, na način veoma sličan onom iz
prethodne linije:
mysqli_select_db($conn,"first_php_test_db");
mysqli_query($conn,"create table mytable (id int primary key
auto_increment, username varchar(50))");
Nakon toga, takođe uz pomoć upita i funkcije mysqli_query, ubacujemo i neke podatke u tabelu. To će biti tri imena:
Peter, Sally i John.
mysqli_query($conn,"insert into mytable values(null,'Peter'),(null,'Sally'),(null,'John')");
Po izvršenju koda, na serveru će biti kreirana baza podataka. U nastavku sledi kompletan kod (ne zaboravite da nakon
izvršenja komentarišete sve linije koje se tiču kreiranja baze podataka i tabela, kako se ne bi svaki put iznova
izvršavale i pokušavale da kreiraju postojeće objekte u bazi):
$conn = mysqli_connect("localhost","root","");
mysqli_query($conn,"create database first_php_test_db");
mysqli_select_db($conn,"first_php_test_db");
mysqli_query($conn,"create table mytable (id int primary key auto_increment, username varchar(50))");
mysqli_query($conn,"insert into mytable values(null,'Peter'),(null,'Sally'),(null,'John')");
mysqli_close($conn);
130
while($rw=mysqli_fetch_row($r))
echo "id: " . $rw[0] . ", username: " . $rw[1] . "<br />";
U praksi, upotreba baze podataka će biti znatno kompleksnija i uključivaće svakako i upotrebu podataka iz formi. Iako
će u pozadini i dalje kompletan koncept počivati na gorepomenutim pravilima.
Primer koji sledi predstavlja stranu neke kompanije na kojoj se nalazi forma za pretraživanje podataka o zaposlenima:
Napomena: Primer sadrži više delova neobrađenih u gradivu i zahteva postojanje odgovarajuće baze podataka, pa ga
nije potrebno raditi, već samo analizirati njegovu strukturu.
DirectorySearch.php
<?php
if ($_POST['submit'] == "Search")
{
//Preuzima kriterijum za pretragu sa forme
$string = $_POST[ 'SearchName' ];
//Selektuje bazu
$db = mysql_select_db('Membership', $conn);
<div>
<?php
if($_POST['submit'] == "Search")
{
//Preuzima podatke iz baze i smešta ih u niz
//a zatim ih ispisuje na strani
while($row = mysql_fetch_array($rs))
{
echo "Ime: " .$row['FName'] . " ";
echo $row['LName'] . "<br/>";
echo "Telefon: " . $row['Telephone'] . "<br/>";
echo "Email: " . $row['Email'] . "<br/>";
}
//Ukoliko ne postoji osoba sa trazenim prezimenom, ispisuje se poruka
if (mysql_num_rows($rs) == 0)
{
echo "No records found!";
}
mysql_close($conn);
}
?>
</div>
</body>
</html>
Ova strana sadrži dva PHP bloka koda. Prvi blok se izvršava kada je pritisnuto dugme "Search". Prezime uneto od
strane korisnika se dodeljuje promenljivoj '$string'. Zatim se uspostavlja konekcija sa bazom i prosleđuje joj se SQL
naredba koja u bazi selektuje sve slogove koji zadovoljavaju uneti uslov, tj. sve zaposlene koji imaju zadato prezime.
Ukoliko postoje, rezultujući slogovi se dodeljuju promenljivoj '$rs'.
Drugi blok se pojavljuje unutar XHTML sekcije dokumenta. Na taj način se sav tekst koji se ispisuje pomoću echo
naredbi formatira isto kao i ostali tekst unutar strane. Ovaj blok koda ispisuje podatke u slogovima koji su selektovani
pomoću SQL naredbe. Prvo se pomoću if naredbe utvrđuje da li postoje podaci u $_POST nizu, tj. da li je barem
jednom pritisnuto dugme za pretragu. Ukoliko nije, promenljiva $rs neće sadržati podatke, pa će
naredba mysql_fetch_array($rs) dovesti do greške.
Zatim se pomoću while petlje prolazi kroz slogove. Narebda mysql_fetch_array($rs) kreira asocijativni niz (ovde nazvan
$row) koji sadrži podatke iz pojedinačnog sloga. Ovi podaci se unutar petlje ispisuju na strani.
Na sličan način se vrši i brisanje, dodavanje ili izmena nekog sloga, s tim što se u tom slučaju koriste odgovarajuće
SQL naredbe: DELETE, INSERT i UPDATE.
132
Sada ćemo pogledati samo ovlašćenja koja su dodeljena običnim korisnicima:
ALTER Baze podataka, Dozvoljava korisnicima da menjaju strukturu postojećihtabela kao sto je na primer
tabele dodavanje kolona, menjanje imena kolona ili tabelaili tipove podataka u tabeli.
Većina ovlašćenaj za obične korisnike uglavnom ne mogu narušiti bezbednost sistema. Ovlašćenje ALTER je jedino
koje može da se zloupotrebi, na primer, ukoliko korisnik promeni ime tabelama, ali, sa druge strane, ova naredba je i
neophodna jer u svakodnevnom radu neizostavno je pravljenje grešaka pri kucanju i ovom naredbom takvi propusti se
lako mogu rešiti.
Vežba 1
Problem:
Uz pomoć PHP MySQL-a potrebno je kreirati bazu podataka test_db i u njoj tabelu users, koja sadrži tri polja: id,
username i password.
Rešenje:
<?php
$conn = mysqli_connect( "localhost", "root", "" );
mysqli_query( $conn, "create database test_db" );
mysqli_select_db( $conn, "test_db" );
mysqli_query($conn, "create table users (userid int primary key auto_increment, username varchar(256),
password varchar(256))");
mysqli_close( $conn );
?>
133
Vežba 2
Problem:
Dat je sledeći niz:
$users = array(array("petar", "123"), array("jovan", "456"), array("petar", "789"));
Potrebno je korisnike iz niza smestiti u bazu test_db, tabelu users, tako da svaki prvi član svakog podniza bude
username polje, a svaki drugi član password.
Rešenje 1:
<?php
$conn = mysqli_connect("localhost", "root", "");
mysqli_select_db($conn,"test_db");
$users = array(array("petar", "123"), array("jovan", "456"), array("petar", "789"));
foreach($users as $user)
mysqli_query($conn,"insert into users (username, password) values ('{$user[0]}', '{$user[1]}')");
mysqli_close($conn);
?>
Rešenje 2:
<?php
$conn = mysqli_connect("localhost", "root", "");
mysqli_select_db($conn,"test_db");
$users = array(array("petar", "123"), array("jovan", "456"), array("petar", "789"));
$usersForQuery = "";
foreach($users as $user)
$usersForQuery.="('{$user[0]}', '{$user[1]}'),";
if(substr( $usersForQuery, strlen($usersForQuery) - 1) == ",")
$usersForQuery = substr($usersForQuery,0,strlen($usersForQuery)-1);
mysqli_query($conn,"insert into users (username, password) values $usersForQuery");
mysqli_close($conn);
?>
Vežba 3
Problem:
Potrebno je izvršiti validaciju korisnika iz baze, na osnovu korisničkog imena i šifre, koji se nalaze u promenljivima:
$username = "jovan";
$password = "4567";
Rešenje:
<?php
$username = "jovan";
$password = "456";
$conn = mysqli_connect("localhost", "root", "");
mysqli_select_db($conn,"test_db");
$r = mysqli_query($conn,"select * from users where username = '$username' and password = '$password'");
if(mysqli_num_rows($r) == 1)
echo "valid";
else
echo "invalid";
mysqli_close($conn);
?>
134
Napomena: Ovo rešenje je u potpunosti nebezbedno, jer je na njemu vrlo lako izvršiti sql injection i dobiti validan
rezultat u svakom trenutku. Za primer, pokušajte da izmenite promenljivu $username, tako da glasi ovako:
$username="jovan ' -- ";
Nakon ovoga, svaka šifra uneta u promenljivu $password rezultiraće validnim rezultatom (odnosno, u praksi, uspešnim
logovanjem na sistem). Zbog toga je obavezno izvršiti što bolju validaciju ulaza i, po mogućstvu, sanaciju. U ovom
slučaju, sledeće dve linije dovoljne su da obezbede sistem od pomenutog napada:
$username=trim($username);
$username=str_replace("'","",$username);
Vežba 4
Problem:
Potrebno je svim poljima u bazi test_db, tabela users, čija je šifra dužine tri karaktera, dodati ta tri ista karaktera na
postojeću šifru (ako je šifra abc, nova šifra treba da bude abcabc i sl.)
Rešenje 1:
<?php
$conn = mysqli_connect("localhost", "root", "");
mysqli_select_db($conn,"test_db");
$r = mysqli_query($conn,"SELECT * FROM users WHERE length(password) = 3");
$brojRedova = mysqli_num_rows($conn,$r);
for($i = 0; $i < $brojRedova; $i++ )
{
$uid = mysqli_result($r, $i, "userid");
mysqli_query($conn,"update users set password = concat(password,password) where userid = $uid");
}
mysqli_close($conn);
?>
Rešenje 2:
Prethodni primer, osim za vežbanje, nije naročito funkcionalan. I isti problem može se rešiti jednim boljim SQL upitom:
<?php
$conn = mysqli_connect("localhost", "root", "");
mysqli_select_db($conn,"test_db");
$r = mysqli_query($conn,"update users set password=concat(password, password) where length(password) = 3");
mysqli_close($conn);
?>
Vežba 5
Problem:
Potrebno je napraviti funkciju koja na osnovu upita vraća dvodimenzionalni niz iz baze.
Potrebno je testirati napravljenu funkciju na tabeli users.
135
Rešenje:
<?php
function arrayFromDb($query)
{
mysqli_connect("localhost", "root", "");
mysqli_select_db($conn,"test_db");
$r = mysqli_query($conn,$query);
$resArray = array();
while($tmpArr = mysql_fetch_row($r))
$resArray[] = $tmpArr;
return $resArray;
}
$users = arrayFromDb("select * from users");
foreach($users as $user)
echo "id: " . $user[0] . ", name: " . $user[1] . ", password: " . $user[2] . "<br>";
?>
Vežba 6
Potrebno je napraviti funkciju koja na osnovu upita prosleđenog kao parametar vraća numeričku vrednost.
Funkciju treba testirati na tabeli users.
Rešenje:
<?php
function scalar($query)
{
mysqli_connect("localhost", "root", "");
mysqli_select_db($conn,"test_db");
$r = mysqli_query($conn,$query);
if(mysqli_num_rows($r) == 1)
{
$value = mysqli_fetch_row($r);
return (int)$value[0];
}
else
return "";
}
echo scalar("select count(userid) from users");
?>
136