Nástěnka v PHP

4. ledna 2002

Často je nástěnka považována za totéž, co návštěvní kniha. Minimálně jeden podstatný rozdíl zde však existuje. Stejně jako u klasické papírové nástěnky, tak i u té internetové jsou zprávy „vyvěšeny“ (zobrazeny) pouze po určitou dobu. Kromě této hlavní funkce, bude mít nástěnka všechny funkce jako návštěvní kniha (dělení slov, detekce odkazů, stránkování atd.). Celá aplikace je založena na databázi MySQL.

Aby bylo vše přehlednější, použijte tyto soubory – board.php (zobrazení zpráv), form.php (formulář pro přidávání zpráv), post.php (uložení zpráv), header.php (hlavička), db.php (připojení k databázi), create_table.php (vytvoření databázové tabulky), style.css (kaskádové styly).

Vytvoření databázové tabulky (create_table.php)

Potřebovat budete pouze jednu tabulku s názvem „board“, kam se budou ukládat všechny zprávy (příspěvky). Tabulka bude mít sedm položek – id (unikátní číslo zprávy), author (autor zprávy), email (email autora), from_date (datum, odkdy bude zpráva zobrazena), to_date (datum, dokdy bude zpráva zobrazena), subject (předmět zprávy), body (text zprávy). U položek „from_date“ a „to_date“ použijte datový typ „date“, který označuje datum ve formátu rok-měsíc-den (RRRR-MM-DD).

require "db.php"; // otevře databázi
$create_table = MySQL_Query("CREATE TABLE board (
id int PRIMARY KEY AUTO_INCREMENT,
author varchar(50),
email varchar(50),
from_date date,
to_date date,
subject varchar(250),
body text
)") or die("Nepodařilo se vytvořit tabulku board"); // vytvoří tabulku board

Soubor db.php, kterým se připojíte k databázi, obsahuje všechny potřebné údaje (jméno databáze ad.)

$server_name = "localhost"; // jméno databázového serveru
$db_user = ""; // uživatel
$db_pass = ""; // heslo
$db_name = "board"; // jméno databáze
MySQL_Connect($server_name, $db_user, $db_pass) or die(‚Nepodařilo se připojit k MySQL databázi‘); // připojení k databázi
MySQL_Select_DB($db_name) or die(‚Nepodařila se otevřít databáze.‘); // výběr databáze

Hlavička (header.php)

Standardní hlavička je kromě tří dobře známých HTTP hlaviček zabraňujících cashování tvořena pouze čistým HTML, proto zde nebudu uvádět dlouhý zdrojový kód, ale jen malý obrázek.

Hlavička

Zobrazení zpráv a formuláře (board.php)

Proměnná $action určuje, jaká akce se provede. Tato proměnná může obsahovat pouze dvě hodnoty – „view“ (zobrazení zpráv) a „post“ (přidávání zpráv). Jelikož uživatelům nástěnky nabízíte možnost prohlédnout si jak „Aktuální zprávy“ (mají být právě „vyvěšené“), tak i „Staré zprávy“ („prošlé“ zprávy), musíte si definovat další proměnnou $what. Pokud obsahuje hodnotu „new“, zobrazíte aktuální zprávy; jestliže obsahuje hodnotu „old“, zobrazíte staré zprávy. Poslední z klíčových proměnných je proměnná $page obsahující číslo stránky, která se zobrazí.

Nejprve zjistíte, zda jsou tyto základní proměnné zinicializovány. Pokud ne, vložíte do nich standardní hodnoty.

$query_error = ‚Došlo k chybě při zpracování SQL dotazu v databázi.‘; // chybová hláška
if (!IsSet($action)) $action = "view"; // ještě není zinicializována proměnná $action
if (!IsSet($what)) $what = "new"; // ještě není zinicializována proměnná $what
if (!IsSet($page)) $page = 0; // ještě není zinicializována proměnná $page

