Diskusní fórum v PHP s využitím databáze – zpracování příspěvků

29. října 2001

V dnešním dílu se dozvíte, jak zpracovat příspěvky odeslané formulářem. Procvičíme si práci s textem, s regulárními výrazy, dělení slov (WordWrap) a posílání emailů.

Zpracování příspěvků (post.php)

V celém skriptu bude několikrát použita proměnná $write, která určuje, zda bude proveden zápis. Pokud bude obsahovat hodnotu true (vše proběhlo v pořádku) zápis se provede, jestliže bude obsahovat hodnotu false (nebyly zadány všechny povinné údaje nebo bylo zadáno špatné heslo) zápis se neprovede a před uživatelem se objeví formulář s příslušnou chybovou hláškou.

require "db.php";        //otevřeme databázi
require "style.php";    //načteme soubor s konfigurací
$write=true;                //předpokládáme úspěšný zápis

Nejprve zkontrolujeme, zda byly zadány všechny povinné údaje – jméno, předmět a text zprávy. Pokud ne, uložíme do proměnné $error chybovou hlášku a hodnotu proměnné $write nastavíme na false. V další části podmínky zkontrolujeme, jestli souhlasí heslo. Z tabulky users vybereme heslo autora právě zpracovávaného příspěvku. Abychom zbytečně nedráždili uživatele, kteří omylem zadají heslo, přestože nemají zaregistrované jméno, přidáme do podmínky $entry["password"]!="", což zajistí kontrolu hesla pouze u registrovaných uživatelů. Poté zjistíme, zda se zadané heslo rovná heslu v databázi. Pokud se hesla nerovnají postupujeme stejně jako u předchozí podmínky.

if($author=="" || $subject=="" || $body==""):    //byly vyplněny všechny povinné údaje?
    $error = ‚Musíte vyplnit všechny povinné údaje – označeny tučným písmem.‘;
    $write = false;
else:
    //souhlasí heslo?
    $user = MySQL_Query("SELECT password FROM users WHERE name = ‚$author’") or die($query_error);
    $entry = MySQL_Fetch_Array($user);
    if($entry["password"]!="" && $password!=$entry["password"]):
        $error = ‚Špatně zadané heslo, prosím opravte ho.‘;
        $write = false;
    endif;
endif;

Jestliže jsou splněny všechny podmínky a hodnota proměnné $write je true, můžeme provést zápis. Nejprve odstraníme ze všech vstupních údajů nebezpečné znaky, které by mohly narušit formátování. Do proměnné $date si uložíme čas jako počet sekund od 1. ledna 1970, tuto hodnotu vrací funkce Time(). Následně zpracujeme text zprávy, nejprve vybereme prvních 1500 znaků a odstraníme mezery z obou konců řetězce. V tuto chvíli si do proměnné $email_message uložíme zprávu, kterou později pošleme emailem. Poté odstraníme nebezpečné znaky a konce řádků nahradíme tagy <BR>.

    //odstraníme nebezpečné znaky
    $author = HTMLSpecialChars($author);
    $email = HTMLSpecialChars($email);
    $subject = HTMLSpecialChars($subject);
    $date = Time(); //počet sekund od 1.1. 1970
    $body = SubStr($body, 0, 1500);        //bereme pouze 1500 znaků
    $body = Trim($body);                           //odstraníme mezery ze začátku a konce řetězce
    $email_message = $body;                //zprávu, kterou pošleme emailem již další úpravy nepostihnou
    $body = HTMLSpecialChars($body);    //odstraníme nebezpečné znaky
    $body = Str_Replace("\r\n"," <BR> ", $body);    //nahradíme konce řádků na tagy <BR>

PHP4 obsahuje novou funkci WordWrap(), která umožňuje dělení řetězce. První parametr udává zdrojový řetězec, druhý počet znaků po kolika se provede rozdělení (standardně 75), v třetím parametru můžete uvést, co se použije jako dělící znak (standardně je to nový řádek – ‚\n‘). Pokud v posledním znaku uvedete 1, budou dělena i slova. V našem případě budeme dělit řetězec po 110 znacích, a to novým řádkem. A co je nejdůležitější rozdělíme i dlouhá slova.

    $body = WordWrap($body, 110, "\n", 1); //rozdělíme dlouhá slova

Stejně jako v předchozích aplikacích budeme i nyní automaticky detekovat odkazy. Tentokráte však mnohem elegantnějším způsobem. Nejprve provedeme detekci odkazů typu http://. Za ‚http://‘ se musí vyskytnout alespoň jeden znak kromě mezery, následuje tečka a opět alespoň jeden znak kromě mezery. Následně budeme zjišťovat existenci odkazů typu www. Regulární výraz je téměř stejný. Pokud však uživatel zadá třeba odkaz http://www.interval.cz, musíme zajistit, aby se neprovedla opětovná detekce, tentokráte však jako www. To vyřešíme přidáním [^/], regulárnímu výrazu pak nebudou vyhovovat odkazy před kterými bude ‚/‘ (např. http://www.interval.cz). Jediným nedostatkem tohoto, myslím, elegantního způsobu je, že nedetekuje odkazy delší než 110 znaků, které jsme předtím rozdělili funkcí WordWrap(). I to však jde vyřešit, skript, který to umožní, najdete ve zdrojovém kódu, který si budete moci stáhnout v příštím článku.

    //vytvoříme odkazy
    $body = EregI_Replace("(http://[^ ]+\.[^ ]+)", " <a href=\\1>\\1</a>", $body);
    $body = EregI_Replace("[^/](www\.[^ ]+\.[^ ]+)", " <a href=http://\\1>\\1</a>", $body);

