Seminarski rad na praksi

Tema: CakePHP, MVC (Model – View – Controller) Juli, 2007

Mentor: Mustafa Hodžić

Student: Jasmina Šero

SADRŽAJ
Seminarski rad na praksi......................................................................................................1 SADRŽAJ............................................................................................................................2 1. Uvod.................................................................................................................................3 2. MVC (Models – Views – Controllers).............................................................................4 2.1. Model........................................................................................................................5 2.1.1. Definiranje i upit sa hasOne: .............................................................................7 2.1.2. Definiranje i upit sa belongsTo..........................................................................8 2.1.3. Definiranje i upit sa hasMany............................................................................9 2.1.4. Definiranje i upit sa hasAndBelongsToMany (HABTM)...............................11 2.2. View .......................................................................................................................20 2.3. Controller................................................................................................................23 2.3.2. Controller callback...........................................................................................27 Možemo kreirati callback u našem aplikacijskom Model-u ili Controller file-u. U ovom primjeru šaljemo email iz Model-a....................................................................................27 3. Helper.............................................................................................................................28 3.1. HTML Helper........................................................................................................28 3.2. TimeHelper............................................................................................................31 3.3. NumberHelper.........................................................................................................32 4. Scaffolding.....................................................................................................................34 5. Data Validation .............................................................................................................35 6. Components...................................................................................................................37 7. Servis “Anketa”.............................................................................................................39 7.1. Tabele servisa..........................................................................................................39 7.2. MVC servisa...........................................................................................................41 7.2.1. Model ..............................................................................................................41 7.2.2. View.................................................................................................................42 7.2.3. Controller.........................................................................................................46 7. 3. Upustvo za servis..................................................................................................52 ZAKLJUČAK....................................................................................................................59 LITERATURA..................................................................................................................60

2

1. Uvod
CakePHP je open source web aplikacijski framework napisan za PHP, distribuiran od MIT license. Razvoj Cake-a počinje u 2005-oj godini od tada je nastalo nekoliko projekata i još uvijek se radi na razvoju novih. CakePHP je dobro dokumentovan framework, inspiriran konceptom predstavljenim u RoR-u (Ruby on Rails), koji može biti primjenjen u PHP4 – PHP5. Cake olakšava komunikaciju user interface-a sa bazom podataka, brz je, koristi MVC ( Model – View – Controller ) arhitekturu, te time forsira objektno i uredno programiranje. Ima podršku za cashe, ajax, RSS Helper, a uskoro bi trebao dobiti još “masu” stvari. Kod testiranja i debagiranja aplikacije bilo koji developer koji primjenjuje CakePHP strukturu će biti sposoban da locira i ispravi grešku bez znanja svih detalja o kodu. Neke osobine CakePHP- a: Kompatibilan je sa PHP4 i PHP5 Fleksibalan View Cashing Application Scaffolding Access Control List View Helpers za AJAX, Javascript, HTML forme,... Radi iz bilo kojeg website poddirektorija Brz, fleksibilan template (PHP sintaksa sa Helper metodama) Ugrađena validacija Website directory nezavisan View caching

Da bi koristili CakePHP moramo imati HTTP sever (wamp, apache), PHP 4 ili 5, database engine (MaSQL, PostgreSQL). Instalacija Cake-a: downloadujemo jednu od verzija CakePHP-a (www.cakephp.org, www.forgephp.org ). Otpakujemo folder i snimimo na web server u webroot direktorij ( wamp, apache,…npr. C:\wamp\www), zatim učitamo stranicu kao localhost u web browser-u. Indexnu stranu podešavamo u /app/config/routes.php file-u, detalje o podešavanju i instalaciji CakePHP-a možemo naći u CakePHP Manual dokumentu, (www.cakephp.org ).

3

funkcije ovih entiteta (Controllers). u kompleksnim kompjuterskim aplikacijama koje predstavljaju dugi niz korisničkih podataka. View i Controller.2. a View generira HTTP odgovor. a controller je kod koji skuplja dinamičke podatke i generira sadržaj sa HTML-om. Svi naši entiteti (Models). kao što možemo vidjeti na sljedećoj slici Input -> Processing -> Output Controller -> Model -> View 4 . Developeri često žele odvojiti podatke (model) od korisničkog interfejsa (view).… Controller i View zavise od Model-a. uključujući komponentu controller. MVC često vidimo u web aplikacijama. tako da mijenjaju korisnički interfejs koji ne daje podatke i podaci mogu biti reorganizovani bez mijenjanja interfejsa. MVC rješava ovaj problem odvajanjem pristupa podacima od biznis logike iz prezentacijskih podataka i korisničkog interfejsa. koji je obićno smješten u bazu podataka ili XML fajl. zato što zahtijevaju podatke iz Model-a. gdje je view ustvari HTML stranica. bilo koji input dolazi preko Controllera. koja postoji kao veza između tri objekta: Model. MVC (Models – Views – Controllers) MVC je arhitekturalni patern koji se koristi u softverskom inžinjeringu. Model je predstavljen stvarnim sadržajem. Controller prima svaki HTTP zahtijev. koji zatim odabire View za prikaz rezultata tj. MVC je software dizajn patern koji pomaže u logičkom odvajanju koda. tako da nećemo mijenjati Contoller ako želimo promijeniti izgled nekog input polja. to je kao konceptualna paradigma. korisnički interfejs (Views) smješteni su u odvojenim fajlovima.

views (pogledi) i kontroleri nalaze se u predefinisanom direktoriju sa CakePHP– ovom direktori strukturom.- Model enkapsulira aplikacijeske podatke.1. kao što se može vidjeti u sljedećem primjeru: • app/ o o o o o o o o config/ controllers/ models/ plugins/ tmp/ vendors/ views/ webroot/ • cake/ config/ docs/ libs/ vendors/ o o o • 2. prima ulaze (zahtijeve) i prevodi ih za Model i View Modeli. Model 5 . aplikacijski flow i business logic View ekstraktuje podatke iz Modela i formatira ih za prezentaciju Controller pristupa aplikacijskom flow.

