Objektno orijentirano programiranje

b0ne^
/srv/http/Posts: 22Administrator in PHP

OOP by b0ne^

[ Sadrzaj ]
[0] Uvod
[1] Klase i objekti
[2] Ogranicavanje pristupa osobinama i metodima
[3] Konstante
[4] Inicijalizacija objekata pomocu konstruktora
[5] Zasnivanje jedne klase na drugoj i preklapanje metoda
[6] Povezivanje sa bazom(PDO)

1) Uvod
Posto sam video da na forumu nema tema vezane za PHP OOP, osim teme od EKV-a koja nije zavrsena, odlucio sam da napravim svoju. OOP je skraceno od Objektno-orijentisano programiranje. OOP je nastalo radi rukovanja velikim programima. Funkcije u PHP-u omogucavaju da podelite skriptu na manje delove kako bi kod bio razumljiviji i sa sto manje ponavljanja koda(veoma korisno ako cemo neku funkciju pokretati vise puta). OOP "ide korak dalje" i omogucava da i funkcije i osobine stavite u objekte. Objekat moze da sadrzi grupu funkcija i osobine koje su tim funkcijama potrebne. Na primer sta se nalazi sve u unutrasnjosti frizidera? Imamo pumpu, termostat i ventilator i sve to radi zajedno. Ako morate da svim tim rukujete rucno, moze doci do katastrofe. Sa druge strane, ako sve to stavite u pogodan objekat, frizider, sve sto treba da upamtite je da se u frizideru hladi hrana. Na isti nacin izdvajanje funkcija i podataka na jedno mesto omogucava da se podele dugacke skripte. Jedan objekat bi, na primer, mogao da rukuje prikazivanjem na ekranu, drugi da proverava podatke, a treci da radi sa bazom podataka.

1) Klase i objekti
Za pocetak bi trebalo da napravimo nasu klasu u kojoj ce se nalaziti funkcije i osobine. To cemo uraditi funkcijom class.

[code2=php]<?php
    class nasaKlasa
    {
        /* Funkcije i osobine */
    }
?>[/code2]
U nasu klasu mozemo dodati i neke funkcije koje se nazivaju metodi.
[code2=php]<?php
    class nasaKlasa
    {
        function nasaFunkcija()
        {
            /* Dalji kod funkcije */
        }
    }
?>[/code2]

Podatke koje hocemo da definisemo u nasoj klasi obicno definisemo na pocetku. Prilikom definisanja osobina mozete da im dodelite konstantne vrednosti, ali ne mozete da dodelite bilo koju vrednost.
[code2=php]<?php class nasaKlasa { var $foo = "bar"; // Vrednost je ok /* var $foo = "b"."a"."r"; */ // Vrednost nije ok i izazvace gresku function nasaFunkcija() { /* Dalji kod funkcije */ } } ?>[/code2]

Ovo je bilo definisanje klasa, osobina i funkcija. Sada cu vam pokazati kako da preko funkcije ispisete neku osobinu i kako da pokrenemo nasu klasu. Da bismo pokrenuli nasu klasu koristimo funkciju new.
[code2=php]<?php class nasaKlasa { /* Funkcije i osobine */ } $nasaKlasa = new nasaKlasa(); ?>[/code2]
Sada kada smo varijablom $nasaKlasa pokrenuli nasu klasu tu varijablu mozemo koristiti za pokretanje funkcija i ispisivanje osobina. Varijabla $nasaKlasa moze biti nazvana kako god mi zelimo ali je vaznan deo [b]new nasaKlasa();[/b]. nasaKlasa() je ime nase klase a razlog zasto ovde dodajemo () a kod definisanja klase ne je zato da bismo mogli da zadamo neke parametre klasi, o tome cemo posle. Da bismo pokrenuli nasu funkciju koristimo operator ->. To bi ovako izgledalo.
[code2=php]<?php class nasaKlasa { function nasaFunkcija() { echo "Funkcija je pokrenuta!"; } } $nasaKlasa = new nasaKlasa(); $nasaKlasa->nasaFunkcija(); ?>[/code2]
Kada izvrsimo ovaj kod na stranici cemo dobiti ispis:
[code]
Funkcija je pokrenuta!

Ovim vidimo da je pokretanje nase funkcije uspelo. Sada kada bismo zeleli da pomocu funkcije ispisemo neku osobinu koju smo zadali moracemo da koristimo built-in varijablu $this i pomocu operatora -> cemo pristupiti varijabli koju smo zadali kao osobinu. To bi izgledalo ovako.
[code2=php]<?php class nasaKlasa { var $foo = "bar"; function nasaFunkcija() { echo "Pristupanje varijabli \$foo. Vrednost varijable \$foo je: ".$this->foo; } } $nasaKlasa = new nasaKlasa(); $nasaKlasa->nasaFunkcija(); ?>[/code2]
Kada izvrsimo ovaj kod na stranici cemo dobiti ispis:
[code]
Pristupanje varijabli $foo. Vrednost varijable $foo je: bar

Da bismo ispisali vrednost varijable $foo nije nam potrebna funkcija, to smo mogli da uradimo i na laksi nacin direktnim pristupanjem varijable $foo.
[code2=php]<?php class nasaKlasa { var $foo = "bar"; } $nasaKlasa = new nasaKlasa(); echo "Pristupanje varijabli \$foo. Vrednost varijable \$foo je: ".$nasaKlasa->foo; ?>[/code2]

Sada cemo napraviti jednu skriptu preko koje ce korisnik zadati ime a skripta ce ga ispisati.
[code2=php]<?php class nasaKlasa { var $ime; function zadajIme($ime) { $this->ime = htmlspecialchars($ime, ENT_QUOTES); } function ispisiIme() { echo $this->ime; } } $nasaKlasa = new nasaKlasa(); $nasaKlasa->zadajIme("b0ne^"); $nasaKlasa->ispisiIme(); ?>[/code2]
Kada izvrsimo ovaj kod na stranici cemo dobiti ispis:

b0ne^

Opet kazem, ovo je moglo da se uradi na laksi nacin direktnim pristupanjem varijable $ime ali ovo su samo primeri kako biste shvatili nacin rada i kako biste naucili OOP i sto bolje ga razumeli.

2) Ogranicavanje pristupa osobinama i metodima
Osobinama i metodima objekta podrazumevno mozete da pristupite. Ponekad to i nije dobra ideja. Imamo 3 modifikatora pristupa koji postoje u PHP-u:
1. public - Znaci "dostupno svima"
2. private - Znaci "dostupno u okviru iste klase"
3. protected - Znaci "dostupno u istoj klasi i klasama koje su izvedene iz te klase(extends), vise o tome kasnije"

