Diskusní fórum v PHP pro každého – výpis témat

    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.

    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