V první větvi následující podmínky řešíte zobrazení zpráv. V závislosti na obsahu proměnné $what vypíšete nadpis („Aktuální zprávy“ nebo „Staré zprávy“). Současně si definujte nejdůležitější část SQL dotazu, který za chvíli použijete. Jedná se o část za slovem WHERE, tedy o podmínku určující, jaké zprávy z databáze vyberete. Funkce NOW() vrací aktuální datum a čas ve formátu RRRR-MM-DD HH:MM:SS. Pokud chcete zobrazit aktuální zprávy, musí být „from_date“ (datum zobrazení zprávy) menší nebo rovno aktuálnímu datu a zároveň (spojka AND) „to_date“ (datum, dokdy bude zpráva zobrazena) větší nebo rovno aktuálnímu datu. Jestliže zobrazujete staré zprávy, stačí zjistit, zda „to_date“ je menší než aktuální datum.

if ($action=="view"): // zobrazuje zprávy
 require("header.php"); // vloží hlavičku
 require "db.php"; // otevře databázi
?>
 <table width="600" border="0" cellspacing="0" cellpadding="0" align="center">
  <tr><td class="tableheading">
    <?
    // zobrazuje aktuální nebo staré zprávy
    if($what=="new"):
        echo "->> Aktuální zprávy";
        $sql = "from_date <= NOW() AND to_date >= NOW()";
    else:
        echo "->> Staré zprávy";
        $sql = "to_date < NOW()";
    endif;
    ?>
    <hr width="100%" size="1" color="#7D7642" noshade>
  </td></tr>
 </table>

Nyní přichází na řadu výběr zpráv z databáze. Nejdříve musíte určit, po kolika se zprávy zobrazí ($view_number). Následně pomocí proměnné $page spočítáte první zprávu, která se zobrazí. Z databáze pak vyberete zprávy odpovídající výše popsané podmínce $sql. „ORDER BY id DESC“ znamená, že zprávy budou seřazeny podle svého čísla, a to sestupně. Pomocí „LIMIT $start, $view_number“ omezíte výběr tak, že vyberete 10 zpráv (standardní hodnota $view_number), počínaje zprávou $start.

 $view_number = 10; // zprávy budou zobrazeny po …
 $start = $page*$view_number; // první zpráva, která se zobrazí
 $message = MySQL_Query("SELECT * FROM board WHERE $sql ORDER BY id DESC LIMIT $start,$view_number") or die($query_error); // vybíráte zprávy – seřazeno podle id

Teď již můžete dané zprávy vypsat. Každá zpráva bude v samostatné tabulce, nad níž bude uvedeno číslo zprávy. Jediný problém nastává u data „od – do“, které uvedete v hranatých závorkách za předmětem zprávy. V databázi máte totiž datum ve formátu RRRR-MM-YY, potřebujete však datum ve formátu DD. MM. YYYY. Použijte funkci Explode, která dokáže rozdělit řetězec na jednotlivé části oddělené určitým znakem (v našem případě pomlčkou).

 // vypíše tabulky se zprávami
 while ($entry = MySQL_Fetch_Array($message)):
 ?>
    <table width="600" border="0" cellspacing="0" cellpadding="1" align="center"><tr><td class="tableheading"><?echo "zpráva č. " . $entry["id"]?></td></tr></table>
    <table width="600" border="0" cellspacing="0" cellpadding="1" align="center" bgcolor="#7D7642"><tr><td>
     <table width="100%" border="0" cellspacing="0" cellpadding="2" align="center" bgcolor="#eaead7">
      <tr>
        <td class="table">
        <?
        $from = Explode("-", $entry["from_date"]); // od
        $to = Explode("-", $entry["to_date"]); // do
        if ($entry["email"]!="") echo ‚<a href="mailto:‘ . $entry["email"] . ‚">‘; // autor zadal svůj email
        echo "<b>" . $entry["author"] . "</b>"; // jméno
        if ($entry["email"]!="") echo ‚</a>‘;
        echo "<br>";
        echo "<b>" . $entry["subject"] . "</b>" . " [". $from[2] . ". " . $from[1] . ". " . $from[0] . " – " . $to[2] . ". " . $to[1] . ". " . $to[0] . "]"; // předmět [od – do]         echo "<br><br>";
        echo $entry["body"]; // zpráva
         ?>
        </td>
      </tr>
     </table>
    </table><br>
 <?endwhile;?>

