4. Tvoríme CMS s CakePHP - Model
V minulej časti seriálu sme si vysvetlili srdce frameworku Active Record. Od dnešnej časti sa pustíme do programovania nášho CMS a začneme návrhom databáze a vytvorením databázovej vrstvy našej aplikácie tzv. Modelu.
2. Konvencie CakePHP
Aby sme vedeli správne navrhnúť databázu, a CakePHP na jej základe správne chápal väzby medzi tabuľkami, je potrebné poznať konvencie pre návrh databáze. Čo myslíme tým, aby CakePHP správne chápal väzby medzi tabuľkami? Znamená to, že ak budeme mať databázu správne navrhnutú, framework bude automaticky rozpoznávať cudzie kľúče, primárne kľúče a väzby medzi tabuľkami, a nebudeme ich musieť pre každú tabuľka explicitne zadávať.
Ešte je dobré poznamenať, že je veľmi rozumné zadávať názvy tabuliek, modelov atď. v anglickom jazyku. CakePHP automaticky chápe anglické jednotné a množné čísla, takže sa vyhneme zbytočným nastavovaniam (samozrejme je možné zadávať názvy aj v národných jazykoch, ale je to práca naviac a my preto budeme používať anglické konvencie).
Názvy tabuliek
Názvy tabuliek sa zapisujú pomenovaním v množnom čísle jednotiek, ktoré
uchovávajú. Napríklad máme tabuľku, ktorá uchováva články, preto musí
byť táto tabuľka pomenovaná v množnom čísle, v našom prípade
articles.
Primárny kľúč
Primárny kľúč sa v tabuľkách označuje pomenovaním id. Taktiež
platí, že môžeme používať aj iné pomenovanie pre primárny kľúč, ale
opäť to musíme nastaviť.
Cudzie kľúče
Cudzie kľúče sa sa v tabuľkách označujú podľa tabuľky, kde sa pôvodne
nachádzajú. Predstavme si, že každý článok má svojho autora. Čiže
budeme mať dve tabuľky a to articles a users. V tabuľke
articles sa bude potom pochopiteľne nachádzať cudzí kľúč
z tabuľky users a to pomenovaním user_id. Čiže nám je
hneď zrejmé, že cudzí kľúč sa tvorí podľa konvencie
jednotne_cislo_tabulky_cudzieho_kluca_id.
Názvy atribútov
Ešte spomeniem, že je celkom vhodné, aby sa atribút názov
pomenovával ako name. Oceníme to najmä pri generovaní select boxov
vo väzbách 1:N, kde si budeme chcieť napríklad pri článku zvoliť
kategóriu výberom z niekoľkých možností.
Spojovacia tabuľka pri väzbe N:M
Tabuľky ktoré sú vo väzbe N:M abecedne zoradíme a následne novú tabuľku
pomenuje podľa konvencie
nazov_prvej_tabulky_nazov_druhej_tabulky. Predstavme si, že náš
článok má N nálepiek a jedna nálepka môže byť v M článkoch. Máme
teda tabuľky pomenované articles a tags a následne
vytvoríme spojovaciu tabuľku, ktorú pomenujeme articles_tags.
Cudzie kľúče do spojovacej tabuľky vytvoríme podľa konvencií, ktoré sme
si definovali vyššie.
2. Navrhujeme databázu
Na obrázku môžeme vidieť našu databázu pre náš nový redakčný systém, ktorú sme navrhli na základe vyššie definovaných konvencií