Primjer: Answer model se treba snimiti u app/models/answer.hasOne . 6 . } ?> Domain Model je layer objekt koji apstraktnu logiku. ako imamo tabelu “answers”.belongsTo . nema nikakve prezentacijske osobine i nikakvu odgovornost prema HTTP zahtijevima. odvaja prezentacijku logiku od aplikacijske. trebamo imati i model “Answer”. jer scaffolding pronalazi i koristi asocijacije između modela. starni ključ u “authors” tabeli bi trabao biti “post_id”. ako želimo snimiti informacije o blog postu i autorima. Cake automatski povezuje modele.Ime modela: [ime tabele u jednini]. . ponaša se kao primarni drajver u aplikaciji. ime modela za tabelu “posts” je “Post”. s tim da je ime tabele u množini. imena tabela trebaju biti “posts” i “authors”. ime modela i ime tabele: . sadrži aplikacijske podatke i logiku.tj. a ime modela za tabelu ”authors” je “Author”. podatke i probleme aplikacije odvaja. Jedna od najmočniji osobina CakePHP je veza između modela. CakePHP konvencija imenovanja odnosi se na foreign (strani) ključ. Postoje četiri tipa veza: . npr.php <?php class Answer extends AppModel { var $name = 'Answer'.Rich Domain Model uključuje kompleksne web objekte i mnoge dizajn paterne Koji model ćemo koristiti zavisi od konteksta aplikacije. npr. Za korektno korištenje asocijacije najbolje je slijediti CakePHP konvenciju imenovanja.Foreign (strani) ključ: [ime modela u jednini]_id. . Ukoliko koristimo CakePHP konvenciju imenovanja.Ime tabele: [ime objekta u množini]. Naravno. možemo koristiti scaffolding da predstavimo sebi aplikacijske podatke.Model je objekt MVC arhitekture.Simple Domain Model ima one – to – one odgovornost između business objekata i tabela u bazi podataka . možemo uvijek podesiti model asocijacije da rade bez CakePHP konvencije imenovanja.hasAndBelongsToMany Kada je veza između modela definisana.hasMany . Omogućava pristup bazi podataka i tabelama u bazi. Po defaultnu imena modela su u jednini i imaju ime isto kao i tabela u bazi. strani ključ u “authors” tabeli za povezivanje sa Post modelom koristi asocijaciju Authors belongs to. Može se klasificirati u dvije kategorije: . npr.

1. npr. 'order' => ''. 'dependent' => true. publisher_id.header_color = ’green’ ”. Primjer: Ako želimo kreirati jednostavni user menađment sistem za blog. postavimo vrijednost ključa koristeći SQL redoslijed: “Pofile. npr. prva Author. Scaffolding očekuje asocijacije u istom poretku kao što su ključevi u tabeli. 'foreignKey' => 'user_id' ) ). svaki user ima jedinstven profil što omogućava asocijaciju hasOne (User hasOne Profile). Međutim user-i mogu dodavati i komentare pa imamo asocijaciju hasMany (User hasMany Comments). ako želimo specifirati “Profile” ime klase modela uslovi: SQL fragmenti stanja (uslova) koji definišu taj odnos. 2.1. Trebamo i tri ključa: author_id.name ASC” 7 - . order: redoslije asocijacija modela. editor_id. druga Editor i posljednja Publisher. tako da imamo asocijaciju hasAndBelongToMany (Post hasAndBelongToMany Tags). } ?> Varijablu $hasOne Cake koristi za pravljenje asocijacije između User i Profile modela. 'conditions' => ''. Editor i Publisher. ako želimo veze modela u specifičnom redoslijedu. Definiranje i upit sa hasOne: <?php class User extends AppModel { var $name = 'User'. Svaki ključ u nizu dozvoljava nam dalju konfiguraciju asocijacije: className: ime klase modela koji želimo povezati . Kada želimo da user sistem radi dozvolit ćemo Posts koji će biti povezan sa Tag objektima. tako ako imamo Article koji belongsTo (pripada) modelima: Author. var $hasOne = array('Profile' => array('className' => 'Profile'. da definišemo ovakav uslov treba specifirati SQL uslov: “Profile. Možemo koristiti ovo da kežemo Caku-u da samo poveže Profile koji ima green header.CakePHP scaffolding očekuje asocijacije u istom poretku kao i kolona.

putanja : /app/models/profile.1. Definiranje i upit sa belongsTo Međutim User može zahtijevati da vidi Profil. print_r($user). 'conditions' => ''. primjer. '25'). to ćemo omogućiti pomoću asocijacije belongsTo koju kreiramo u modelu Profil. pridruženi model je uništen kada je uništen predhodni forgeinKey: ime stranog ključa koji povezuje odgovarajući model $user = $this->User->read(null.- zavisnost: ukoliko je podešena na true.2. //output: Array ( [User] => Array ( [id] => 25 [first_name] => John [last_name] => Anderson [username] => psychic [password] => c4k3roxx ) Kada izvršimo find() ili findAll() poziva korišteni Profile model. var $belongsTo = array('User' => array('className' => 'User'. trebali bi vidjeti asocijaciju User modela. 'order' => ''. 'foreignKey' => 'user_id' ) ). } ?> 8 .php <?php class Profile extends AppModel { var $name = 'Profile'. kao što je: [Profile] => Array ( [id] => 4 [name] => Cool Blue [header_color] => aquamarine [user_id] = 25 ) ) 2.

Kada izvršimo find() ili findAll() poziv Profil modela. 'conditions' => 'Comment.$belongsTo niz Cake koristi da poveže modele Profil i User. 'finderQuery' => '' ) ). 9 . 'dependent' => true. //output: Array ( [Profile] => Array ( [id] => 4 [name] => Cool Blue [header_color] => aquamarine [user_id] = 25 ) [User] => Array ( [id] => 25 [first_name] => John [last_name] => Anderson [username] => psychic [password] => c4k3roxx ) ) 2. Definiranje i upit sa hasMany Sada kada su User i Profile model povezani i rade. var $hasMany = array('Comment' => array('className' => 'Comment'. '4').created DESC'. 'exclusive' => false. treba napraviti sistem da User arhivu poveže sa Comment arhivom. 'foreignKey' => 'user_id'.3. U User model trebamo dodati: <?php class User extends AppModel { var $name = 'User'.1. trebali bi vidjeti pridruženi User model kao što je: $profile = $this->Profile->read(null.moderated = 1'. 'limit' => '5'. print_r($profile). 'order' => 'Comment.

exclusive: ako je posatvljeno na true.limit (ograničenje). ovo je dobar način za kompleksne asocijacije koje ovise o više tabela Kada izvršimo find() ili findAll() poziv User modela. “Comment. svi povezani objekti će biti obrisani u jednoj SQL izjavi bez da se beforeDelete callback pokrene .foreignKey: ime stranog ključa koji povezuje pridruženi model . '25'). //output: Array ( [User] => Array ( [id] => 25 [first_name] => John [last_name] => Anderson [username] => psychic [password] => c4k3roxx ) [Profile] => Array ( [id] => 4 [name] => Cool Blue [header_color] => aquamarine [user_id] = 25 ) 10 . Svaki ključ u nizu dozvoljava dalju konfiguraciju veze: .maksimalan broj veza modela.className: ime modela koji želimo povezati . Možemo koristiti uslov da kažemo Cake-u da poveže samo Comment koji je ograničen.created DESC” . print_r($user). kao što je: $user = $this->User->read(null.uslovi: SQL fragmenti stanja (uslova) koji definišu taj odnos. postavimo vrijednost ključa da koristi SQL redoslijed. u ovom primjeru nismo htjeli sve komentare.finderQuery: specifikacija kompletne SQL izjave za dohvat veze. “Comment. ako želimo povezati modele u određeni redoslijed. koji želimo da nam Cake dohvati. npr. već samo 5 .redoslijed: redoslijed povezani modela. npr.Cake koristi $hasMany niz da napravi vezu User i Comment modela. trebali bi vidjeti povezane Comment modele.modereted = 1” .

tako da oba modela mogu vidjeti jedan drugi. Razlika između hasMany I hasAndBelongsToMany je ta što sa hasMany. ) ) ) Dobra ideja je definirati “Comment belongsTo User” asocijaciju. Ne definiranje asocijacija iz oba modela je često uobičajna greška kada pokušamo koristiti scaffolding. asocijacija 11 .koristan je kad imamo dva modela koja su povezana zajedno sa pridruženim tabelama. ) [2] => Array ( [id] => 269 [user_id] => 25 [body] => The hasMany assocation is really. ali je takođe i najviše korišten. ) [4] => Array ( [id] => 286 [user_id] => 25 [body] => The hasMany assocation is super nice to have.4.[Comment] => Array ( [0] => Array ( [id] => 247 [user_id] => 25 [body] => The hasMany assocation is nice to have. ) [3] => Array ( [id] => 285 [user_id] => 25 [body] => The hasMany assocation is extremely nice to have. 2. ) [1] => Array ( [id] => 256 [user_id] => 25 [body] => The hasMany assocation is really nice to have. Definiranje i upit sa hasAndBelongsToMany (HABTM) HasAndBelongsToMany je najteži za “pravljenje”.1. Pridružene tabele sadrže individualne redove koji su povezani jedan sa drugim. really nice to have.

Categories i Articles: articles_categories HABTM da poveže tabele treba najmanje dva strana ključa modela koji su povezani. sa HABTM. -. `tag` varchar(100) default NULL. Primjer Posts HABTM Tags: --. asocijacije modela su dijeljene. -. `user_id` int(10) default NULL. `tag_id` int(10) unsigned NOT NULL default '0'. `created` datetime default NULL. samo je user povezan sa komentarima.modela nije dijeljena (shared). Ako imamo User hasMany Comments. Za naš primjer to su “post_id” i “tag_id”. `body` text.Table structure for table `posts_tags` -CREATE TABLE `posts_tags` ( `post_id` int(10) unsigned NOT NULL default '0'. PRIMARY KEY (`id`) ) TYPE=MyISAM.---------------------------------------------------------. `modified` datetime default NULL.`tag_id`) ) TYPE=MyISAM. 12 . `status` tinyint(1) NOT NULL default '0'. `title` varchar(50) default NULL.Posts i Tags: posts_tag . HABTM pridružene tabele.Table structure for table `tags` -CREATE TABLE `tags` ( `id` int(10) unsigned NOT NULL auto_increment. jednostavni modeli i pridružena im imena tabela: . PRIMARY KEY (`id`) ) TYPE=MyISAM.Table structure for table `posts` -- CREATE TABLE `posts` ( `id` int(10) unsigned NOT NULL auto_increment.---------------------------------------------------------.Monkeys i IceCubes: ice_cubes_monkeys . PRIMARY KEY (`post_id`.

'uniq' => true. 'deleteQuery' => ''. 'foreignKey' => 'post_id'. ) ). 'associationForeignKey'=> 'tag_id'. 'finderQuery' => ''. 'limit' => ''. 'conditions' => ''. [created] => 2006-04-15 09:33:24 [modified] => 2006-04-15 09:33:24 [status] => 1 ) [Tag] => Array ( [0] => Array ( [id] => 247 [tag] => CakePHP ) 13 . var $hasAndBelongsToMany = array('Tag' => array('className' => 'Tag'. //output: Array ( [Post] => Array ( [id] => 2 [user_id] => 25 [title] => Cake Model Associations [body] => Time saving. '2'). 'order' => ''.Sa ovim tabelama definišemo asocijaciju u Post modelu: /app/models/post. easy. Kada izvršimo find() ili findAll() poziv Post modela. 'joinTable' => 'posts_tags'. print_r($post).php hasAndBelongsToMany <?php class Post extends AppModel { var $name = 'Post'. trebali bi vidjeti pridruženi Tag model kao što je: $post = $this->Post->read(null. and powerful. } ?> Cake koristi $hasAndBelongsToMany niz da napravi asocijaciju između Post i Tag modela.

$this->saveField('hidden'.1. $this->saveField('hidden'. Treba da sadrži metode koje su dijeljene između dva ili više modela. '0'). } 14 . Primjer specifične metode u modelu je par metoda za hiding/unhiding post u blogu. '1'). function hide ($id=null) { if ($id) { $this->id = $id. ali ako želimo kreirati vlastitu. } } function unhide ($id=null) { if ($id) { $this->id = $id.1.php.[1] => Array ( [id] => 256 [tag] => Powerful Software ) ) ) 2.php. AppModel klasa je orginalno definisana u cake/ direktoriju. Model funkcije Modeli su klase proširene AppModel klasom. kao što vidimo u sljedećem primjeru: <?php class Post extends AppModel { var $name = 'Post'. treba je smjestiti u /app/app_model. Time ona proširuje klasu Model koja je standardna Cake biblioteka definisana u cake/libs/model.

} } ?> U sljedećem primjeru vidimo nekoliko standardni načina za dobivanje naših podataka koristeći model: findAll ($conditions thermal_detonators > 3". Vraća specifično polje iz prvog rekorda koje odgovara $conditions. $this->Author->findByLastName('Rogers'). int $recursive. $order. $fields. int $limit. $this->Property->findAllByState('AZ'). primjer: $this->Post->findByTitle('My First Blog Post'). Treba samo izabrati ime polja koji želimo tražiti. find ($conditions $fields. $recursive). array $fields. $fields. Povratni rezultat je niz formatiran koji je nađen sa find() ili findAll( ). $this->Specimen->findAllByKingdom('Animalia'). Ove magične funkcije mogu biti korištene kao shortcut za pretragu tabela za redom koji je dat određenim poljem i određenom vrijednošću. string array string int $conditions. $recursive. string $order. //primjer:$conditions="race='wookie' AND Kada je $recursive opcija postavljena na vrijednost veću od 1. $page. $limit. findAll( ) operacije pokušavaju vratiti odgovarajući model nađen sa findAll( ). $order. findAll( ) na našem Property modelu će vratiti te odgovarajuće modele. string $conditions. int $page. 15 . Ako naš property ima više vlasnika koji su uključeni u više ugovora. $order. $recursive).

generateList ($conditions. // But we also want the previous and next images. Ovo radi samo za numerička i date polja..findNeighbours ($conditions $field. Ova funkcija je shortcut za dobivanje liste ključnih vrijednosti parova – pogotovo praktična za kreiranje html select tagova iz liste našeg modela. $this->Image->findNeighbours(null. $valuePath. array $field. 'id'. $keyPath. ako želimo generirati listu uloga baziranu na Role modelu. string $conditions. $order. $order. Vraća niz sa susjednim modelom (sa samo navedenim poljima). } } findCount ($conditions). $limit. puni poziv može izgledati kao u sljedećem primjeru: $this->set( 16 .. $this->set('image'. Ovo može biti korisno u situaciji kada želimo 'Previous' i 'Next' linkove koji vode korisnika kroz uređenu sekvencu u našem model-u ulaza.. $this->set('neighbours'. $keyPath. string $value. $value). Primjer: class ImagesController extends AppController { function view($id) { // Say we want to show the image. string $conditions. $valuePath). string string int string string $conditions. specifiran sa $field i $value i filtriran sa SQL uslovima. Vraća broj rekorda koji odgovaraju zadanim uslovima. Npr. $conditions. $limit. $this->Image->find("id = $id").. $id).

'Roles', $this->Role->generateList(null, 'role_name ASC', null, '{n}.Role.id', '{n}.Role.role_name') ); //This would return something like: array( '1' => 'Account Manager', '2' => 'Account Viewer', '3' => 'System Manager', '4' => 'Site Visitor' ); read ( $fields, $id); string $fields; string $id;

Ovu funkciju možemo koristiti da dobijemo polja i vrijednosti polja iz trenutačno učitanog rekorda ili rekorda specifiranog sa $id.
query ($query); string $query; execute ($query); string $query;

SQL poziv možemo napraviti koristeći model query( ) i execute ( )metode. Razlika između query( ) i execute ( ) je ta što, query( ) koristimo da napravimo korisnički SQL upit, a execute( ) koristimo da napravimo korisničke SQL komande. Primjer:
<?php class Post extends AppModel { var $name = 'Post';

} ?>

function posterFirstName() { $ret = $this->query("SELECT first_name FROM posters_table WHERE poster_id = 1"); $firstName = $ret[0]['first_name']; return $firstName; }

Većina model pretraživača uključuju prosljeđivanje uslova u jednom ili u drugom pravcu. Najjednostavniji pristup ovome je pomoću WHERE klauzule iz SQL-a, ali ako nam je potrebno više kontrole možemo koristiti nizove. Korištenje nizova je jednosatvno i lako za čitanje i jednostavno je za pravljenje upita. Sintaksa odvaja elemente upita u diskretne, 17

manipulativne dijelove. Ovo dozvoljava Cake-u da generira najviše moguće efikasne upite, osigurava odgovarajuću SQL sintaksu. Upit baziran na nizu izgleda ovako:
$conditions = array("Post.title" => "This is a post"); //Example usage with a model: $this->Post->find($conditions);

Traži bilo koji post gdje naslov odgovara stringu “This is a post”, mogli smo koristiti samo “title” kao ime polja. Kada pravimo upite, dobra je praksa uvijek specificirati ime modela, kao poboljšanje jasnoće koda i kao pomoć pri prevenciji kolizija u budućnosti ako odlučimo mijenjati našu šemu. I sa drugim komparacijama je isto, npr. ako želimo naći sve postove gdje naslov nije “This is a post”.
array("Post.title" => "<> This is a post")

Sve što je dodano nalazi se između ‘< >’ tagova prije izraza. Cake može obraditi bilo koju validnu SQL komparaciju operatora uključujući odgovarajuće izraze koristeći LIKE, BETWEEN. Npr. Ako želimo naći post gdje je naslov dat kao set vrijednosti:
array("Post.title" => array("First post", "Second post", "Third post"))

Dodavanje dodatnih filtera uslovima je jednostavno kao dodavanje dodatnih parova vrijednosti /ključeva nizu.
array ( "Post.title" => array("First post", "Second post", "Third post"), "Post.created" => "> " . date('Y-m-d', strtotime("-2 weeks")) )

Cake prihvata sve validne SQL bool-ove operacije, uključujući AND, OR, NOT, XOR,...i možemo ih pisati malim ili velikim slovima. Po defaultu, Cake pristupa višestrukim uslovima sa bool-ovim AND, što znači, odlomak koji želimo odgovara samo postu koji je kreiran prije dvije sedmice i naslov odgovara jednom u datom setu. Mi možemo jednostavno naći post koji odgovara bilo kojem uslovu:
array ("or" => array ( "Post.title" => array("First post", "Second post", "Third post"), "Post.created" => "> " . date('Y-m-d', strtotime("-2 weeks")) ) )

18

Snimanje podataka Da bi snimili podatke u naš model, trebamo dostaviti podatke koje želimo snimiti, podaci koji se šalju save( ) metodi trebaju biti u sljedećoj formi:
Array ( [ModelName] => Array ( [fieldname1] => 'value' [fieldname2] => 'value' ) )

U redoslijedu slanja podataka controller-u u ovom načinu, lakše je koristiti HTML helper za ovo, jer kreira forme elemenata koje su imenovane na način koji Cake očekuje. Samo trebamo biti sigurni da forme elemenata imaju imena kao što je data[Modelname] [fieldname], koristiti $html->input('Model/fieldname') je najjednostavnije. Podaci poslani iz forme se automatski formatiraju i budu smješteni u $this->data u contoller-u, tako da je snimanje podataka iz web formi brzo. Edit funkcija za svojstvo controller-a može izgledati ovako:
function edit($id) { // The property model is automatically loaded for us at $this->Property. // Check to see if we have form data... if (empty($this->data)) { $this->Property->id = $id; $this->data = $this->Property->read();//populate the form fields with the current row } else { // Here's where we try to save our data. Automagic validation checking if ($this->Property->save($this->data['Property'])) { //Flash a message and redirect. $this->flash('Your information has been saved.', '/properties/view/'.$this->data['Property']['id'], 2); } //if some fields are invalid or save fails the form will render } }

Delete funkcija: del ( $id, 19

View View je page template.$cascade). <h1>Add Post</h1> <form method="post" action="<?php echo $html->url('/posts/add')?>"> <p> Title: <?php echo $html->input('Post/title'.thtml.2. koji se obično imenuje poslije akcije. vraća true pri uspjehu.') ?> </p> <p> Body: <?php echo $html->textarea('Post/body'. array('size' => '40'))?> <?php echo $html->tagErrorMsg('Post/title'. Ako je model povezan sa drugim modelima. string $id. npr. array('rows'=>'10')) ?> <?php echo $html->tagErrorMsg('Post/body'. 2. ova metoda će takođe obrisati povezani model.') ?> </p> <p> <?php echo $html->submit('Save') ?> </p> </form> 20 . boolean $cascade. 'Body is required. Brisanje modela specificiramo sa $id ili sa aktualnim id-om modela. view za PostController::add() nalazi se u /app/views/posts/add. Ako je $cascade posatvljen na true. tj. 'Title is required. nakon uspješnog brisanja.

org/TR/xhtml1/DTD/xhtml1-transitional. zato nema puno korištenih javnih funkcija u view-u. image.thtml. Jednom kada defaultni layout bude kreiran.w3. Postoje dva dizajn paterna koja se koriste u view-u: Template View i Transform View. to bi trebalo uraditi preko Controller-a. controller view kod biva smješten unutar defaultnog layout-a. View ima pristup Model-u.. ali nije dobro da View poziva metode Model-a kao što je update. View : . uključuje scripte.layouts . Popularni template Smarty je primjer template-a koji koristi custem syntax metodu. npr. mediu…Mnoge funkcije u view-u su dostupne preko helpera. XML.1.. View takođe može biti bilo koji set podataka.</div> 21 .org/1999/xhtml"> <head> <title><?php echo $title_for_layout?></title> <link rel="shortcut icon" href="favicon. Transform View ekstraktuje podatke iz modela i transformiše ih u traženi output format.Views omogućava sve aspekte prezentacije.thtml) koji su slobodni od kompleksnog PHP koda. najviše view file-ova sadrži HTML. Kada kreiramo layout treba “reči” Cake gdje se nalazi controller..0 Transitional//EN" "http://www. include it here --> <div id="header"> <div id="menu">.w3.. Cake views su prilično jednostavni PHP file-ovi.dtd"> <html xmlns="http://www.If you'd like some sort of menu to show up on all of your views. Koristan je kod kreiranja formi. Primjer kako može izgledati defaultni layout <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1. a može se kreirati i vlastiti.2. dok u Transform View-u počinje se sa podacima i gradi se output prema tome. U Template počinje se sa skeletom outputa i insertuju domain podaci u to. Razlika između Template View-a i Transform View-a je u pristupu data flow-u. linkove.Svi pogledi (views) unutar Cake-a se nalaze u odvojenim fajlovima (*. HTML Helper je po defaultu dostupan u svakom view-u i to je najkorišteniji helper u view-u. Template View je primarni patern koji koristi template file (obično HTML) koji uključuje specijalne markere koji su zamijenjeni sa podacima iz modela kada je Template View izvršen.ico" type="image/x-icon"> </head> <body> <!-. Layout file-ovi nalaze se u /app/views/layouts. Cake dolazi sa velikim brojem helper-a. View ne treba sadržavati puno logike. Cake-ov defaultni layout može biti zamijenjen novim defaultnim layout-om kao /app/views/layouts/defaults. eksktaktuje podatke iz Modela i priprema ih kao HTML za web stranicu ili kao XML za web server ili kao tekst za mail. Layouts Layouts sadrži prezentacijski kod i bilo što što želimo vidjeti u view-u treba biti smješteno u layout-u.elements 2.

Cake pomaže da ponavljamo dio website-a koji nam je potreban.thtml file ekstenziju. Elementi se nalaze u /app/views/elements/ folderu I imaju . ?> U Element file-u sve propuštene varijable su varijable imenovane kao i niz .2. Primjer: Poziv elemenata bez parametra Poziv elementa kao niza podataka: <?php echo $this->renderElement('helpbox'. Elements Mnoge aplikacije imaju male blokove prezentacijskog koda koji se treba ponavljati na više stranica. Elementi po defaultu nemaju nikakav pristup podacima.")). Help boksovi.Here's where I want my views to be displayed --> <?php echo $content_for_layout ?> <!-. ?> <?php echo $this->renderElement('helpbox'). 2.</div> <!-. ponekad u različitim mjestima u layout-u. Element je bazično mini view koji koji može biti uključen u drugi View. array("helptext" => "Oh. navigacijka kontrola. this text is very helpful. da bi dozvolili pristup podacima šaljemo ih kao imenovani parameter u niz..</div> </body> </html> Možemo kreirati koliko hoćemo layout-a u Cake-u samo ih treba smjestiti u /app/views/layouts direktorij. 22 . elementi se mogu koristiti da View učine više čitljivim.Add a footer to each displayed page --> <div id="footer">.2.ekstra meniji su implementirani u Cake-u kao elementi..

1. Command patern enkapsulira akciju u objekte. Application Controller je centar onog čime MVC Controller operira. PeopleController. za privatnu vidljivost. really_nifty_things_controller. Controller varijable: 23 . Controller se koristi za logičko upravljanje modelom. 2. file controller će biti posts_controller.ime treba početi sa '. primjeri: people_controller. Ime controller klase zavrašava sa „Controller“ npr.3. UsersController. Tipičan način impelmentacije Controller-a je koristeći Command paterne.Front Controller . klase AppController-a definisane su u app/app_controller.php. Primarna odgovornost je da odluči šta aplikacija treba odgovoriti na traženi zahtijev. U sadržaju web aplikacije koristan je cilj koda koji odvaja koncentrirani Command da brine o radu pojedinačni HTTP zahtijeva. ime Controllera u Cake-u je uvijek u množini. tako da možemo parametrizirati upit.php i treba da sadrže metode koje su dijeljenene imeđu dva ili više Contoller-a.php. tipična korisnička akcija i poziva promjene na modelu. Da bi zaštitili vidljivost.php.-'. Imamo dvije vrste Controller-a: . Controller Controller procesira i odgovara na događaje. Ime controller file-a piše se malim slovima i završava sa '_controller'.php.3. ime akcije controller-a treba početi sa '-'.Application Controller Front Controller često pomaže u centralizaciji aplikacijkog flow-a u jednostavnim tačkama. Centralizacija može pomoći da razumijemo kako kompleksan sistem operira i navodi jednostavna mjesta gdje možemo ubaciti globalni kod.2. Manipulacija sa nekoliko specijalnih varijabli u controller-u dozvoljava da koristimo neke prednosti extra Cake funkcionalnosti. line_items_controller. Front Controller je odličan za centralizaciju. pa ako imamo controller klasu koja se zove PostsController.

24 . $beforeFilter – koristimo ovu varijablu ako želimo da se kod pokreće svaki put kada se akcija pozove .postavljajući ovo na false će zaustaviti akciju od automatskog izvođenja $components – kao $helpers i $uses.1. Primjer: class ProductsController extends AppController { var $beforeFilter = array('checkAccess'). ova varijabla koristi se za učitavanje komponenata koje su nam potrebne npr. } } 2. $helper – ova varijabla se koristi za učitavanje helpera u view. $autoRender . dostupan je po defaultu ali ako definišemo $helper bez HtmlHelpera. treba pokušati dodati sljedeću liniju koda u controller: var $uses = array('Fraggle'.'Javascript'). Najčešće se koristi da se dobiju informacije (podaci) koje su date controller-u preko POST ili GET operatora. Treba uključiti HtmlHelper u $helpers ako ga želimo koristiti. function checkAccess() { //Logic to check user identity and access would go here. iako je automatski prije bio dostupan. $this->data Primjer: slanje podataka POST metodom iz HTML Helper-a u controller // A HTML Helper is used to create a form element $html->input('User/first_name'). checkAccess() is called first. HTML helper se automatski učitava.'Ajax'. dobit ćemo poruku o greški u view-u.'Smurf'). var $components = array('acl'). var $helpers = array('Html'.3. } function index() { //When this action is called. ova varijabla se koristi da dajemo podatke u controller i omogućava pristup informacijama o tačnom upitu. ali ako želimo pristupiti $this->Smurf. ali može se ova varijabla koristiti i za druge helpere npr. Treba primjetiti da smo uključili Fraggle model u $uses niz.možemo vidjeti korisničke permisije prije nego se izvrši bilo koja akcija.- - - $uses – ako controller koristi više od jednog modela.Controller parametri Controller parametri su dostupni preko $this->params u Cake controller-u.... Ova funkcionalnost je veoma dobra za access control. FragglesController će automatski učitati $this->Fraggle.

set( ) funkcija je glavni put da uzmemo podatke iz controller-a da bi ih vidjeli. U sljedećem primjeru imamo Post controller sa četiri funkcije: funkcija index ( ). mixed $value. .$this->flash( ) funkcija zove se upravljačka funkcija koja prikazuje korisniku poruku npr. stranicu koju smo postavili da bude indexna. parametri funkcije mogu biti jednostavne vrijednosti. tj. edit ( ) i delete ( ). varijablama može se pristupiti u view-u. .// When rendered in the HTML would look something like: <input name="data[User][first_name]" value="" type="text" /> // And when submitted to the controller via POST. controller napravi varijablu $color dostupnom u view-u.vraća broj grešaka koje su generirane pri neuspješnom snimanju podataka. ispisuje poruku da je post izbrisan. .'.' has been deleted.$value). // shows up in $this->data['User']['first_name'] Array ( [data] => Array ( [User] => Array ( [username] => mrrogers [password] => myn3ighb0r [first_name] => Mister [last_name] => Rogers ) ) ) Akcija je jedinstvena funkcionalnost kontrolera.'. '/posts').validateErrors( ) ... Omogućava dodavanje novih vijesti. ako napišemo set('color'. Funkcija index nam prikazuje početnu stranicu tj.'blue') . Save() metoda provjerava greške i neće snimiti podatke ako postoji greška. Ispisuje poruku korisniku da je njegov post snimljen ili $this->flash ('The post with id: '.. edit i delete vijesti koje su nalaze u bazi. string $var. $this->flash ('Your post has been saved. add ( ). 25 . početna. set($var. cijele nizove.. Funkciju set( ) možemo koristiti da uzmemo bilo šta: jednosatvne vrijednosti. pokreće se automatski po zahtijevu.render ( ) je funkcija koja se često ne koristi. jer render se automatski poziva na kraju svake kontrolne akcije.'/posts'). koja prikazuje naslov postojeće vijesti. nizovi. .$id.Jednom kada koristimo set().

$this->data = $this->Post->read().'/posts').$id. $this->set('post'.'/posts'). '/posts'). function index() { } { } { function add() if (!empty($this->data)) { if ($this->Post->save($this->data)) { $this->flash('Your post has been saved.'. } } } } ?> function view($id = null) $this->Post->id = $id.'. } { 26 . $this->Post->findAll()). $this->flash('The post with id: '. } function edit($id = null) { if (empty($this->data)) { $this->Post->id = $id. } else { if ($this->Post->save($this->data['Post'])) { $this->flash('Your post has been updated.<?php class PostsController extends AppController { var $name = 'Posts'.' has been deleted.'. $this->set('posts'. $this->Post->read()). } } function delete($id) $this->Post->del($id).