Poslední částí je vypsání odkazů na stránky s dalšími zprávami. Nejprve z databáze vyberte všechny zprávy odpovídající podmínce $sql. Následně zjistíte počet stran, na kterých se zprávy zobrazí, což je podíl celkového počtu zpráv a počtu zpráv na jedné straně ($view_number). Pomocí jednoduchého cyklu pak již jen vypíšete odkazy na jednotlivé stránky. U právě zobrazované stránky ($page) odkaz vytvářet nemusíte.

 <table width="600" border="0" cellspacing="0" cellpadding="0" align="center">
  <tr><td align="right" class="table">
    <hr width="100%" size="1" color="#7D7642" noshade>
    <b>strana:
    <?
    // odkazy na starší zprávy (u právě zobrazené zprávy se odkaz nevytvoří)
    $count = MySQL_Query("SELECT id FROM board WHERE $sql") or die($query_error); // výběr zpráv
    $page_count = Ceil(MySQL_Num_Rows($count)/$view_number); // počet stran, na kterých se zprávy zobrazí
    for($i=0;$i<$page_count;$i++):
        echo " | ";
        if($page!=$i) echo ‚<a href="board.php?action=view&what=‘ . $what . ‚&page=‘ . $i . ‚">‘;
        echo ($i+1);
        if($page!=$i) echo ‚</a> ‚;
    endfor;
    MySQL_Close(); // zavření databáze
    ?>
    |</b>
  </td></tr>
 </table>

V druhé části základní podmínky buď zobrazíte formulář, nebo uložíte zprávu do databáze. K tomu potřebujete proměnnou $write. Pokud je hodnota „false“, zobrazí se formulář, pokud „true“ uloží se zpráva do databáze.

else: // formulář nebo uložení zprávy
 $write = false; // předpokládáte zobrazení formuláře

Protože zdrojový kód formuláře je velmi dlouhý, uvedu jen některé důležité části a malý obrázek.

Formulář

Od uživatele budete získávat několik údajů – jméno ($author), email($email – nepovinný), předmět ($subject), text zprávy ($body) a dvě data – odkdy ($from_day – den, $from_month – měsíc, $from_year – rok) a dokdy ($to_day – den, $to_month – měsíc, $to_year – rok) má být zpráva zobrazena. Aby uživatel nemusel po odeslání chybně vyplněného formuláře vyplňovat vše znovu, budete zadané údaje uchovávat v atributu VALUE. Problém však nastává u částí, které jsou tvořeny formulářovým prvkem SELECT. Jde to však vyřešit tak, že jednotlivé položky budete vypisovat přes cyklus a pokud se předchozí hodnota (např. $from_month) rovná proměnné $i, vypíšete „SELECTED“, což způsobí, že uživatel nebude muset po odeslání chybně vyplněného formuláře vybírat datum znovu. Zde uvádím pouze jednu část souboru form.php. Obdobně se však postupuje i u dalších „selectů“.

<select name="from_month" size="1" class="input">
<?
// od – měsíc
$month=Array(1=> "ledna", "února", "března", "dubna", "května", "června", "července", "srpna", "září", "října", "listopadu", "prosince");
for($i=1;$i<=12;$i++):
    echo "<option value=" . $i;
    if($from_month==$i) echo " selected";
    echo ">" . $month[$i] . "</option>\n";
endfor;
?>
</select>