3. Modely tabuliek
Databázu už máme správne navrhnutú a môžeme sa pustiť do tej najzaujímavejšej časti, a to je návrh databázovej vrstvy našej aplikácie tzv. Modelu, čo je jedna z troch častí návrhového vzoru Model View Controller. Ako sme si už spomínali v predchádzajúcom článku, modely sa umiestňujú do adresára app/models. V našom prípade vytvoríme 4 modely, i keď máme tabuliek spolu 5. Ako sme si už spomínali, model sa pre spojovaciu tabuľku nevytvára a kedže máme databázu správne navrhnutú, všetku potrebnú prácu v súvislosti so spojovacou tabuľkou vykoná Cake automaticky. Predtým, než začneme vytvárať samotné modely treba poznamenať, že model sa pomenováva ako jednotné číslo názvu tabuľky, čiže napr. pre našu tabuľku articles sa bude model nazývať article a bude umiestnený v súbore app/models/article.php
Model Article umiestený v súbore /app/models/article.php
<?php
class Article extends AppModel {
var $name = 'Article';
var $useTable = 'articles';
var $validate = array(
'title' => VALID_NOT_EMPTY,
'text' => VALID_NOT_EMPTY,
'user_id' => array('numeric'),
'created' => array('date')
);
var $belongsTo = array('User');
var $hasAndBelongsToMany = array('Tag');
var $hasMany = array('Comment');
}
?>
Model User umiestnený v súbore /app/models/user.php
<?php
class User extends AppModel {
var $name = 'User';
var $useTable = 'users';
var $validate = array(
'username' => VALID_NOT_EMPTY,
'password' => VALID_NOT_EMPTY
);
var $hasMany = array('Article');
}
?>
Model Comment umiestnený v súbore /app/models/comment.php
<?php
class Comment extends AppModel {
var $name = 'Comment';
var $useTable = 'comments';
var $validate = array(
'title' => VALID_NOT_EMPTY,
'text' => VALID_NOT_EMPTY,
'username' => VALID_NOT_EMPTY,
'article_id' => array('numeric')
);
var $belongsTo = array('Article');
}
?>
Model Tag umiestnený v súbore /app/models/tag.php
<?php
class Tag extends AppModel {
var $name = 'Tag';
var $useTable = 'tags';
var $validate = array(
'name' => VALID_NOT_EMPTY,
'seo_link' => VALID_NOT_EMPTY
);
var $hasAndBelongsToMany = array('Article');
}
?>
Ako môžeme vidieť vyššie, v kóde sme už uviedli aj validačné kritéria, ktoré sme si priblížili už v predchádzajúcej časti seriálu. Využívať ich však budeme až v časti nasledujúcej, v ktorej sa budeme venovať vytváraniu zvyšných dvoch častí architektúry MVC a to Controller a View.
Aby sme si mohli otestovať, či sme našu databázu skutočne navrhli správne, môžeme využiť tzv. scaffolding. Cake nám pomocou scaffolding dokáže na základe vytvorených modelov automaticky skonštruovať ukážkovú aplikáciu, pomocou ktorej môžeme otestovať, či nám väzby v našej tabuľke fungujú správne. Potrebujeme však ku každému modelu vytvoriť Controller, v ktorom určíme, že Cake má používať na vytvorenie aplikácie scaffolding (ako som už spomínal vyššie, controlleru sa budeme venovať v nasledujúcej časti, preto nám teraz stačí bez hlbšieho vysvetlenie skopírovať jednotlivé kódy konkrétnych súborov s controllermi).
Controller Articles umiestnený v súbore /app/controllers/articles_controller.php
<?php
class ArticlesController extends AppController {
var $name = 'Articles';
var $scaffold;
}
?>
Controller Users umiestnený v súbore /app/controllers/users_controller.php
<?php
class UsersController extends AppController {
var $name = 'Users';
var $scaffold;
}
?>
Controller Comments umiestnený v súbore /app/controllers/comments_controller.php
<?php
class CommentsController extends AppController {
var $name = 'Comments';
var $scaffold;
}
?>
Controller Tags umiestnený v súbore /app/controllers/tags_controller.php
<?php
class TagsController extends AppController {
var $name = 'Tags';
var $scaffold;
}
?>
Skúste si zadať do url prehliadača napríklad adresy
www.tvoja-adresa/articles, www.tvoja-adresa/comments alebo www.tvoja-adresa/users.Aké jednoduché však? Scaffolding je mocný nástroj tohto frameworku a dokáže nám značne uľahčiť prácu pri návrhu zložitejších vzťahov v databáze, preto určite stojí zato ho v rannom štádiu vývoja používať.
Rád uvítam vaše námety a pripomienky v diskusii k článku.
Stiahnuť zdrojové kódy k článku
Súvisiace články
-
Kategórie
- Tipy a triky (28)
- Články (8)
- Fantom CMS (4)
- Zábava (2)
- Začíname s CakePHP (6)
-
Najčítanejšie články
-
Novinky
-
Seriál o CakePHP na www.debug.sk
15. 10. 2008
Od 7. októbra vychádza nový seriál o CakePHP na serveri zameranom na programovanie s názvom Debug.sk Autorom seriálu je autor tohto webu a kto by mal záujem, môžete daný seriál podporiť jeho prečítaním.
-
-
Nálepky
-
Nedávne komentáre
-
Rss kanály