poziva se prije svake controller akcije. Uzimanje podataka iz controller-a je jednostavno. $url je Cake URL (/controllername/actionname/params).3.beforeRender ( ). array $options.beforeFilter ( ).2. Cake controller omogućava odgovarajući broj callback-ova koji možemo iskoristiti da bi ubacili logiku prije ili poslije značajnih funkcija controller-a. Treba deklarisati funkcije u controller-u koristeći parametre i povratne vrijednosti. AutoRender automatski postavlja true za controller akciju. Controller callback U Cake-u callback je način izvršavanja nekog koda prije ili poslije Model ili Contoller metoda. prikazuje view. $options). // Ovdje je jednostavni controller class UsersController extends AppController { function getUserList() { $this->User->findAll(). poziva se nakon svake controller akcije . . korisna za provjeru aktivni sesija i provjeru uloga . Možemo koristiti requestAction da dobijemo podatke iz druge controller akcije ili da dobijemo potpuni render view iz controller-a.requestAction ( $url.2. poziva se nakon controller logike i prije nego što je view prikazan Sljedeće funkcije su dio Cake objekt klase. koristi se samo upitna akcija u view-u u iz kojeg trebamo podatke.afterFilter ( ). string $url. U ovom primjeru šaljemo email iz Model-a <?php // File: /app/models/bookmark. } } Možemo kreirati callback u našem aplikacijskom Model-u ili Controller file-u. Ova funkcija poziva controller akciju iz bilo koje lokacije i vraća tj. ako $extra niz uključuje 'return' .php class Bookmark extends AppModel { 27 . ali one mogu biti dostupne i u controller-u .