Kada funkciji ili osobini ne zadamo ni jedan modifikator on ce po default-u biti public. Sada kada bismo predhodni kod napisali isto samo sto bismo dodali neki od modifikatora, public na primer, to bi izgledalo ovako.
[code2=php]<?php class nasaKlasa { public $ime; public function zadajIme($ime) { $this->ime = htmlspecialchars($ime, ENT_QUOTES); } public function ispisiIme() { echo $this->ime; } } $nasaKlasa = new nasaKlasa(); $nasaKlasa->zadajIme("b0ne^"); $nasaKlasa->ispisiIme(); ?>[/code2]
Zamenili smo var sa public i pre najave funkcije(function) dodali smo public. To znaci da mozemo da pokrenemo funkciju van klase i da mozemo da pristupimo varijabli $ime van klase. Sta ako sada zelimo da stavimo da osobina $ime moze da se koristi samo unutar klase. Umesto public stavicemo private. Kod ce sada izgledati ovako.
[code2=php]<?php class nasaKlasa { private $ime; public function zadajIme($ime) { $this->ime = htmlspecialchars($ime, ENT_QUOTES); } public function ispisiIme() { echo $this->ime; } } $nasaKlasa = new nasaKlasa(); $nasaKlasa->zadajIme("b0ne^"); $nasaKlasa->ispisiIme(); ?>[/code2]
Na stranici cemo idalje dobiti ispis zadatog imena, u nasem slucaju b0ne^. Zasto? Zato sto mi ne pristupamo varijabli $ime van klase nego je ispisujemo uz pomoc funkcije ispisiIme koja se nalazi unutar klase. Kada bismo probali da ispisemo $ime direktnim pristupom dobili bismo gresku. Kod sa takvom greskom bi izgledao ovako.
[code2=php]<?php class nasaKlasa { private $ime; public function zadajIme($ime) { $this->ime = htmlspecialchars($ime, ENT_QUOTES); } } $nasaKlasa = new nasaKlasa(); $nasaKlasa->zadajIme("b0ne^"); echo $nasaKlasa->ime; ?>[/code2]
Greska koju cemo dobiti je sledeca.

( ! ) Fatal error: Cannot access private property nasaKlasa::$ime in C:\wamp\www\index.php on       line 12
Call Stack
#   Time    Memory  Function    Location
1   0.0005  367144  {main}( )   ..\index.php:0

Isto kao i osobine i funkcije mogu biti privatne.
[code2=php]<?php class nasaKlasa { private $ime; public function zadajIme($ime) { $this->ime = htmlspecialchars($ime, ENT_QUOTES); } private function ispisiIme() { echo $this->ime; } } $nasaKlasa = new nasaKlasa(); $nasaKlasa->zadajIme("b0ne^"); $nasaKlasa->ispisiIme(); ?>[/code2]
Kod ce izazvati gresku zato sto pokusavamo da pokrenemo funkciju ispisiIme() van klase.

