Jak spočítat počet příspěvků když mám tři tabulky?

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

Dobrý večer,
programuji svojí první aplikaci v nette, je to fórum a už dva dny si lámu hlavu jak docílit toho, abych vypsal na úvodní stránku počet příspěvků u každé kategorie. Kdybych používal jenom dvě tabulky, tak by to bylo snadné ale se třemi si nevím rady.

Pro výpis počtu vláken v jednotlivých kategoriích jsem použil jednoduché {$category->related(‚forum_threads‘)->count()}, ale u těch příspěvků je potřeba se prokousat ještě třetí tabulkou a to nevím jak jednoduše udělat. Mohl bych zkusit to nějak složitě spočítat třeba procházením všech záznamů v tabulce, ale to mi moc elegantní nepřijde, asi by to dost zatěžovalo server.

Je možné to nějak elegantně spočítat a vypsat, nebo bude lepší ten počet akorát ukládat do tabulky, měnit a pak akorát posílat na výstup?

hrach
Člen | 1838
+
0
-

pisu z hlavy, neco jako:

foreach ($conn->table('forum_categories') as $cat) {
	echo    "name: $category->name".
		"count of posts: ". $cat->count('forum_threads:forum_posts:id');

}

Editoval hrach (26. 12. 2011 23:40)

hrach
Člen | 1838
+
0
-

nicmene to provede pro kazdou kategorii dalsi select na count, nejlepsi bude:

$categories = $conn->table('forum_categories')
	->select('forum_categories.*')
	->select('COUNT(DISTINCT forum_threads:forum_posts:id) as postCount')
	->group('forum_categories.id');

foreach ($categories as $category) {
	echo    "name: $category->name".
		"count of posts: $category->postCount";
}

Editoval hrach (26. 12. 2011 23:40)

Pilda
Člen | 52
+
0
-

hrach: díky moc, zkusím to.

bojovyletoun
Člen | 667
+
0
-

Všiml jsem si dvojtečky v zápisu tabulek, mohl by to prosím někdo přidat do dokumentace? Ze zdrojáku jsem si všiml, že jde o zpětné reference (many, referencing,…). Co by tedy dělal dotaz, kdyby tam bylo forum_threads:forum_posts.id?

Hrachovi chci taky poděkovat za velké vylepšení nette database

Editoval bojovyletoun (27. 12. 2011 0:11)

Pilda
Člen | 52
+
0
-

Píše mi to chybu

PDOException #42000

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‚:forum_posts:id) as postCount FROM forum_categories GROUP BY `forum_categories‘ at line 1

Není tam někde nějaký překlep, nebo něco? Nette používám verzi 2.0 betta 2.

Pro jistotu uvádím přesný zápis:

Presenter:

<?php
    public function renderDefault() {

        $this->template->categories = $this->getService('model')->getForumCategoriesTable()
        ->select('forum_categories.*')
        ->select('count(DISTINCT forum_threads:forum_posts:id) as postCount')
        ->group('forum_categories.id');
    }
?>

Šablona

<table>
<tr><th>Kategorie</th><th>Téma</th><th>Přís.</th></tr>
{foreach $categories as $category}
<tr>
 <td><a n:href="Category $category->id">{$category->name}</a><br>{$category->description}</td>
 <td>{$category->related('forum_threads')->count()}</td>
 <td>{$category->postCount}</td>
</tr>
{/foreach}
</table>

Editoval Pilda (27. 12. 2011 0:53)

hrach
Člen | 1838
+
0
-

@bojovyLetoun:

  • jo, do dokumentace to samozřejmě všechno chci dát… :)
  • zpětné joiny (aka join ve smyslu hasMany) je port z notorm, bohužel taky ne příliš zdokumentovaný a přidán v podstatě na moji zmínku právě ve stejném případu, jako řeší @pilda.
  • ta syntaxe, co si popsal forum_threads:forum_posts.id je velmi zajimavý oříšek, který jsem se už taky zabýval. Jde to, že parser teď vždy vezme „token“ s tím symbolem, tedy „forum_threads:“, „forum_posts:“ a podle toho uděla ten join, muselo by se to tedy změnit na „:forum_threads:forum_posts“, což už by dávalo větší smysl i naznačením, že je to obráceně, ale zase tam není (a ono je to tak asi i názornější) ten sloupec id, což na druhou stranu může někoho zase mást oproti klasickému zápisu…

@Pilda
jo, to bude ten problém, že v betě 2 to ještě nebude implementované.

hrach
Člen | 1838
+
0
-

@pilda
jo a zkus pak jeste toto, aby se nedelal dalsi dotaz:

$this->template->categories = $this->getService('model')->getForumCategoriesTable()
->select('forum_categories.*')
->select('count(DISTINCT forum_threads:forum_posts:id) as postCount')
->select('count(DISTINCT forum_threads:id) as threadCount')
->group('forum_categories.id');
<td>{$category->threadCount}</td>
Pilda
Člen | 52
+
0
-

hrach:
a kdy pak, v betě 3? Zkoušel jsem nejnovější build z gitu a po zprovoznění mi to stejně nešlo. Možná jsem udělal něco špatně, nevím stáhnul jsem si hlavní build + sandbox a zkombinoval.

hrach
Člen | 1838
+
0
-

stahni tu dole nightly build: https://nette.org/cs/packages
pokud to stale nepojede, posli chybu a zkontroluj preklpy atp.

Pilda
Člen | 52
+
0
-

Udělal jsem to a bohužel mi to stále nejde. Hlásí to úplně tu samou výjimku jako předtím. Screenshot té chyby je zde. Překlep bych tam mít snad neměl, udělal jsem to metodou copy & paste přímo odsud.

Editoval Pilda (27. 12. 2011 14:36)

h4kuna
Backer | 740
+
0
-

na první pohled bych to viděl že AS by nemělo být v uvozovkách pač to je klíčové slovo

Pilda
Člen | 52
+
0
-

h4kuna:
můžete být prosím trošku konkrétní? Pracuji s nette asi týden. Bohužel netuším jak to myslíte.

Editoval Pilda (27. 12. 2011 19:53)

hrach
Člen | 1838
+
0
-

napis as velkymi pismeny.

Pilda
Člen | 52
+
0
-

Paráda, už mi to jde, díky!

Akorát mi s tím night buildem přestalo fungovat vypsání příspěvků. Píše mi to chybu htmlspecialchars() expects parameter 1 to be string, object given. Píše mi to když chci vypsat datum příspěvku. Došlo tam od té bety 2 k nějakým zásadním změnám?

Editoval Pilda (27. 12. 2011 22:08)

hrach
Člen | 1838
+
0
-

Tak hele, zkus taky trochu vlastní iniciativy, datetime v db se nyní převádí na datetime objekt, takže musít zavolat ->format(‚d. j. Y‘).

Pilda
Člen | 52
+
0
-

Děkuji.

boob
Člen | 21
+
0
-

mne len napadlo, ze by bolo mozno lepsie pridat do tabulky s kategoriami stlpec, kde by bol ulozeny pocet prispevkov a do tabulky s prispevkami pridat trigger, ktory by pri kazdom pridany/zmazani prispevku toto pocitadlo zmenil, aby to nebolo treba ratat vzdy pri kazdom nacitani stranky