$return ).var $name = 'Bookmark'. . Ako želimo neke promjene napravimo kopiju /cake/config/tags. Omogućiti ubacivanje često ponovljene sekcije HTML koda 2. return true. } } ?> 3. 'Bookmark saved to database').ini. Helper Cake ima nekoliko već kreiranih helpera koje možemo iskoristiti.Number .Text . mixed $secondArg = null[.AJAX . 28 .… Generiranje charset MET-a taga: charset ( $charset. ako je prvi argument niz. HTML Helper ima dva cilja: 1. Ako želimo koristiti Cake za ubacivanje dobro formirani i često korištenih elemenata u HTML kodu.. HTML Helper funkcije takođe uključuju $htmlAttributes parametre. treba provjeriti specifični ključ sa funkcijom array_key_exists ( ).php.]]) U svakoj funkciji treba provjeriti je li prvi argument niz. HTML Helper HTML Helper je jedan od načina Cake-a za brži i manje monoton razvoj. a to su: ..Javacript . Postoje funkcije u ovom helperu koje insertuju mediu.Cache Svaka metoda u helperu treba da prihvati argumente u sljedeći način: helperMethod(mixed $params[.php i snimimo je u /cake/config/ folder. Omogućiti brzo i jednostavno kreiranje web formi Mnoge funkcije u HTML Helper-u koriste HTML tagove definisane u file-u tags.ini.com'.HTML . 3.1. function afterSave() { // mail me when a new bookmark is added mail('example@example. tabele. liste.Time . HTML Helper je veoma dobar u tome. to provjeravamo sa funkcijom is_array ( ).

'Last Name'. string string array boolean $path.cakephp.'email')).'http://www.org'). ?> CakePHP nam vraća: 29 . ?> Cake nam vraća: <a href="http://www. $rel=’stylesheet’.org" >CakePHP Home</a> koji vidimo kao CakePHP Home Ako napišemo: <?php echo $html->tableHeaders(array('First Name'.'Email').). ?> Cake nam vraća: <tr><th>First Name</th> <th>Last Name</th> <th>Email</th></tr> što prikazuje kao First Name Ako napišemo: Last Name Email <?php echo $html->tableCells(array('Dunnottar'.css" /> koji učitava stil za našu stranicu Ako napišemo: <?php echo $html->link('CakePHP Home'.'Ceiteach'. ?> CakePHP nam vraća: <link rel="stylesheet" type="text/css" href="/cake1point2/css/donutczar. $htmlAttributes. $rel=’stylesheet’. $return = ‘false’).cakephp. boolean $return. Kreiranje linka u CSS stylesheet-u : css( $path.string $charset. //$rel parameter dozvoljava kreiranje HTML Helperi Ako napišemo: <?php echo $html->css('donutczar'). rel=vrijednost za tag $htmlAttributes. $return = ‘false’.

} if (strpos($href.<tr><td>Dunnottar</td> <td>Ceiteach</td> <td>email</td></tr> što prikazuje : Dunnottar Ako napišemo: Ceiteach email <?php echo $html->image('cake. unset($confirm). } if (isset($confirm)) { $options['confirm'] = $confirm. $href = null.array('alt'=>'CakePHP icon')). } if (!isset($href)) { $href = $title. $confirm = null) { if (is_array($params)) { extract($params.icon. } if (!isset($title)) { $title = null. $options = null. 30 . ?> CakePHP nam vraća: <img src="/cake1point2/img/cake. EXTR_OVERWRITE).png'. '://') === false) { $href = $this->url($href). } if (!isset($options)) { $options = null.png" alt="CakePHP icon" /> što prikazuje Primjer definicije HtmlHelper::link ( ) <?php function link($params. } else { $title = $params.icon.

password . array $htmlAttributes. . 3.} $values = array( 'href' => $href... $htmlAttributes.trim Ako napišemo: <?php echo $time->trim('Source character string. } ?> Form tagovi koje HTML Helper može generirati: . $htmlAttributes.nice Ako napišemo: <?php echo $time->nice('07-11-2007 18:13:15'). $return = false).. string array boolean $filedName. 'options' => $this->_parseOptions($options). TimeHelper . ?> 31 . $return = false). $values). 'tagValue' => $title ).2.').'. submit ( $buttonCaption. return $this->assign('link'. $return = false. boolean $return = false.'.submit password ($fieldName. ?> CakePHP vraća: Source chara. string $buttonCaption. $htmlAttributes..12.

'created'). NumberHelper . ?> CakePHP vraća: 123.2.43 .4321'. ?> 32 . ?> CakePHP vraća: 98.precision Ako napišemo: <?php echo $number->precision('123456789'.currency Ako napišemo: <?php echo $number->currency ('98765. 18:13 .77% .2).'').4321'.'.isToday Ako napišemo: <?php echo $time->isToday('07-11-2007 18:13:15').'USD').format Ako napišemo: <?php echo $number->format('98765.dayAsSql Ako napišemo: <?php echo $time->daysAsSql('07-11-2007 18:13:15'.'. ?> CakePHP vraća true ako je dati datum današnji 3.457 .3.CakePHP vraća: Mon.toPercentage Ako napišemo: <?php echo $number->toPercentage('98.'07-01-2007 00:00:00'.7654321'.765.3). ?> CakePHP vraća: $98. ?> CakePHP vraća: (created >= '2013-04-29 00:00:00') AND (created <= '2012-06-29 23:59:59') . Apr 29th 2013.

php = name of php file in /app/views/helpers Ako želimo kreirati helper koji će koristiti output CSS style linka koji trebamo u aplikaciji.php trebamo dodati: Putanja: /app/views/helpers/link.php class LinkHelper extends Helper { function makeEdit($title. $url) { 33 . string $string. $return = false).php class LinkHelper extends Helper { function makeEdit($title.toReadableSize Ako napišemo: <?php echo $number->toReadableSize('123456789'). npr.. } } Postoji nekoliko funkcija uključenih u Cake helper klase koje možemo iskoristiti: output ( $string. u link. boolean $return = false. prvo trebamo kreirati novu klasu u app/views/helpers. Ako koristimo output ( ) za formatiranje naših linkova title i URL i vraćanje ih u view. file php klase trebao bi izgledati ovako: Putanja: /app/views/helpers/link. $url) { // Logic to create specially formatted link goes here. da se naš helper zove LinkHelper.43 .CakePHP vraća: 98.4. Kreiranje vlastitih helpera Konvencija imenovanja je slična kao u modelu: • • • LinkHelper = class name link = key in helpers array link.765. ?> CakePHP vraća: 117..74 MB 3.

Da bi smanjili pritisak na developere. array('class' => 'edit')). Kada kreiramo vlastiti helper snimimo ga u /app/views/helpers/ i bit ćemo u mogućnosti da ga uključimo u naš contoller-u preko specijalne varijable $helpers. function makeEdit($title. } } Možemo koristiti neke već postojeće funkcionalnosti drugog helpera. 'Link').php ( korištenje drugi helpera) class LinkHelper extends Helper { var $helpers = array('Html'). delete i edit dugmićima. $url. Web developeri ne vole kreirati forme koje nikad neće “stavrno” koristiti. Putanja: /app/views/helpers/link. class ThingsController { var $helpers = array('Html'. Da koristimo prednosti drugi helpera trebamo specificirati helper koji želimo koristiti. } } return $this->output("<div class=\"editOuter\">$link</div>"). scaffolding je uključen u Cake. Scaffolding analizira tabele u bazi i kreira standradnu listu sa add. zatim pišemo funkcije kao u controller-u npr. Scaffolding Scaffolding je dobar način uzimanja početnog dijela web aplikacije. Strandardnu formu za edit i standardni 34 .// Use the helper's output function to hand formatted // data back to the view: return $this->output("<div class=\"editOuter\"><a href=\"$url\" class=\"edit\">$title</a></div>"). } 4. početna šema baze i tema se mijenjaju. npr. što je normalno u početnom dijelu dizajna procesa. $helper nizom. $url) { // Use the HTML helper to output // formatted data: $link = $this->Html->link($title.

thtml /app/views/posts/scaffold/show. Da postavimo koje polje u stranoj tabeli će se prikazivati.scaffold. parent_id je strani ključ za tabelu parent.scaffold. označeni box će se automatski popuniti sa redom iz strane tabele (category) u show/edit/new view. Primjer: Custom scaffolding views for a PostsController should be placed like so: /app/views/posts/scaffold/index.thtml /app/views/posts/scaffold/new.scaffold.scaffold. 5. Ako imamo tabelu category i kolonu parent_id. Za dodavanje scaffoldinga u aplikaciju. postavimo varijablu $displayField u strani model. Ako želimo nešto drugačiji scaffolding view.thtml Osobina koja može koristiti u Cake-u je kod generator: Bake. } ?> Scaffold očekuje da bilo koje ime polja koje završava sa “_id” je strani ključ za tabelu koja ima ime koje predhodi “ _”. Data Validation Kreiranje korisnički validacijski pravila pomaže da podaci budu sigurni u Model-u uz pravila aplikacije. Bake dozvoljava da generiramo kodiranu verziju scaffold koda.… Prvi korak u data validation je kreiranje validacijskih pravila u Model-u. primjer: 35 . možemo kreirati vlastiti. <?php class CategoriesController extends AppController { var $scaffold. } ?> var $displayField = 'title'.thtml /app/views/posts/scaffold/edit. Primjer: <?php class Title extends AppModel { var $name = 'Title'. u controller treba dodati varijablu $scaffold. Kada imamo strani ključ u tabeli (tabela title sa category_id) i imamo asocijaciju modela. lozinka može biti samo osam karaktera. npr. korisničko ime može sadržavati samo slova. Da bi to uradili koristimo Model:: validate array u Model definiciji. koju zatim možemo premjestiti i modifikaovati prema zahtijevima aplikacije. npr.view za provjeru jednostavni item-a u bazi.

'password' => VALID_NOT_EMPTY. Validation errors. to su: VALID_NOT_EMPTY VALID_NUMBER VALID_EMAIL VALID_YEAR Ako postoji bilo koja validacija u modelu definicije ($validate array) bit će analizirana i provjerena tokom snimanja (Model:: save() method). } else { if($this->Post->save($this->data)) { //ok cool. the stuff is valid } else { //Danger. primjer: /app/controllers/blog_controller. } 36 . 'born' => VALID_NUMBER ).php. 'email' => VALID_EMAIL. Ali su obično podaci u kodu controller-a.'). neke od njih su predefinisane u /lib/validators.}$/i'.php <?php class User extends AppModel { var $name = 'User'. 'Please correct errors below.Putanja: /app/models/user. $this->set('errorMessage'.php <?php class BlogController extends AppController { var $uses = array('Post'). Za direktnu validaciju podataka koristimo Model::validates() (vraća false ako su podaci pogrešni) i Model::invalidFields() (vraća error message kao niz). function add () { if (empty($this->data)) { $this->render(). Will Robinson. $this->render(). } ?> Validacije se definišu koristeći Perl kompatibilne regularne ekspresije. var $validate = array( 'login' => '/[a-z0-9\_\-]{3.

')?> </p> <p><?=$html->submit('Save')?></p> </div> </form> Controller::validates($model[. tako što dodamo file u /app/controllers/components direktorij. Controller::validationErrors() vraća bilo koju poruku o grešci u modelu. nego proširene Cake biblioteke.')?> </p> <p>Body <?php echo $html->textarea('Post/body') ?> <?php echo $html->tagErrorMsg('Post/body'. Components Komponente se koriste kao pomagalo controller-a u specifičnim situacijama. class FooComponent extends Object { var $someVar = null. to je prezentacijska logika. array('size'=>'40'))?> <?php echo $html->tagErrorMsg('Post/title'. u file-u trebamo definirati klasu koja ima ime isto kao i komponenta. var $controller = true. isto što i helper za view. 6.thtml <h2>Add post to blog</h2> <form action="<?php echo $html->url('/blog/add')?>" method="post"> <div class="blog_add"> <p>Title: <?php echo $html->input('Post/title'. Developeri više vole koristiti specijalne funkcije koje prave u komponentama. permisije za korisnike (akcije: edit. del. ako želimo login. Ako želimo dodati još neke unose na glavni meni kada je korisnik logiran.} } ?> } View za blog može izgledati ovako: /app/views/blog/add. Primjer: autentifikacija korisnika. 'Body is required. 'Title is required. logout... Glavna razlika u tome je što komponente enkapsuliraju biznis logiku. add. Primjer: ako želimo kreirati komponentu foo.$model…] se koristi za provjeru bilo koje korisničke validacije dodane u model. dok helperi enkapsuliraju prezentacijsku logiku. 37 . tako da je ova autentifikacija komponenta.) to je biznis logika. Komponente su za controller.php. tako da može biti prikazana sa tagErrorMsg() u view-u. Možemo kreirati i vlastite komponente.