( ! ) Fatal error: Call to private method nasaKlasa::ispisiIme() from context '' in C:\wamp\www\index.php on line 16
Call Stack
#   Time    Memory  Function    Location
1   0.0075  368192  {main}( )   ..\index.php:0

3) Konstante
Ovo ce biti kratko poglavlje. Osim varijabli u klasama mozemo da koristimo i konstante koje se zadaju funkcjom const. Kao sto samo ime kaze one su konstante i njihova vrednost se ne moze menjati. Na primer to nam moze sluziti ako hocemo da racunamo ukupnu dnevnu zaradu u odnosu na broj prodatih proizvoda. To bi izgledalo ovako.
[code2=php]<?php class izracunajZaradu { const cena = 250; public function izracunaj($kolicina) { echo $kolicina * $this::cena; } } $izracunajZaradu = new izracunajZaradu(); $izracunajZaradu->izracunaj(10); ?>[/code2]
Kod konstanti se ne koristi $ kao kod varijabli vec je cist text. Da bismo pristupili nekoj konstanti koristimo :: umesto -> sto vidimo na liniji 7(echo $kolicina * $this::cena;). Da bismo pristupili konstanti van klase isto cemo koristiti ::.
[code2=php]<?php class izracunajZaradu { const cena = 250; public function izracunaj($kolicina) { echo $kolicina * $this::cena; } } $izracunajZaradu = new izracunajZaradu(); echo "Cena jednog proizvoda je ".htmlspecialchars($izracunajZaradu::cena).", a ukupna dnevna zarada je "; $izracunajZaradu->izracunaj(10); ?>[/code2]

