Po několikadílném seriálu o knize návštěv si dnes představíme další užitečnou aplikaci, a to diskusní fórum (též diskuse) bez použití databáze. Diskuse je služba, která podobně jako návštěvní kniha umožňuje návštěvníkům vašich stránek kritizovat stránky nebo se vyjádřit k určitým tématům či problémům. Obrovskou výhodou diskuse je oproti návštěvní knize řazení jednotlivých příspěvků. Zatímco u návštěvní knihy byly všechny příspěvky na stejné úrovni, v diskusi jsou řazeny příspěvky pod témata a vy můžete reagovat na kterýkoliv z nich.

Diskusní fórum a jeho struktura

Nejprve stručně k tomu, co bude naše diskusní fórum umět. Jednotlivá témata, tedy příspěvky na nejvyšší úrovni, budeme vypisovat po určitém počtu, standardně po 30, s tím, že nejnovější se budou zobrazovat nejvýše. U každého tématu bude uvedeno několik údajů, včetně počtu odpovědí. Při výpisu konkrétního tématu (příspěvku) se zobrazí i strom s odpověďmi na dané téma s možností reagovat na zobrazený příspěvek.

Jaká bude struktura tohoto diskusního fóra? Bude tvořeno několika hlavními soubory, z nichž jeden vypíše seznam témat (index.php3), další zobrazí daný příspěvek (read.php3), další provede přidání nového příspěvku (post.php3) a poslední dva zobrazí formulář pro přidání (new.php3, form.php3). K tomu ještě dva menší soubory – jeden bude obsahovat standardní hlavičku (header.php3) a druhý styly (styl.css).

Všechny ostatní soubory budou umístěny v adresáři data. Soubor ‚main.topic‘ přitom bude obsahovat seznam hlavních témat a do ostatních souborů se budou ukládat odpovědi na jednotlivé příspěvky.

Výpis témat

Na úvod vás seznámím s tím, jak budou vypadat soubory obsahující příspěvky. Na prvním místě bude uvedeno unikátní označení příspěvku, na dalších pak předmět příspěvku, jméno autora, datum, kdy byl příspěvek vložen, e-mail autora (pokud byl zadán) a samotný obsah příspěvku. Jednotlivé údaje jsou odděleny znakem ‚#‘. Odpovědi na daný příspěvek se budou ukládat do souboru <unikátní označení příspěvku, na který odpovídáme>.topic. Každý příspěvek bude na zvláštním řádku.

Standardní hlavička (header.php3) bude vypadat takto. Komentář si zaslouží snad jen proměnná $width vyjadřující šířku tabulky, která se bude měnit podle toho, zda budeme příspěvky vypisovat (width=90%) nebo přidávat nové (width=50%).

<table width="<?echo $width?>%" border="0" cellspacing="0" cellpadding="3" align="center">
<tr><td class=menu><a href="new.php3">Nové téma</a>   |   
<a href="index.php3">Úvodní strana</a></td></tr></table>

Výpis diskusních témat bude provádět soubor index.php3. Témata se zobrazí v tabulce o čtyřech sloupcích – téma, jméno autora, datum a počet odpovědí.

<table width="90%" border="0" cellspacing="0" cellpadding="0" align="center" bgcolor="Black"><tr><td>
<table width="100%" border="0" cellspacing="1" cellpadding="3" align="center">
<tr bgcolor="#4A4A4A">
<td class=tabulkanadpis>Téma</td>
<td width=25% class=tabulkanadpis>Autor</td>
<td width=10% align=center class=tabulkanadpis>Datum</td>
<td width=10% align=center class=tabulkanadpis>Odpovědí</td></tr>

Jak již bylo napsáno, témata se ukládají do souboru main.topic. Budeme je vypisovat od nejnovějších, a to po 30. Nejprve načteme do proměnné $main_file obsah souboru main.topic a navíc si do proměnné $number uložíme celkový počet příspěvků.

//vypis temat
$main_file = File("data/main.topic");
$number = Count($main_file);

Následuje cyklus, který vypíše požadované příspěvky. Pro výpis příspěvků po 30 máme vyčleněnou další proměnnou $page, ve které budeme předávat určité číslo. 0 označuje témata 1-30, 1 témata 31-60 atd. s tím, že téma 1 je nejnovější. Ale pozor – nové příspěvky se na rozdíl od návštěvní knihy budou ukládat na konec souboru, čímž se o něco zjednoduší proces zápisu. Ukládání na konec souboru také trochu změní cyklus. Počáteční hodnota proměnné $i tedy bude $number-1-30*$page a koncová $number-30-30*$page a hodnotu proměnné $i budeme postupně snižovat.

for ($i=$number-1-30*$page;$i>=$number-30-30*$page;$i–):