Komentáre k článku
Nový komentár
Titulok: Nazov atributov
Autor: huco
Vytvorený: 18. 03. 2008 11:47
Nie je mi jasne, preco je vhodné, aby sa atribút názov pomenovával ako name. Mohol by si uviest nejaky konkretnejsi priklad s vysvetlenim?
Titulok: RE: Nazov atributov
Autor: Tibor
Vytvorený: 18. 03. 2008 17:49
Odpoved najdes v tomto clanku, ktory som pisal pred nedavnom. Ide v podstate len o to, ze zas by si musel nieco nastavovat navyse a pritom to nie je vobec potrebne, ked to dokaze Cake pochopit automaticky
http://ims.rockretail.com/…generatelist
Titulok: Vazba v třídě Article
Autor: Andrea
Vytvorený: 19. 03. 2008 10:14
Super seriál. Mám jednu otázečku:
V třídě Article nemělo by být také:
var $hasMany = array(‚Comment‘);
protože je mezi nimi vazba 1:N nebo stačí, když je vazba uvedená pouze v třídě Comment?
Titulok: RE: Vazba v třídě Article
Autor: Tibor
Vytvorený: 19. 03. 2008 11:58
Dakujem za pochvalu :-)
Ano ta vazba tam ma byt, uz je to opravene. Komentare by sice bolo mozne pridat k clanku, ale bez urcenia tejto vazby v modely Article by nebolo mozne zobrazit tieto komentare k clanku.
Opravil som taktiez validacne kriteria, ktore neboli spravne.
Titulok: Diagram
Autor: pointer
Vytvorený: 19. 03. 2008 14:19
Ahoj, v akom programe si „namaloval“ ten DB diagram (ER model) ?
Titulok: problem s DELETE
Autor: Andrea
Vytvorený: 19. 03. 2008 14:53
Ahoj, zkouším cakephp podle článku. Vytvořila jsem v MySQL (Verze MySQL: 4.0.26-nt-log) všechny tabulky, přesně podle článku. Ale mám problémy s editací, přesněji řečeno s mazáním položek. Píše to následující hlášku:
Query: DELETE
ArticlesTagFROMarticles_tagsASArticlesTagWHEREArticlesTag.article_idIN (1)Warning (512): SQL Error: 1066: Not unique table/alias: ‚articlestag‘ [CORE\cake\libs\model\datasources\dbo_source.php, line 440]
5 queries took 3 ms Nr Query Error Affected Num. rows Took (ms) 1 SELECT COUNT(*) AS
countFROMarticlesASArticleWHEREArticle.id= 1 1 1 1 2 UPDATEarticlesASArticleLEFT JOINusersASUserON (Article.user_id=User.id) SETArticle.id= 1,Article.title= ‚clanek 1‘,Article.text= ‚text článku‘,Article.user_id= 1 WHEREArticle.idIN (1) 1 1 3 SELECTArticlesTag.article_idFROMarticles_tagsASArticlesTagWHEREarticle_id= 1 1 1 0 4 DELETEArticlesTagFROMarticles_tagsASArticlesTagWHEREArticlesTag.article_idIN (1) 1066: Not unique table/alias: ‚articlestag‘ 0 5 INSERT INTOarticles_tags(article_id,tag_id) VALUES (1,1) 1 1Vím, že kdyby příkaz DELETE byl takto: DELETE FROM
articles_tagsWHEREarticles_tags.article_idIN (1)tj bez aliasu, tak to projede. Podle internetu nejsem sama, ale řešení jsem nenašla.
Titulok: RE: Diagram
Autor: Tibor
Vytvorený: 19. 03. 2008 15:02
Jedna sa o netbeans http://www.netbeans.org/
Skusal som ho prvykrat, ale moc sa mi tam to uml nepozdava. Uvidime, ked pride verzia 6.1
Titulok: RE: problem s DELETE
Autor: Tibor
Vytvorený: 19. 03. 2008 15:28
Jedna sa pravdepodobne o tento problem https://trac.cakephp.org/ticket/3977
Aku verziu cake pouzivas? Skus si bud nahodit najnovsiu verziu cake, co je 1.2.0.6311-beta alebo skus novsiu verziu mysql.
Tieto problemy sa objavuju vo verzii mysql 4.
Ja osobne pouzivam cake 1.2.0.6311-beta a mysql 5 a tieto problemy nemam.
Titulok: problem s DELETE
Autor: Andrea
Vytvorený: 19. 03. 2008 15:41
Děkuji. Použila jsem poslední 1.2.0.6311-beta verzi. Ani 1.2…alfa ani 1.1 to nedělala. Bohužel musím zůstat u MySQL4 kvůli hostingu.
Titulok: chaba podpora objektov...
Autor: ropman
Vytvorený: 04. 04. 2008 10:42
neskutocne mi v cakephp vadi ze vsetky metody ktore vracaju zaznamy z databazy typu find(), nie su objekty ale len polia. kym sa toto nezmeni, tak u mna pouzitie cakePHP neprichadza do uvahy… tym padom sa nedaju pouzit ani setters a getters atd… som zastancom „convention over configuration“ a tak som bol na tento framework velmi zvedavy, tymto zasadnym neduhom ma vsak sklamal…
Titulok: RE: chaba podpora objektov...
Autor: Tibor
Vytvorený: 09. 04. 2008 15:12
No to je pravda, ze active record objekty nevracia, ale myslim si, ze z pohladu view je to zas velmi dobra moznost mat k dispozicii viacrozmerne polia…
Titulok: kodovanie
Autor: st3n
Vytvorený: 02. 05. 2008 19:19
zdravim, mam otazocku..ked pisem do suborov .ctp tak mi to dava zle formatovanie, pritom je nastavene utf-8…editujem to v ps-pade kde davam tiez utf-8 v com je problem? dakujem a co sa tyka databazky zobrazuje data spravne ale ked sa pozriem na obsah tabulky cez phpMyAdmin tak tam mam zle kodovanie… vsetko mam na localhoste cez XAMPP
dik za pomoc
Titulok: sort a filter
Autor: st3n
Vytvorený: 02. 05. 2008 20:30
problem s kodovanim som vyriesil, tie subory boli zle naformatovane… neviem preco ale uz to ide…
mam ale 2 otazocky: 1 potrebujem spravit filter nasledovne:ked mam zobrazene udaje v databaze-tabulku, ze by tam bol textbox do ktoreho po tom ako by sa zadal text by prehladal celu databazu a vratil len zaznamy kde by nastala zhoda 2 druha vec sortovanie tabulky podla stlpcov ako je to v scaffolding… ako to spravit?
dakujem velmi pekne za pomoc, potrebujem to na projekt do skoly…
Titulok: filter
Autor: st3n
Vytvorený: 02. 05. 2008 22:07
takze to sortovanie je lahke to uz mam: $paginator->sort(); ale co ten filter/search ? hladal som vselikde na nete a teda nic moc som nenasiel, pritom by to podla mna mal byt jeden zo zakladnych objektov…
Titulok: vyhladavanie
Autor: Tibor
Vytvorený: 04. 05. 2008 23:23
Bohuzial cake nedisponuje vstavanym vyhladavacim enginom, takze uvadzam niekolko moznosti, na ktore som doposial narazil
Jedna z moznosti je pouzit lucene vyhladavanie
http://bakery.cakephp.org/…-application
Druha moznost je vytvorit si indexy na stlpce priamo v databaze v ktorych sa bude vyhladavat a normalne pouzivat metodu find() ktora ma ako prvy parameter conditions co by bol hladany vyraz.
Urcite pojde pouzit aj fulltext, ktory maju implementovane samotne databazy, avsak to uz zrejme bez custom query nepojde.
Kedze to mas ako nejaky jednoduchy projekt, odporucal by som ti druhu moznost.
Titulok: filter
Autor: st3n
Vytvorený: 11. 05. 2008 23:59
hladal som na internete ale nejako… neviem, nejaky podrobnejsi postup by som potreboval na ten filter
Titulok: RE:filter
Autor: Tibor
Vytvorený: 12. 05. 2008 15:40
No uplne jednoducho beznym find()
Kde $this → data[„Search“][„text“] pochadza z inputu Search.text, cely kod je umiestneny napr. v controllery Products a v databaze je vytvorena tabulka products so stlpcom nazvanym name
Samozrejme je este dobre na v tabulke products vytvorit index na stlpec name
Titulok: pekne
Autor: st3n
Vytvorený: 12. 05. 2008 18:18
no to je sice pekne, dakujem, ale nepomohlo mi to…
Titulok: kontakt
Autor: st3n
Vytvorený: 12. 05. 2008 20:25
nejaky kontakt by sa nedal vymenit? je nas viac co robime projekty v cakephp a velmi by nam to pomohlo :) moje icq: 269324339
Titulok: relacie mezdi tabulkami
Autor: ajpi
Vytvorený: 22. 05. 2008 02:21
Dobry, potreboval by som pomoc s vypisom obsahu tabuliek, mam totiz: modely: land.php
<?php class Land extends AppModel {
var $name = ‚Land‘;
var $validate = array(‚id‘ ⇒ array(‚rule‘ ⇒ array(‚minLength‘, 1)),‚shortname‘ ⇒ array(‚rule‘ ⇒ array(‚minLength‘, 1)),‚fullname‘ ⇒ array(‚rule‘ ⇒ array(‚minLength‘, 1)));
var $hasMany = ‚Player‘; } ?>
a player.php
<?php
class Player extends AppModel {
var $name = ‚Player‘;
var $validate = array(‚name‘ ⇒ array(‚rule‘ ⇒ array(‚minLength‘, 1)),‚surname‘ ⇒ array(‚rule‘ ⇒ array(‚minLength‘, 1)),‚land_id‘ ⇒ array(‚rule‘ ⇒ array(‚minLength‘, 1)));
var $belongsTo = ‚Land‘; }
?> Tabulka players obsahuje polia id, name, surname, land_id. Tabulka lands obsahuje polia id, name a fullname. Potreboval by som vypisat obsah tabulky players tak, aby mi vypisalo name, surname a land_id. nemam problem s name a surname, ale land_id potrebujem tak, aby mi nevypisalo id cislo z tabulky land, ale k tomu prisluchajuce meno, napr. v tabulke lands mam: id=1, name=SK, fullname=slovensko do tabulky players som pridal: id=1, name=peter, surname=novak, land_id=1. Vystup by som potreboval: name=peter, surname=novak, land_id=slovensko. Vlastne neviem co mam dat do view aby mi to islo. V controller som pouzil nasledovnu funkciu kvoli sortovaniu:
function index() {
$this->set(‚players‘, $this->paginate(‚Player‘));
}
Potreboval by som to rychlo :S Tiez by sa mi hodil nejaky kontakt na Vas. Dakujem velmi pekne.
Titulok: RE:ajpi
Autor: Tibor
Vytvorený: 22. 05. 2008 09:22
Dobry den. V subore view si jednoducho pozrite co ste si do view poslali napr. jednoducho takto
A urcite uvidite, ze v premennej $players mate pole, ku ktoremu mozete pristupovat takto
Titulok: RE: RE: ajpi
Autor: Ajpi
Vytvorený: 22. 05. 2008 12:03
Dakujem velmi pekne, Vy ste fakt macher :) Uz by som potreboval iba jednu vec, neda sa nejak spravit to, ked pridavam novy player, aby sa mi zobrazilo scroll box s aktualnymi hodnotami v tabulke lands namiesto obycajneho inputboxu pre pole land_id? Ako to je napr. aj v MS Access. Cize by som do pole players → land_id mohol vyberat z danych hodnot, a nie pisat rucne.
Prepacte ze tolko otravujem ale som uplny zaciatocnik s cake a nezvykavam robit vela ani v php. Dakujem este raz :)
Titulok: scroll box
Autor: Ajpi
Vytvorený: 24. 05. 2008 14:32
Cize mam spojene tie tabulky a funguju aj dobre, cez scaffold mi to robi perfektne, mozem vyberat iba z tych zaznamov co tam zatial mam v tej druhej tabulke, lenze ja by som potreboval kod ako spravit manualne ten scrollbox, a nie cez scaffold :(
Hladal som na nete, ale nic uzitcne som nenasiel… :(
Titulok: RE:scroll box
Autor: Tibor
Vytvorený: 25. 05. 2008 11:12
Takze tatko. Do suboru app/controllers/players_controller.php vloz tento kod
A vo view scroll box vytvor klasicky
Co tak si prestudovat zdrojove kody napr. mojho Fantoma, co je redakcny system na ktorom bezi tento blog alebo zamerat sa na cake console, ktora ti znacne ulahci pracu a vygeneruje ti hotove zdrojove kody na zaklade vazieb v databaze atd.
Titulok: vlastne sql a reakcia cakephp nan
Autor: jozko
Vytvorený: 26. 05. 2008 19:19
ked si robim vlastny sql prikaz a dam tam napriklad SUM(tabulka.hodnota) AS spolu ako potom mam k tomuto pristupovat vo view ked to chcem vypisat? surne, dakujem za pomoc
Titulok: RE: vlastne sql a reakcia cakephp nan
Autor: Tibor
Vytvorený: 27. 05. 2008 10:52
Vo view si daj metodou var_dump() vypisat obsah premmenej, ktoru si si poslat do view, to je predsa jednoduche
A hned vidis, co sa ti do view dostalo. Z vlastneho query by si mal dostat troj rozmerne pole, ku ktoremu pristupujes $exam[0][0][‚sum‘]
Avsak najjednoduchsie pouzitie sum je v metode findAll()
Taktiez dostanes rovnake troj rozmerne pole, ku ktoremu pristupis vo view takto $exam[0][0][‚sum(income)‘]
Titulok: Rýchlosť písania seriálu
Autor: w3q
Vytvorený: 05. 06. 2008 20:36
Ahojte, nechcem kritizovať, ale bol by som rád ak by tento seriál vychádzal rýchlejšie. Tibo, neber to ako buzeráciu, proste ten seriál je super, a mám problém čakať na dalšiu časť. :D Je fakt super.
Titulok: RE:Rýchlosť písania seriálu
Autor: Tibor
Vytvorený: 06. 06. 2008 00:53
No v provom rade slo o dohodu s abclinuxu.cz pockat, kym nevyjdu clanky aj u nich.
Taktiez som teraz dost zaneprazdneny, ale buduci tyzden planujem vydat niekolko clankov a jednym z nich by malo byt aj pokracovanie mojho serialu.
Takze musis este chvilku vydrzat :-)
Titulok: jak dostat model do vlastni komponenty
Autor: hAdam
Vytvorený: 10. 07. 2008 15:07
Zdravim nevedel by tu nekdo jak dostat model do vlastni komponenty. jedno reseni sem nasel na http://debuggable.com/…4647cbdd56cb
toto reseni mi bohuzel nepomohlo .. cake nebyl schopen model najit… navic jedna funkce pouzita v tomto reseni konkretne loadModel($modelClass) je podle cakephp 1.2 nepripustna