Diskusní fórum v PHP pro každého (1.)
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.
První verzi našeho diskusního fóra si můžete
předem vyzkoušet.
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é.
Michal Kebrt - Další články
autora
_soubory/invisible.gif)
|