Pro názornost jeden příklad. Máme celkem 167 témat a chceme zobrazit 30 nejnovějších ($page=0), což znamená, že musíme vypsat řádky 166 – 137 (řádky jsou číslovány od 0, proto ten posun o 1 dolů). Zobrazujeme-li starší témata, např $page=2, bude postup obdobný – zobrazíme řádky 106 (167-1-30*2) až 77 (167-30-30*2).

Následující podmínku využijeme při zjišťování, zda existuje ještě další stránka s tématy. Pokud daný řádek obsahuje nějaká data, pokračuje provádění dalších operací. Jestliže je však řádek prázdný, znamená to, že již další témata neexistují a tudíž mimo jiné nemusíme zobrazovat odkaz na starší témata ($view_link = ‚no‘). Následně do proměnné $entry uložíme jednotlivé části příspěvku (jméno, … – popsáno výše), a to pomocí známé fce Explode(). Získané údaje zapíšeme do tabulky. Význam proměnných $topic, $row, $mainrow, $id si vysvětlíme v dalším článku.

if ($main_file[$i]!=""):
$entry = Explode("#", $main_file[$i]);
echo "<tr bgcolor=white><td class=tabulka><a href=read.php3?topic=main&row=$i&mainrow=$i&id=$entry[0]>";
echo $entry[1];
echo "</a></td>";
echo "<td class=tabulka>$entry[2]</td>";
echo "<td align=center class=tabulka>$entry[3]</td>";

Poslední sloupec, ve kterém zobrazíme počet odpovědí na dané téma, bude o poznání komplikovanější. Ještě jednou si připomeňme, že odpovědi na daný příspěvek se ukládají do souboru <unikátní označení příspěvku, na který odpovídáme>.topic. Např. je-li unikátní označení tématu ‚12345‘, odpověď se uloží do souboru ‚12345.topic‘ opět pod nějakým unikátním označením.

Pro počítání odpovědí si definujme funkci Answers($topic), kde jediný parametr určuje unikátní označení právě zpracovávaného příspěvku. Pokud zjistíme, že existuje soubor $topic.topic, jinými slovy, že existuje odpověď na příspěvek s označením $topic, projdeme pomocí jednoduchého cyklu soubor $topic.topic (na každý příspěvek může být libovolný počet odpovědí) a do proměnné $entry načteme obsah dané odpovědi. Nyní část, která spočítá odpovědi. Obsah souboru temp.temp postupně zvyšujeme o 1, a tak získáme celkový počet odpovědí na dané téma. Hned poté voláme rekurzivně fci Answers (fce volá sama sebe) a jako parametr předáme unikátní označení právě zpracované odpovědi, protože pochopitelně může existovat i odpověď na odpověď. Tak zpracujeme celý strom odpovědí na dané téma.

//fce pro pocitani odpovedi
function Answers($topic)
{
if (File_Exists("data/$topic.topic")):
$dat_file = File("data/$topic.topic");
for ($i=Count($dat_file)-1;$i>=0;$i–):
$entry = Explode("#", $dat_file[$i]);
if (File_Exists ("temp.temp")):
$fp = FOpen ("temp.temp", "r");
$data = FRead ($fp, FileSize("temp.temp"));
FClose($fp);
endif;
$fp = FOpen ("temp.temp", "w");
FWrite ($fp, $data+1);
FClose ($fp);
Answers($entry[0]);
endfor;
endif;
}

Již máme definovanou fci Answers, takže ji použijeme a v parametru předáme unikátní označení tématu, které zpracováváme. Co následuje? Pokud existuje soubor temp.temp, uložíme jeho obsah do proměnné $data a zároveň ho smažeme, protože cyklus bude procházet další témata. Jestliže neexistuje, $data=0.

echo "<td align=center class=tabulka>";
Answers($entry[0]);
if (File_Exists ("temp.temp")):
$fp = FOpen ("temp.temp", "r");
$data = FRead ($fp, FileSize("temp.temp"));
FClose($fp);
Unlink("temp.temp");
else:
$data = 0;
endif;
echo $data;

V další části nám končí podmínka i cyklus, o proměnné $view_link již také byla řeč.

echo "</td></tr>";
else:
$view_link = "no";
endif;
endfor;
echo "</table></td></tr></table>";

Na řadu přichází závěrečná část – zobrazení odkazu na starší témata. Ten se zobrazí pokud proměnná $view_link neobsahuje řetězec ‚no‘. Hodnotu proměnné $page zvýšíme o 1 a předáme v odkazu.

if ($view_link!="no"):
?>
<table width="90%" border="0" cellspacing="0" cellpadding="3" align="center"><tr>
<td align=right class=menu><a href="index.php3?page=<?echo $page+1?>">Starší témata</a></td>
</tr></table>
<?endif;?>
</body></html>

Tímto končí úvod do diskusního fóra, v dalších článcích si vysvětlíme, jak zobrazit konkrétní příspěvky a jak přidat nové.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

1 Příspěvěk v diskuzi

Odpovědět