Da bi koristili naš model u komponenti. Komponente imaju dozvolu controller-a da se učitaju u startup() metodi. Ovo nam dozvoljava da postavimo osobine komponente u beforeFilter() metodu koja komponenta će se izvršiti u startup() metodi. jednostavno u našoj komponenti deklariramo koju komponentu želimo kotistiti. Možemo koristiti i druge komponente u vlastitoj komponenti. } function doFoo() { $this->someVar = 'foo'. 38 . trebamo kreitati instancu: $foo =& new Foo(). } } Da bi koristili komponentu trebamo dodati sljedeći kod u definiciju controller-a var $components = array('Foo'). Sada u controller-u možemo koristiit: $this->Foo->doFoo().function startup(&$controller) { // This method takes a reference to the controller which is loading it. ova metoda se poziva poslije Controller::beforeFilter(). Primjer: ako želimo koristiti session komponentu: var $components = array('Session'). // Perform controller initialization here.

7. Tabele servisa Servis se sastoji od pet tabela: 39 . Servis “Anketa” 7.1.

u tabelu „polls“ smještamo id (primarni ključ tabele). broj korisnika koliko ih je glasalo i broj odgovora (noq) tj. jedna anketa može imati samo jedno pitanje. jer jedna anketa može imati više rezultata. Tabela „polls“ je u odnosu 1:1 sa tabelom „questions“ tj. broj odgovora koliko će imati anketa. polls . ime ankete (name).1. ukupno odgovora (ukupno_odg) tj. a 1:n u odnosu na tabelu „results“. 40 .

tj. IP adresu korisnika. 41 . polje anketa_id povezuje tabelu „questions“ sa tabelom „polls“ u odnosu 1:1. polje anketa_id povezuje sa tabelom „polls“ u odnosu 1:1. Tabela „checkip“ nije povezana sa drugim tabelama.2.1. Tabelu answers pitanja_id povezuje sa tabelom “questions” u odnosu 1:n. lang_id povezuje tabelu “answers” sa tabelom ”languages” u odnosu 1:n. kao što možemo vidjeti u sljedećem primjeru.php class Question extends AppModel { var $name = 'Question'. U koloni rezultat smješteni su rezultati odgovora koji se vežu za jednu anketu „anketa_id = 1“. 3. jedno pitanje može imati više odgovora. odgvore (odgovor).2. ukupan broj glasova za svaki odgovor. rezultat tj. question. lang_id i pitanje 4. MVC servisa 7. Na osnovu ove tabele provjeravamo da li je korisnik već glasao i poll_code. svaki rezultat (odgovor) povezan je sa anketom.2. answers – u tabelu „answers“ smještamo id (primarni ključ tabele). rezultati_id povezuje sa tabelom “results” u odnosu 1:1. Model Servis „Anketa“ ima četiri modela: 1. questions – u tabelu „questions“ smještamo id (primarni ključ tabele). tj. služi za snimanje IP adresa. id 1 2 3 4 rezultat 15 10 20 8 anketa_id 1 1 1 1 5. checkip – u tabelu „checkip“ smještamo id (primarni ključ tabele). results – u tabelu „results“ smještamo id (primarni ključ tabele). odgovore možemo pisati na više jezika. 7. jedan odgovor može imati samo jedan rezultat.

php class Result extends AppModel { var $name = 'Result'. View Servis „Anketa“ ima view „polls“ koji se sastoji od četiri php file-a: 1. poll. } 7. admin_index. } 4. answer.php class Answer extends AppModel { var $name = 'Answer'.php class Poll extends AppModel { var $name = 'Poll'.} 2. } 3.2. result.2.php <tr> <td colspan="3"><table width="100%" border="0" cellspacing="10" cellpadding="0"> <tr> <td><span class="naslov_kategorije"><strong>Kreirati:</strong></span><br /> 42 .

') ? ></td> <tr> <td><?php echo $html->submit('Save') ?></td> </tr> U admin_add.'/Polls/admin_add_qu'. dugmić „Save“. 'Br_odg is required.<a class="menu" href="<?php echo $rootPath ?>Polls/admin_add/"> [Dodati novu anketu]</a><br /></td> </tr> </table></td> </tr> Admin_index. 'Name is required. zatim pišemo putanju tj. 2. Zatim smo kreirali tabelu i koristili smo html helpere za unos naziva ankete i broj odgovora u anketi. admin_add. 3.php file-u. Koristili smo html helpere za poruku u slučaju greške koje smo poslije stavili pod komentar jer nisu bili neophodni i html helper za snimanje (prosljeđivanje) tj.'/Polls/admin_add_an'. array('size' => '40'))?> <?php //echo $html->tagErrorMsg('Poll/ name'.php file-u kreirali smo formu koja pomoću metode post unesene podatke šalje admin_add_qu. u našem primjeru Polls/admin_add/.admin_add_qu.php služi za ispis linka za dodavanje nove ankete.') ?> </td> </tr> <tr> <td>Broj odgovora:</td><td><?php echo $html->input('Poll/noq'.?>" enctype="multipart/form-data" > <table width="100%" border="0" cellspacing="10" cellpadding="0"> <tr> <td><table> <tr> <td>Pitanje</td> <td><?php echo $html->input('Poll/name'.php <tr> <td colspan="3"><form method="post" action="<?php echo $rootPath. Dodali smo i css class „naslov_kategorije“ za ispis „Kreirati“ i class „menu“ za link [Dodati novu anketu]. koji view i php file se poziva. Kreiramo tabelu i u redove/kolone tabele dodajemo link zbog preglednosti na stranici.php <tr> <td colspan="3"><form method="post" action="<?php echo $rootPath. array('size' => '10'))?></td> <td><?php //echo $html->tagErrorMsg('Poll/noq.?>" enctype="multipart/form-data" > <?php 43 .

gif" alt="" /></td> <td width="96%" class="atributi_p"><?php echo $lang['Language'] ['name']. foreach($pitanja as $pitanje){?> <tr> 44 .</td> </tr> <tr> <td height="25" bgcolor="#E1E1E1">&nbsp.$lang['Language'] ['code'].</td> <td bgcolor="#E1E1E1"><?php echo $html->input('Pages_'. ?></td> </tr> </table></td> <td bgcolor="#666666">&nbsp. $lang['Language']['code'].</td> <td width="329">&nbsp. ?>lang/<?php echo $lang['Language']['code'].'/question'.</td> <td width="9">&nbsp.</td> </tr> <tr> <td height="35" bgcolor="#666666">&nbsp.</td> <td bgcolor="#E1E1E1"> <table width="100%" border="0" cellspacing="0" cellpadding="0"> <?php $j =1. array('size' => '80'))?></td> <td bgcolor="#E1E1E1">&nbsp.$lang['Language']['code'].foreach ($langs as $lang){ echo $html->hidden('Pages_'. ?> <table width="700" border="0" align="center" cellpadding="0" cellspacing="0"> <tr> <td width="12" height="25">&nbsp.</td> </tr> <tr> <td height="25" bgcolor="#E1E1E1">&nbsp.</td> <td bgcolor="#666666" class="naslov_kategorije"><table width="100%" border="0" cellspacing="0" cellpadding="0"> <tr> <td width="4%"><img src="<?php echo $imgPath.</td> </tr> <tr> <td height="25" bgcolor="#E1E1E1">&nbsp.</td> <td bgcolor="#E1E1E1" class="naslov_kategorije">Pitanje:</td> <td bgcolor="#E1E1E1">&nbsp.'/lang'.</td> </tr> <tr> <td height="25" bgcolor="#E1E1E1">&nbsp.</td> </tr> <tr> <td height="25" bgcolor="#E1E1E1">&nbsp. ?>.</td> <td bgcolor="#E1E1E1">&nbsp. array('value' => $lang['Language']['id'])). echo $html->hidden('Pages_'.'/poll_id'.</td> <td bgcolor="#E1E1E1">&nbsp.</td> <td bgcolor="#E1E1E1">Odgovori:</td> <td bgcolor="#E1E1E1">&nbsp. array('value' => $poll_id)).

}?> </table></td> <td bgcolor="#E1E1E1">&nbsp. html helper za snimanje/submit i html helper za unos/input. $lang['Language']['code']..</td> </tr> </table> <?php }?> <table width="700" border="0" align="center" cellpadding="0" cellspacing="0"> <tr> <td width="12" height="25">&nbsp. ?></td> <td width="95%"><?php echo $html->input('Pages_'.$lang['Language']['code']. Tabeli smo u neke redove i kolone dodali boju pozadine. prvu foreach petlju koristimo da izlistamo sve jezike koji se nalaze u bazi. ?></td> </tr> </table> </form></td> </tr> U file-u admin_add_qu.Koristimo html helper za skriveno „hidden“ polje za provjeru poll_id i coda za jezik.</td> </tr> <tr> <td height="25" bgcolor="#E1E1E1">&nbsp.php napravili smo formu koja pomoću metode post unesene podatke prosljeđuje admin_add_an.</td> <td bgcolor="#E1E1E1">&nbsp.'/result_id_'.<td width="5%"><?php print $j.admin_add_an. tj. zastavu pored naziva jezika.'/answer_'.php <tr> <td colspan="3"><table width="100%" border="0" cellspacing="10" 45 .$j. array('size' => '80')). 4. Drugu foreach petlju koristimo da ispišemo pitanja i odgovore na svim jezicima. echo $html->hidden('Pages_'.</td> <td width="454"></td> </tr> <tr> <td height="35" bgcolor="#666666">&nbsp.$j. Imamo dvije foreach petlje.</td> <td bgcolor="#666666"><?php echo $html->submit('Save'). array('value' => $pitanja[$j-1])). id tabele „languages“.</td> <td bgcolor="#E1E1E1">&nbsp. ?> </td> </tr> <?php $j++. css class..php file-u.