Pro zvýraznění důležitých částí příspěvku povolíme použití některých tagů – <b>, <u>, <i>. Tagy si uložíme do pole a následně pomocí jednoduchého cyklu provedeme náhradu.

    //povolíme tyto tagy – <b> <u> <i>, možnost přidat další
    $tag = Array("b", "u", "i");
    for($y=0;$y<Count($tag);$y++):
        $body = EregI_Replace("<" . $tag[$y] . ">", "<" . $tag[$y] . ">", $body);
        $body = EregI_Replace("</" . $tag[$y] . ">", "</" . $tag[$y] . ">", $body);
    endfor;

Pokud si uživatel nepřeje zasílat odpovědi, uložíme do proměnné $reply hodnotu ‚N‘. Nyní můžeme přistoupit k samotnému zápisu do databáze. Pokud je hodnota proměnné $thread ‚0‘, jedná se o přidávání hlavního tématu. Od přidávání odpovědi se to liší pouze tím, že se uvádí datum poslední odpovědi. Pokud přidáváme odpověď musíme provést ještě několik dalších operací. Tou první je aktualizace data poslední odpovědi u příslušného tématu (pomocí UPDATE a SET).

    if($thread==0):    //přidávání hlavního tématu
        $add = MySQL_Query("INSERT INTO phorum VALUES (“, ‚0‘, ‚$author‘, ‚$email‘, ‚$subject‘, ‚$body‘, ‚$date‘, ‚$date‘, ‚$reply‘)") or die($query_error);
    else:
        //přidávání odpovědi a aktualizace data poslední odpovědi u příslušného tématu
        $add = MySQL_Query("INSERT INTO phorum VALUES (“, ‚$thread‘, ‚$author‘, ‚$email‘, ‚$subject‘, ‚$body‘, ‚$date‘, “, ‚$reply‘)") or die($query_error);
        $update = MySQL_Query("UPDATE phorum SET latest = ‚$date‘ WHERE id = $id") or die($query_error);

Abychom mohli poslat odpověď emailem, musíme zjistit údaje o příspěvku, na který přišla odpověď. Pokud si autor tohoto příspěvku přál zasílat odpovědi, zjistíme id právě zapsané odpovědi (SELECT max(id) as maxid), abychom mohli vytvořit odkaz směřující k této odpovědi.

        //zjistíme údaje o příspěvku, na který přišla odpověď
        $email_reply = MySQL_Query("SELECT email, body, reply FROM phorum WHERE id = $thread") or die($query_error);
        $entry = MySQL_Fetch_Array($email_reply);
        if($entry["reply"]=="Y"):    //budeme zasílat odpověď emailem?
        
            //zjistíme id právě zapsaného příspěvku
            $latest_id = MySQL_Query("SELECT max(id) as maxid FROM phorum") or die($query_error);
            $entry2 = MySQL_Fetch_Array($latest_id);

Do proměnných $subject a $body uložíme předmět a tělo emailu. V těle bude uveden původní příspěvek ($entry["body"]), odpověď ($email_message) a odkaz na její prohlédnutí. Pomocí funkce StrTr() odstraníme diakritiku. Tělo emailu zalomíme po 75 znacích znakem ‚\n‘ a následně pomocí funkce Mail() odešleme.

            $subject = ‚Odpoved na Vas prispevek v diskusi‘;    //předmět emailu
            //tělo emailu
            $body = "Na vas prispevek\n—————————————————————————" . $entry["body"] .
                    "\n—————————————————————————\nprisla tato odpoved:\n\n" . $email_message .
                    "\n\nZde si ji muzete prohlednout a pripadne odpovedet:\nhttp://zadara.d2.cz/myphorum/read.php?id=" . $id .
                    "&id_answer=" . $entry2["maxid"] . "&view=single";
            $body = StrTr($body, "ěščřžýáíéúůťďňĚŠČŘŽÝÁÍÉÚŮŤĎŇ", "escrzyaieuutdnESCRZYAIEUUTDN");    //odstraníme diakritiku
            $body = WordWrap($body, 75, "\n", 1);    //zalomíme tělo emailu po 75 znacích
            @Mail($entry["email"], $subject, $body, "From: \"Dikusni forum\" <example@example.net>");    //pošleme email
        endif;
    endif;

Na závěr odešleme cookies, aby uživatel nemusel pokaždé vyplňovat své jméno a email. A pomocí hlavičky Header("Location:") se přesuneme na úvodní stránku.

    //odešleme cookies
    SetCookie("cookie_author", $author, Time()+31536000);
    SetCookie("cookie_email", $email, Time()+31536000);
    MySQL_Close();    //zavřeme databázi
    Header("Location: index.php?view=$view"); //přesuneme se na úvodní stránku
endif;

Tímto končí seznámení se základem diskusního fóra. Příště se podíváme na registraci uživatelů a celou aplikaci si budete moci konečně stáhnout.

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

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

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *