Zavolání metody modelu z templatu?

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
snakeeater
Člen | 18
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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.

phx
Člen | 651
+
0
-

Osobne jsem pro 1 dotaz. Pri vypisu vsechn clanku, rekneme 1000, by se mistlo 1 sloziteho dotazu provedlo 1001 a to bude urcite nakladnejsi!

westrem
Člen | 398
+
0
-

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
+
0
-

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 :))