4) Inicijalizacija objekata pomocu konstruktora
U PHP-u je konstruktor je specijalni metod pod nazivom __construct, i uz pomoc njega mozemo zadati parametre klasi i reci skripti sta da radi prilikom pokretanja klase.
[code2=php]<?php class izracunajZaradu { const cena = 250; public function __construct($kolicina) { if(!is_numeric($kolicina)) { die("Kolicina mora biti broj!"); } $this->kolicina = $kolicina; $this->izracunaj(); } public function izracunaj() { echo "Cena jednog proizvoda je ".htmlspecialchars($this::cena).", a ukupna dnevna zarada je ".($this->kolicina * $this::cena); } } $izracunajZaradu = new izracunajZaradu(10); ?>[/code2]
Kao sto vidite, u ovom primeru smo samo pokrenuli klasu i kod $izracunajZaradu = new izracunajZaradu(10) smo zadali kolicinu da bude 10. Uz pomoc konstruktora smo zadali globalnu vrednost kolicina($this->kolicina) koju cemo koristiti da bi izracunali ukupnu cenu i zadali smo da pri pokretanu klase izvrsi funkciju izracunaj. Da smo stavili $kolicina umesto $this->kolicina mogli bi da koristimo tu varijablu samo unutar funkcije __construct posto je ona tu zadata. Ukratko receno za konstruktor, koristimo ga da bismo zadali skripti sta sve da radi pri pokretanju klase.

]5) Zasnivanje jedne klase na drugoj i preklapanje metoda
U ovom poglavlju govoricemo o dugo ocekivanom protected i extends. Cesto je korisno da jednu klasu zasnujete na drugoj. Ja cu kao primer napraviti da imamo klasu izracunajZaradu i podigniZaradu koja ce nasledjivati(extends) prvu klasu. Zasto to ovako radimo? Zato sto ne moramo uvek da podignemo zaradu, zapamtite da su ovo samo primeri i da cete u pravom slucaju to koristiti za nesto drugo. Poenta nasledjivanja jeste da u drugoj klasi, klasa koja nasledjuje prvu, imamo sve metode i osobine koje smo koristili u prvoj. Nasledjivanje klase se vrsi pomocu funkcije extends nakon koje ide ime klase koju zelimo da nasledimo. Evo koda koji cemo koristiti kao primer, namerno sam stavio da za sve sto nam treba imamo funkciju a ne da sve izvrsimo u funkciji konstruktora.
[code2=php]<?php class izracunajZaradu { const cena = 250; public function __construct($kolicina) { if(!is_numeric($kolicina)) { die("Kolicina mora biti broj!"); } $this->kolicina = $kolicina; $this->izracunaj(); } public function izracunaj() { $this->zarada = $this->kolicina * $this::cena; echo "Cena jednog proizvoda je ".htmlspecialchars($this::cena).", a ukupna dnevna zarada je ".($this->kolicina * $this::cena).".
"; } } class podigniZaradu extends izracunajZaradu { public function __construct($kolicina, $podigni) { parent::__construct($kolicina); if(!is_numeric($podigni)) { die("Kolicina zarade koju zelite da podignete mora biti broj!"); } if($podigni > $this->zarada) { die("Ne mozete podici vise para nego sto ste zaradili!"); } $this->podigni = $podigni; $this->podigniPare(); } public function podigniPare() { $this->zarada = $this->zarada - $this->podigni; echo "Podigli ste ".$this->podigni." para sa racuna i ostlao vam je ".$this->zarada."."; } } $podigniZaradu = new podigniZaradu(10, 100); ?>[/code2]
Prvu klasu ne moram da objasnjavam jer smo taj deo vec presli. I u drugoj klasi cemo imati konstruktor pa da objasnimo sta se tu desava. parent::__construct($kolicina); ce nam sluziti da posaljemo parametre konstruktoru prve klase(izracunajZaradu). Nakon toga cemo imati proveru da li je kolicina koju hocemo da podignemo veca od ukupne kolicine, gde koristimo varijablu $this->zarada koja je zadata u prvoj klasi. Nakon toga je sve ostalo jasno i sa time smo se vec susretarli.

Sta uraditi ako prilikom izvodjenja jedne klase iz druge dodjete u situaciju da u novoj klasi napravite metod koji se zove isto kao metod u osnovnoj klasi? U tom slucaju preklapate metod osnovne klase, a objekti nove klase ce, umesto metoda osnovne klase, koristiti novi metod. Ukoliko zelite da pristupite starom metodu iz prve klase koristicete operator :: uz ime klase i metoda. Znaci Ako u staroj klasi(klasa pod imenom izracunajZaradu) imate metod izracunaj() a imate ga i u nasledjenoj klasi(klasa pod imenom podigniZaradu) da biste pokrenuli metod izracunaj() iz prve klase koristicete izracunajZaradu::izracunaj();.

6) Povezivanje sa bazom(PDO)
Evo cisto jednog pravog primera da ne bude da je sve radjeno teoretski. U ovom primeru cemo napraviti konekciju sa bazom i ispisivanje i to koristeci PDO i OOP.
[code2=php]<?php class databaseConnection { public function __construct($host, $user, $password, $database, $table) { $this->connection = new PDO("mysql:host=".htmlspecialchars($host, ENT_QUOTES).";dbname=".htmlspecialchars($database, ENT_QUOTES). ";charset=UTF-8", htmlspecialchars($user, ENT_QUOTES), htmlspecialchars($password, ENT_QUOTES)); echo "Connection successfully established!"; $this->fetchContent($table); } public function fetchContent($table) { $query = $this->connection->query("SELECT COUNT(*) FROM `".htmlspecialchars($table, ENT_QUOTES)."`"); if($query->fetchColumn() > 0) { $query = $this->connection->query("SELECT * FROM `".htmlspecialchars($table, ENT_QUOTES)."`"); $row = $query->fetchAll(PDO::FETCH_ASSOC); echo "

";
                    print_r($row);
                    echo "
"; } else { echo "There are no entries in table ".htmlspecialchars($table, ENT_QUOTES); } } } $databaseConnection = new databaseConnection("localhost", "root", "", "private", "users"); ?>[/code2]
U konstruktoru smo se konektovali na bazu i rekli skripti da ako je konekcija uspela, kod PDO se odmah prekida ako konekcija ne uspe, da izlista podatke iz tabele users. Naravno da nemate svi databazu private i tabelu users ali u mom slucaju ja sam dobio sledeci ispis.
Connection successfully established!
Array
(
    [0] => Array
        (
            [id] => 1
            [username] => b0ne^
            [password] => 6b4fb497612f8de381eeb56210ab1d81
            [rank] => 0
            [register_date] => 22-December-2012 23:16
            [login_date] => 22-June-2013 16:51
        )

    [1] => Array
        (
            [id] => 3
            [username] => dr3x
            [password] => b5e3f089830aba20b076ab701b473e1f
            [rank] => 1
            [register_date] => 24-December-2012 22:12
            [login_date] => 28-May-2013 21:30
        )

    [2] => Array
        (
            [id] => 4
            [username] => xxxx
            [password] => 6100d54a121ff9aeeef96479f0c93cdc
            [rank] => 0
            [register_date] => 17-April-2013 0:10
            [login_date] => 
        )

)

Iz ovoga vidimo da je konekcija uspela i da smo dobili na stranici ispis sadrzaja tabele private. Nadam se da sam sve pokrio ovim tutorialom i da ce se naci neko kome ce pomoci.

If you don't know who I am, then maybe your best course would be to tread lightly.

Sign In or Register to comment.

Welcome

It looks like you're new here. If you want to get involved, click one of these buttons!

Discussions