Zavolání metody modelu z templatu?
- snakeeater
- Člen | 18
Zdravím,
jsem úplně nový v Nette a zkouším se tento framework naučit
prostřednictvím tutoriálů zde na webu. Udělal jsem si blog podle tutoriálu.
Inspiroval jsem se dalšími náměty uvedenými na konci článku. Vše se mi
povedlo, jediné, u čeho jsem se trochu zaseknul, byl výpis počtu
komentářů u jednotlivých postů blogu. Nakonec jsem to vyřešil pomocí
funkce COUNT(), tj. zjišťuju počet komentářů ve stejném dotazu, v jakém
získávám řádky jednotlivých postů z databáze.
Ale k věci. Říkal jsem si, jestli by šlo vůbec udělat, abych získal
počet komentářů až u výpisu jednotlivých postů… tj:
<?php
<div id="posts">
{if count($posts)}
{foreach $posts as $post}
// NEKDE TADY BYCH POMOCI NAPR. $POST[ID] VYTAHNUL KOMENTARE Z DATABAZE VZTAHUJICI SE K POSTU
<div class="post">
<h3>{$post['title']}</h3>
<small>Přidáno {$post['date']|date}</small>
<p>{$post['body']|truncate:300}</p>
<a href="{link single, $post['id']}">Více…</a>
</div>
{/foreach}
{else}
Zatím nebyl napsán žádný článek.
{/if}
</div>
?>
Slo by to? A je to spravny Nette pristup? Predpokladam, ze ne, proto by me
zajimalo, jak by to bylo idealni. Tohle je jednoduchy pripad, ve slozitejsich
situacich si nejsem jisty, jestli by bylo vhodne vse cpat do jednoho dotazu.
Dekuji za odpovedi
- Mesiah
- Člen | 240
Ne, tohle je špatně. Porušuješ chování MVC(P) volaš ve view něco o čem view neví a ani vědět nemá.
Na tyto situace jsou v nette komponenty (Control), v kostce jde o logickou
součást webu/stránky/aplikace. V temlate k akci zavoláš jen
{widget comments}
a tím se zavolá komponenta.
Editoval Mesiah (16. 10. 2010 23:09)
- snakeeater
- Člen | 18
Ale v tom miste, kde mi doporucujes vlozit komponentu, chci vypsat jen proste cislo vyjadrujici pocet komentaru u postu. To na to musim vytvaret specialni tridu? Ono totiz proste:
<?php
public function createComponentComments($name,$post_id)
{
$komentaru = CommentsModel::count($post_id);
return $komentaru;
}
?>
…nefunguje, protoze (predpokladam) nikde nevytvarim objekt implementujici rozhrani IComponent. Zkousel jsem tam pridat $this[‚comments‘] = $komentaru;, coz samozrejme taky nefunguje… Vim, ze to je docela zaklad, ale priznejme si, dokumentace Nette je velice chaba…
Editoval snakeeater (17. 10. 2010 14:16)
- Mesiah
- Člen | 240
Proč ti to nevrací model k postům? Pokud Ti jde jen o počet komentářů, tak tuhle informaci ti dokáže vrátit model, který ti dává posty.
Edit: tohle ti vrací ten tvůj model, tak to jen „pošli“ do view. Pro složitější „požadavky autora“ se využívají komponenty…
Editoval Mesiah (17. 10. 2010 14:25)
- snakeeater
- Člen | 18
Ano, tak to mam ted udelane, ze v jednom dotazu se ptam zaroven i na komentare:
<?php
return dibi::fetchAll('
SELECT posts.id,title,posts.body,posts.date,COUNT(comments.id) AS komentaru
FROM posts LEFT JOIN comments ON posts.id = comments.post_id
GROUP BY posts.id,title,posts.body,posts.date
ORDER BY posts.date', dibi::DESC
);
?>
Takze vim, jak to udelat timto zpusobem, jen premyslim, jak to delat ve slozitejsich pripadech, kdy bych chtel rekneme pri vypisu vsech postu zaroven vypsat pod kazdym postem vsechny vztahujici se komentare. To je trochu osemetne resit to vsechno v jedinem dotazu, jak jsem to resil ted, ne? Proto jsem premyslel, jak vyvolat dalsi dotaz pro kazdy radek vraceny pomoci foreach. Navic si treba predstav, ze bych chtel vypsat vsechny ty komentare jen u tech postu, jejichz nazev napriklad zacina na slovo „Post“. Tudiz bych se mel az ve chvili, kdy v iteraci foreach pracuji s jednotlivymi daty o postu, rozhodnout, zda-li vypsat pro tento post komentare nebo ne. Nebo to ma doopravdy vsechny tyhle veci resit uz model?
- Mesiah
- Člen | 240
Takze vim, jak to udelat timto zpusobem, jen premyslim, jak to delat ve
slozitejsich pripadech, kdy bych chtel rekneme pri vypisu vsech postu zaroven
vypsat pod kazdym postem vsechny vztahujici se komentare.
- K tomu jsou komponenty
To je trochu osemetne resit to vsechno v jedinem dotazu, jak jsem to resil
ted, ne?
- Jo
Nebo to ma doopravdy vsechny tyhle veci resit uz model?
- Vždycky to řeší model (nebo aspoň by měl)
- Ani
- Člen | 226
Mesiah napsal(a):
Ne, tohle je špatně. Porušuješ chování MVC(P) volaš ve view něco o čem view neví a ani vědět nemá.
Na tyto situace jsou v nette komponenty (Control), v kostce jde o logickou součást webu/stránky/aplikace. V temlate k akci zavoláš jen
{widget comments}
a tím se zavolá komponenta.
Ani bych neřekl, že to jde proti MVC. Z view si do modelu šahat můžeš, když ti ten model předá control. Alespoň takhle to vidim já.
Prostě si do view předáš rovnou model a na něm voláš metody. Není třeba to přeposílat přes control. Obzvlášť, když jako model použiješ nějakou chytrou třídu, třeba na principu notorm.
- westrem
- Člen | 398
snakeeater napsal
Samozrejme, ze to ma riesit model, pokial su komentare logicka cast clankov,
ma model vediet ako ich ziskat, tzn v konecnom dosledku by si mal mat metodu
napr: getAllPosts()
, ktora ti vrati zoznam postov, ktore uz budu
mat aj injektovane komentare. Toto sa da riesit 2 SQL dotazmi, menej to
imho nejde.
Co sa tyka potom view, kludne maj jeden obecny template pre vypis a v kazdej metode renderX to nastav pomocou
$this->setView('yourCommonView');
Tymto pokryvas uplne vsetko co chces. Ak chces len posty, ktore zacinaju na
post
tak si ich v render metode pomocou modelu vytiahni a sablona
ich len vykresli.
Tak isto ak chces komentare len niekde, modelom si urci kde, vytiahni si dane clanky (ostatne vytiahnes tiez ale bez komentarov) a vo view len vypisujes, pricom ak bude mat post komentare tak ich vypises inak ee (je jedno ci ich fyzicky ma v DB, pokial ich modelom nevytiahnes, sablone sa to bude javit, ze clanok ziadne komenty nema)
- snakeeater
- Člen | 18
Mesiah napsal(a):
Takze vim, jak to udelat timto zpusobem, jen premyslim, jak to delat ve slozitejsich pripadech, kdy bych chtel rekneme pri vypisu vsech postu zaroven vypsat pod kazdym postem vsechny vztahujici se komentare.
- K tomu jsou komponenty
To by pro me bylo vskutku pohodlne delat to pres komponenty, ale pokud to chapu dobre, tak komponenta jde udelat jen z objektu a ja vazne netusim, jak poslat retezec (tj nejaky vypis co mi vyhodi ta komponenta) jako objekt. kazdopadne, budu to jeste hodne studovat, zda se, ze mam porad mezery :))