1. dodali smo u kolonu i poruku „Hellooooo!!!!“. u contoller-u pišemo funkcije koje se izvršavaju u view-u. zatim imamo link za DNC stranu.3.ba" target="_blank">DNC Spinnaker</a></span></td> </tr> </table></td> </tr> U file-u admin_add_an.dnc. results_controller. 7. answers_controlller.php. 2007 <a href="http://www. } Kada kreiramo controller .2.php.php.cellpadding="0"> <tr> <td><h1>Hellooooo!!!!<br /></h1></td> </tr> </table></td> </tr> <tr> <td colspan="3"><a class="menu" href="<?php echo $rootPath ? >Polls/admin_add/"><h5>Povratak na stranicu za kreiranje ankete</h5i></a></td> </tr> <tr> <td colspan="3" align="center"><span class="copy">Copyright &copy. Controller Servis „Anketa“ ima četiri controller-a: polls_controller.php i questions_controller.php kreirali smo tabelu i link za povratak na stranicu za kreiranje ankete.php Kreiranje controller-a: class PollsController extends AppController { var $name = 'Polls'. dodamo funkcije koje su nam potrebne: 46 . polls_controller.

`rezultat`. $i++){ $id += $i. koju zatim pozivamo u funkcijama kada trebamo prikazati početnu stranu. $noq=$n['Poll']['noq']. if($id == 0) $id = 1. $id = $ret[0]['max(id)']+1. results(`id`. '$polls_id')"). $this->set('imgPath'. $ret = $ret[0]. 'http://localhost/cake/img/'). $name=$n['Poll']['name']. function admin_add_qu() { $this->set('rootPath'. `anketa_id`) 47 . $ret = $this->Poll->query("SELECT max(id) FROM results"). $pitanje_id[$i] = $id. $this->requestAction('/languages/getLanguages')). } Funkcija admin_index() služi za kreiranje varijeble za prikaz početne strane.'$noq')"). if($id == 0) $id = 1. 'http://localhost/cake/'). '0'. 'http://localhost/cake/img/'). } $this->set('langs'. $ret = $this->Poll->query("SELECT max(id) FROM polls"). odnosno loga i slika potrebnih za bolji dizajn strane. '0'. $this->Poll->query("INSERT INTO VALUES('$id'. `ukupno_odg`. $polls_id = $id. for($i=0. u našem primjeru 'http://localhost/cake/' i kreiramo varijablu $imgPath za prikaz slika. $id = $ret[0]['max(id)']+1.'$name'.function admin_index() { $this->set('rootPath'. 'http://localhost/cake/').`name`. $ret = $ret[0]. $i<$noq. $this->set('imgPath'. $this->Poll->query("INSERT INTO polls(`id`. U našem primjeru kreiramo varijablu $rootPath. if ($this->data) { $n = $this->data.`noq`) VALUES('$polls_id'.

'{$podaci['poll_id']}'. 'http://localhost/cake/img/'). } } Funkciaj admin_add_qu() provjerava da li postoje podaci. if($id == 0) $id = 1. '{$podaci['lang']}'.$i]. $i++.'{$podaci['question']}')"). $this->set('pitanja'. $ret = $ret[0]. `lang_id`. while(isset($podaci['answer_'. Zatim uzima max id od „results“ i prolazi kroz for petlju onoliko puta koliko ima odgovora u anketi i u tabelu „results“ unosi rezultat tj.$i])){ $odgovor = $podaci['answer_'. $questions_id = $id. `pitanja_id`. $this->set('imgPath'. ime ankete i broj odgovora.$i]. 'http://localhost/cake/'). '$result_id')"). } $questions_id++. $this->Poll->query("INSERT INTO answers (`odgovor`. $id = $ret[0]['max(id)']+1. '$questions_id'. `rezultati_id`) VALUES('$odgovor'. ukupan broj glasova za svaki odgovor i anketa_id da poveže odgovore sa anketom. if ($this->data) { $ret = $this->Poll->query("SELECT max(id) FROM questions"). `lang_id`. '{$podaci['lang']}'. $polls_id). } } 48 . foreach($this->data as $podaci){ $this->Poll->query("INSERT INTO questions (`id`. `anketa_id`. Ako postoje podaci uzima max id tabele polls i u tabelu polls smješta podatke tj.$this->set('poll_id'. function admin_add_an() { $this->set('rootPath'. $pitanje_id). `pitanje`)VALUES('$questions_id'. $i = 1. $result_id = $podaci['result_id_'.

a odgovore.odgovor FROM answers a. $ukupno = $this->Poll->findAll($page).php class ResultsController extends AppController { var $name = 'Results'. function ukupnoGlasaova($id ){ $page = array ('id' => $id). id pitanja i id rezultata upisuje u tabelu „answers“.rezultati_id = r. results r WHERE a.Funkcija admin_add_an() provjerava da li postoje podaci.lang_id = '$id'"). na stranu gdje se nalazi anketa.rezultat. 2. Varijabla $i se inkrementuje onoliko puta koliko imamo odgovora i $questions_id onoliko puta koliko ima jezika u bazi. tj. } Funkcija ukupnoGlasaova() vraća ukupan broj glasova i ispisuje ih na indexnu stranu. } Funkcija rezultati() vraća broj glasova za svaki odgovor u anketi.id AND a. 49 . id jezika i pitanje u tabelu „questions“. id jezika. upisuje id ankete. Ako postoje podaci uzima max id iz tabele „questions“. results_controller. prolazi kroz foreach petlju dok postoje podaci. a. } function inc($id) { $page = array ('id' => $id). function rezultati($id ){ return $this->Poll->query("SELECT r. return $ukupno[0]['Poll']['ukupno_odg'].

$ip_ = getenv ("REMOTE_ADDR"). Pomoću funkcije getenv() uzima ip adrese korisnika i snima ih u tabelu “checkip“ i postavlja cookie ako je korisnik glasao. "glasao"). } Funkcija inc() inkrementuje broj odgovora i ukupan broj glasova. $this->Result->query("UPDATE `results` SET `rezultat` = `rezultat` + 1 WHERE id = '$rez_id'"). setcookie("DNCCMSANKETA". tj. `poll_code`) VALUES ('$ip_'. if(isset($_COOKIE['DNCCMSANKETA'])) $uslov2 = false. else $uslov1 = true. $this->Result->query("INSERT INTO checkip (`IP`. $rez_id = $rez[0]['Result']['id']. vrši update tabele results i polls. function provjeraGlasanja(){ $ip_ = getenv ("REMOTE_ADDR"). $this->Result->query("UPDATE `polls` SET `ukupno_odg` = `ukupno_odg` + 1 "). 50 .$rez = $this->Result->findAll($page). else $uslov2 = true. ' ')"). if($this->Result->query("SELECT poll_code FROM checkip WHERE IP = '$ip_'")) $uslov1 = false.

lang_id = 1').php class QuestionsController extends AppController { var $name = 'Questions'. questions q WHERE q. Ako ima IP ili cookie ili oboje. 'http://localhost/cake/'). 3. U našem primjeru anketa_id = 1. function odgovori() { return $this->Answer->query('SELECT a. function admin_index() { $this->set('rootPath'. prikazuje reultate ankete. $this->set('imgPath'. } } ?> Controller answers ima samo funkciju odgovori() koja vraća odgovore i rezultati_id koji su povezani preko anketa_id.rezultati_id FROM answers a. land_id = 1 i pitanje_id u tabeli „answers“odgovara id-u u tabeli „questions“.php file-u.if(($uslov1) && ($uslov2)) return true. a. a ako ne prikazuje anketu i korisnik ima mogućnost glasanja.pitanja_id AND a. questions_controller.odgovor. else return false.id = a. 4. 'http://localhost/cake/img/'). pitanje_id i land_id. answers_controller. } Funkcija provjeraGlasanja() provjerava da li postoji korisnikova IP adresa u bazi i da li ima cookie. } function view($id = null) { 51 .php <?php class AnswersController extends AppController { var $name = 'Answers'.anketa_id = 1 AND q. Ova funkcija se poziva u /pages/display.

} } $this->Question->id = $id. Na admin strani kliknemo na link anketa 52 . function pitanje($id = 1. editovanje i brisanje ankete. } Funkcija pitanje() služi za ispis pitanja na indexnoj strani. Funkcija admin_index() ima istu funkciju kao u controller-u polls. Administrator kreira anketu. poziva se u /pages/display. $lang_id = 1) { $pitanje = array ('anketa_id' => $id. 7.php file-u. funkcija view() služi za prikaz pitanja na osnovu id-a. $this->Question->read()). 'lang_id' => $lang_id). Upustvo za servis Servis „Anketa“ sa aspekta adminstracijskog dijela treba da omogući kreiranje. $pitanje = $this->Question->findAll($pitanje). unosi naziv ankete i broj odgovora. $this->set('questions'. 1. zatim pitanje i odgovore. 3. return $pitanje[0]['Question']['pitanje'].

Zatim se otvara nova strana sa linkom za dodavanje nove ankete 3.2. anketa br. Admin unosi naziv ankete npr.1 i broj odgovora u anketi 53 .

Admin unosi pitanje i odgovore na više jezika tj.4. na sve jezike koje ima u bazi 54 .

55 .

prikažu se rezultati glasanja 4. Ako nema u bazi IP adrese i korisnik nema cookie-a. Korisnik posjećuje stranu 2. engleski. Ako korisnik pokuša drugi put glasati.Sa aspekta korisnika: 1. Servis je implementiran na 3 jezika (bosanski.glasanje . Provjerava se korisnikova IP adresa i cookie 3. njemački) i ima mogućnost dodavanja novi jezika. korisniku se prikazuju rezultati ankete Ključne mogućnosti servisa: .pregled rezultata ankete Aplikacija dozvoljava da korisnik može samo jednom glasati na anketi na osnovu IP adrese i cookie-a.kreiranje ankete . Ako postoji IP adresa ili cookie. nakon klika na dugmić “glasati“. Servis treba biti dostupan 24h svih sedam dana u 56 . dozvoljava se glasanje. prikazuje mu automatski rezultat ankete.

Anketa je prikazana na prezentacijskom dijelu Naziv: Cilj: Prioritet: Grupa korisnika: CASE2 . Admin kreira anketu na admin dijelu 2. Izvještaji: prezentacijski dio administracijski dio Usability: Lakoća korištenja servisa.glasanje Glasati na anketi Visok Gost 57 .kreiranje ankete Kreirati anketu da bi dobili informacije od korisnika Visok Admin Server mora biti online 1.sedmici. potrebno je osnovno poznavanje rada na računaru ( za kriranje ankete) i mogućnosti i znanje korištenja interneta ( za glasanje i pregled rezultata) Kategorije korisnika: obični korisnici (imaju mogućnost glasanja i pregleda rezultata) administratori ( imaju mogućnost kreiranja ankete) CASE: Naziv: Cilj: Prioritet: Grupa korisnika: Preduslovi: Scenario: CASE1. Servis nam treba omogućiti da dobijemo mišljenje korisnika o anketi „temi“ koju postavimo.

posjetiti stranicu za pregled rezultata Za gosta: 1. Provjera gostove IP adrese i cookie-a. automatski se prikazuju rezultati Za admina: 1. Gost posjećuje stranicu 2. gost Server mora biti online. Gost posjećuje stranicu 2. Ako prvi put glasa. gost mora biti online. korisnik mora biti online. 3. Na osnovu IP adrese i cookie-a daje se mogućnost glasanja ili pregleda rezultata Naziv: Cilj: Prioritet: Grupa korisnika: Preduslovi: Scenario: CASE3 – pregled rezultata Pregledati rezultate glasanje ankete Visok Admin. da nije prije glasao 1. Posjećuje stranicu 2.Preduslovi: Scenario: Server mora biti online. Analizira rezultate ankete Dokumentacija seminarskog: osnove CakePHP-a opis aplikacije MVC za servis „Anketa“ case-ovi servisa „Anketa“ 58 . za pregled treba kliknuti da dugnić „Pregled rezultata“ 3. posjetiti stranicu. Ako je već glasao.

59 .a uskoro bi trebao dobiti podršku za I18 arhitekturu. stabilnost. bez gubljenja fleksibilnosti. CakeAMFPHP za vezivanje na flash. MVC framework možemo iskoristiti za većinu aplikacija u PHP-u koje želimo na brzinu iskodirati i time sami sebi uštediti vrijeme i natjerati se da se držimo nekih standarda. Cakephp ima napravljene komponente za autentifikaciju. brute force protection. biznis logike i prezentacije. CakePHP developri rade na razvoju preko 100 projekata..… . Jedini nedostatak koji sam pročitala tokom istraživanja za seminarski je što se do sada core cakephp mijenjao nekoliko puta.. tako da ni implementacija ne može biti toliko različita. pagination. Primjenom frameworka se dobiva mnogo prednosti: portabilnost.višejezičnost. xcache. automatic layout switcher. MVC arhitektura pomaže sa čistim predstavljanjem database funkcijalnosti.Primarni cilj seminarskog je bio predstaviti strukturu frameworka koji omogućava PHP korisnicima svih nivoa brzi razvoj web aplikacija. no s verzijom 2.. html helperi. ajax.ZAKLJUČAK CakePHP je framework koji ima podršku za puno stvari kao što je memcache.. ubrzanje razvoja...0 bi se to trebalo stabilizirati. Svi MVC framework-ovi nastoje zadovoljiti iste ciljeve i u MVC filozofiji su pravila jasna.

org www. 4.org 60 .forgephp.org http://bakery. CakePHP Manual PHP Design Patterns ETF Sarajevo. SPIS 2006 Cakesheet Web stranice: www. 2.mi3dot.LITERATURA 1.cakephp.cakephp.org www. 3.org www.wikipedia. RI.

Sign up to vote on this title
UsefulNot useful