Ve formuláři je také jedno skryté pole s názvem „sent“. Pokud je proměnná $sent zinicializována, byl formulář odeslán, a tak se můžete pustit do kontroly zadaných údajů. Nejprve zkontrolujte, zda byly vyplněny všechny povinné údaje. Následně zjistěte, jestli není datum OD větší než datum DO. K tomu využijte funkci MkTime(), která převádí datum na počet sekund od 1. ledna 1970. Jednotlivé parametry se zadávají v pořadí hodina, minuta, sekunda, měsíc, den, rok. Podobně zkontrolujte, zda datum OD není menší než dnešní datum. Pokud nastala nějaká chyba, uložte chybovou hlášku do proměnné $error a vypište ji na konci formuláře. Jestliže je vše v pořádku, vložte do proměnné $write hodnotu „true“. Následující podmínka snad žádný podrobný komentář nepotřebuje – v závislosti na proměnné $write se buď provede zápis nebo se zobrazí formulář.

 if(IsSet($sent)):    // byl odeslán formulář?
     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.‘;
    elseif(MkTime(0,0,0,$from_month,$from_day,$from_year) > MkTime(0,0,0,$to_month,$to_day,$to_year)): // zkontroluje data od-do
        $error = ‚Datum OD nesmí být větší než datum DO.‘;
    elseif(MkTime(0,0,0,$from_month,$from_day,$from_year) < MkTime(0,0,0, Date("m"), Date("d"), Date("Y"))):
        $error = ‚Datum OD nesmí být menší než dnešní datum.‘;
    else:
        $write = true; // provede zápis
    endif;
 endif;
 if($write): // zápis do databáze
    require("post.php");
 else: // zobrazuje formulář
    require("header.php");
    require("form.php");
 endif;
endif;

Uložení zprávy do databáze (post.php)

Uložení zprávy do databáze je velmi jednoduché. Všechny prováděné operace byly popisovány v seriálech Návštěvní kniha a Diskusní fórum. Jediné, co okomentuji, je získání data OD a DO. K tomu použijete funkci Date(). Jako první parametr uvedete formát data, který vyžaduje databáze MySQL (RRRR-MM-DD), jako druhý počet sekund od 1. ledna 1970, k čemuž znovu použijete funkci MkTime(). Velká výhoda této funkce spočívá v tom, že si poradí i se špatně zadaným datem. Např. nesmyslné datum 31. 4. převede na 1. 5.

// odstraní nebezpečné znaky
$author = HTMLSpecialChars($author);
$email = HTMLSpecialChars($email);
$subject = HTMLSpecialChars($subject);
$body = SubStr($body, 0, 1500); // bere pouze 1500 znaků
$body = Trim($body); // odstraní mezery ze začátku a konce řetězce
$body = HTMLSpecialChars($body); // odstraní nebezpečné znaky
$body = Str_Replace("\r\n"," <BR> ", $body); // nahradí konce řádků na tagy <BR>
$body = WordWrap($body, 90, "\n", 1); // rozdělí dlouhá slova
// vytvoří odkazy
$body = EregI_Replace("(http://[^ ]+\.[^ ]+)", " <a href=\\1>\\1</a>", $body);
$body = EregI_Replace("[^/](www\.[^ ]+\.[^ ]+)", " <a href=http://\\1>\\1</a>", $body);
// povolí 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;
$from = Date("Y-m-d", MkTime(0,0,0,$from_month,$from_day,$from_year)); // od
$to = Date("Y-m-d", MkTime(0,0,0,$to_month,$to_day,$to_year));// do
require "db.php"; // otevře databázi
$add = MySQL_Query("INSERT INTO board VALUES (“, ‚$author‘, ‚$email‘, ‚$from‘, ‚$to‘, ‚$subject‘, ‚$body‘)") or die($query_error); // vloží zprávu
MySQL_Close(); // zavře databázi
Header("Location: board.php"); // přesune se na úvodní stránku

Nástěnku můžete použít pro vkládání akcí a zpráv, které mají omezenou platnost. Smíte si ji však libovolně upravit a použít třeba jako obyčejnou návštěvní knihu. Kompletní zdrojové kódy si můžete stáhnout.

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

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

Předchozí článek Jaký bude Interval?
Další článek Databáze nejsou jen MySQL

Mohlo by vás také zajímat

Nejnovější

1 komentář

  1. ComBett

    Čvn 28, 2009 v 15:27

    Ahojte,
    v PHP som uplny zaciatocnik, tato nastenka sa mi veeeelmi pozdava, aj to mam na serveri rozbehane.
    Problem mam ale v tom, ze by som rad odstranil zadavanie datumu „od:“, teda aby sa tam dosadil dnesny datum. Pokusov som spravi vela, ale nezdarilo sa. Pomoze mi niekto?
    Vopred vdaka.
    c.

    Odpovědět

Napsat komentář

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