V tomto článku vám představím užitečnou aplikaci. Již ovládáte práci s proměnnými, soubory, cykly i podmínkami, a tak nebude problém vytvořit návštěvní knihu. S takovou návštěvní knihou (někdy bývá také nazývána „Diskuse“ či „Diskusní fórum“) se jistě setkal každý. Jejím prostřednictvím můžete zanechat na stránkách zprávu, příslušné stránky můžete pochválit či naopak zkritizovat.

A nyní se už pustíme do tvorby návštěvní knihy. Hlavička dokumentu bude vypadat takto – všechno se bude zobrazovat v tabulce o velikosti třeba 500 pixelů:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1250">
<LINK href="styl.css" rel="stylesheet" type="text/css">
<title>Kniha návštev – PHP</title>
</head>
<body>
<table width="500" align="center">
<tr><td width="500"><center><font class=nadpis>Kniha návštev</font><br><br>
<font class="male">povinné údaje označeny červeným písmem</font></center>
<hr color="#00008B"><br>

Aby byl výsledný kód kratší a přehlednější jsou použity kaskádové styly (CSS). Obsah souboru, kde jsou uloženy, vám proto také předkládám:

TEXTAREA {FONT-SIZE: 9 pt;font-family : Verdana;font-weight : normal;}
INPUT {FONT-SIZE: 9 pt;font-family : Verdana;font-weight : normal;}
.nadpis {font-family : Arial CE, Arial, Helvetica, sans-serif;font-weight : bold;font-size : 15pt;color : #00008B;}
.povinne {FONT-SIZE: 9 pt;font-family : Verdana;font-weight : bold;color : Red;}
.male {FONT-SIZE: 7 pt;font-family : Verdana;font-weight : bold;color : Red;}
.nepovinne {FONT-SIZE: 9 pt;font-family : Verdana;font-weight : bold;}
.jmeno {FONT-SIZE: 11 pt;font-family : Verdana; font-weight : bold;color : #00008B;}
.odkaz {FONT-SIZE: 10 pt;font-family : Verdana; font-weight : bold;color : #00008B;text-decoration : none;}
.odkaz:HOVER {FONT-SIZE: 10 pt;font-family : Verdana;font-weight : bold;color : #00008B;text-decoration : underline;}
.cas {FONT-SIZE: 10 pt;font-family : Verdana;font-weight : bold;color : #00008B;}
.text {FONT-SIZE: 10 pt;font-family : Verdana;color : Black;font-weight : bold;}

Nejprve tedy vytvoříme formulář, kam budeme zadávat tyto položky: Jméno, E-mail, Web a samotný Text zprávy (kromě Webu jsou všechny povinné, tz., že do návštěvní knihy se zapíší pouze ty příspěvky, které budou obsahovat všechny povinné údaje). Celý formulář umístíme do tabulky, abychom mohli snadno zarovnat popisky a vstupní pole formuláře:

<table border="0" cellspacing="0" cellpadding="0" align="center">
<form method="post">
<tr><td width=120 class=povinne>Jméno:</td>
<td><input type="text" name="jmeno" size="30" value="<?
if ($jmeno=="" || $email=="" || $popis==""): //pokud nebudou zadány všechny povinné údaje, objeví se formulář znovu (s údaji, které již byly vyplněny)
echo $jmeno;
endif;
?>"></td></tr>
<tr><td width=120 class=povinne>E-mail:</td>
<td><input type="text" name="email" size="30" value="<?
if ($jmeno=="" || $email=="" || $popis==""): //pokud nebudou zadány všechny povinné údaje, objeví se formulář znovu (s údaji, které již byly vyplněny)
echo $email;
endif;
?>"></td></tr>
<tr><td width=120 class=nepovinne>Web (i s http://):</td>
<td><input type="text" name="web" size="30" value="<?
if ($jmeno=="" || $email=="" || $popis==""): //pokud nebudou zadány všechny povinné údaje, objeví se formulář znovu (s údaji, které již byly vyplněny)
echo $web;
endif;
?>">
<input type="hidden" name="odeslano" value="ano"></td></tr>
<tr><td valign=top width=120 class=povinne>Text zprávy:</td>
<td><textarea cols="29" rows="5" name="popis"><?
if ($jmeno=="" || $email=="" || $popis==""): //pokud nebudou zadány všechny povinné údaje, objeví se formulář znovu (s údaji, které již byly vyplněny)
echo $popis;
endif;
?></textarea></td></tr>
<tr><td width=120></td>
<td><center><input type="submit" value="Odeslat">&nbsp;&nbsp;&nbsp;<input type="Reset" value="Vymazat"></center></td></tr></form></table>

Myslím, že vytvoření tabulky není žádný problém, komentář si ale zaslouží použitý PHP kód. Může totiž nastat případ, kdy autor příspěvku zapomene na nějaký povinný údaj a formulář se před ním objeví znovu. Těch několik příkazů tedy způsobí, že člověk nemusí údaje, které již předtím vyplnil, zadávat znovu, ale údaje budou v příslušných formulářových polích vyplněny. Asi se ale ptáte, proč je použita podmínka, stačilo by napsat „echo $jmeno“. Pokud bychom to udělali takto, stalo by se po korektním odeslání formuláře to, že všechna vstupní pole by byla vyplněna. Pak by stačilo několikrát za sebou formulář znovu pouze odeslat a návštěvní kniha by byla zahlcena jedním a tím samým příspěvkem. To řeší právě naše podmínka, která nechává pole vyplněná pouze, pokud chybí nějaký povinný údaj. Po odeslání všech povinných údajů se před vámi objeví zase prázdný formulář:

if ($jmeno=="" || $email=="" || $popis==""): //pokud nebudou zadány všechny povinné údaje, objeví se formulář znovu (s údaji, které již byly vyplněny)
echo $popis;
endif;

Podmínku rozeberu ještě podrobněji. Jenom připomenu, že názvy proměnných se shodují s názvy polí ve formuláři, tak např. pokud se pole jmenuje „email“, jeho obsah máme přístupný v proměnné $email. Zjišťujeme tedy, zda se některá z proměnných rovná prázdnému řetězci (v příslušné položce nebylo nic napsáno). Musíme dát pozor, abychom použili dvě =, jinak by se jednalo o přiřazení, důležitý je ještě operátor || , který označuje logický součet („NEBO“). Pokud je splněna podmínka, že alespoň jeden z povinných údajů nebyl zadán, zůstanou všechna ostatní pole po odeslání vyplněná a do knihy se nic neuloží.

Nyní doporučuji znovu spustit návštěvní knihu a v praxi vyzkoušet, o čem byla v posledních dvou odstavcích řeč.

Následuje nejdůležitější část skriptu – zpracování vložených údajů, uložení do souboru a vypsání obsahu souboru:

<?
if ($odeslano=="ano"):
if ($jmeno=="" || $email=="" || $popis==""): //kontrola zadaných udajů, pokud nebyly zadány všechny povinné údaje, do knihy se nic nezapíše
echo "<center><br><font class=male>musíte vyplnit všechny povinné údaje<br></font></center>";
else: //včechny povinné údaje jsou zadány
$name = "<font class=jmeno>$jmeno</font><BR>\n"; //do proměnné "name" uloží Jméno, zformátuje jej pomocí tagu <FONT> a otevře nový řádek
$e_mail = "<A class=odkaz HREF=mailto:$email>$email</A><BR>\n"; //do proměnné "e_mail" uloží Email, zformátuje jej, přidá odkaz typu MAILTO a otevře nový řádek
if ($web!=""): //pokud byl zadán Web, vytvoří proměnnou "www"
$www = "<A class=odkaz HREF=\"$web\">$web</A><BR>\n"; //do proměnné "www" uloží Web, zformátuje jej, přidá odkaz na danou stránku a otevře nový řádek
endif;
$cas = "<font class=cas>" . Date("j. " . "m. " . "Y, " . "H:i:s") . "</font><BR>\n"; //do promenne "cas" uloží aktuální datum a čas ve formátu (př. 5. 11. 2000, 13:54:53), zformátuje a načne další řádek
$popis2 = NL2BR(HTMLSpecialChars($popis)); //změna konců řádků na tagy <BR> a ostraní znaky, které by mohly porušit formátování
$zprava = "<BR><font class=text>$popis2</font><BR><BR><HR color=\"#00008B\"><BR>\n\n"; //do proměnné "www" uloží $popis2, zformátuje, přidá čáru, která bude oddělovat příspěvky a otevře nový řádek
$write = StripSlashes($name . $e_mail . $www . $cas . $zprava); //do proměnné "write" uloží všechna data, která se budou zapisovat a odstraní escape sekvence
if (File_Exists ("book.dat")): //existuje soubor book.dat
$fp = FOpen ("book.dat", "r"); //otevře soubor book.dat pro čtení
$data = FRead ($fp, FileSize("book.dat")); //přečte data ze souboru a uloží do proměnné "data" – kvůli tomu aby se zobrazoval poslední příspěvek nahoře
FClose($fp); //zavře book.dat
endif;
$fp = FOpen ("book.dat", "w"); //otevře book.dat pro přepis nebo vytvoření
FWrite ($fp, $write.$data); //zápis do souboru book.dat (nejprve aktuální příspěvek, poté předešlý obsah souboru book.dat)
FClose ($fp); //zavře soubor book.dat
endif;
endif;
?>
<hr color="#00008B"><br>
<?
if (File_Exists ("book.dat")): //existuje soubor book.dat
$fp = FOpen ("book.dat", "r"); //otevře soubor book.dat pro čteni
FPassThru($fp); //vypíše obsah souboru
endif;
?>

Nejprve musíme zajistit, aby se celý skript prováděl pouze, když bude formulář odeslán. Toho docílíme tak, že do formuláře přidáme skryté pole <input type="hidden" name="odeslano" value="ano">. Pak už jen vytvoříme podmínku uvedenou níže, pokud je v proměnné $odeslano řetězec „ano“ (formulář byl odeslán) – pokračuje provádění dalších příkazů, jinak se pouze vypíše obsah datového souboru, kde máme uloženy příspěvky. Další podmínka je podobná té, která byla popsána v úvodu. Způsobí, že pokud nebyly odeslány všechny povinné údaje, vypíše se věta: „musíte vyplnit všechny povinné údaje“, která je naformátovaná podle stylů popsaných výše:

if ($odeslano=="ano"): //formulář byl odeslán
if ($jmeno=="" || $email=="" || $popis==""): //kontrola zadaných údajů, pokud nebyly zadány všechny povinné údaje, do knihy se nic nezapíše
echo "<center><br><font class=male>musíte vyplnit všechny povinné údaje<br><br></font></center>";

Další část podmínky je již složitější, a proto si ji probereme odděleně. Máme tedy všechny povinné údaje a nezbývá, než je zpracovat. Do proměnné $name uložíme obsah proměnné $jmeno, přidáme formátování textu pomocí CSS a otevřeme další řádek tagem <BR>. Escape sekvence \n způsobí vytvoření nového řádku. Data jsou pak v datovém souboru přehledně uspořádána – vždy na novém řádku (výsledný HTML kód to ale nijak neovlivní). Pokud by nebyla použita, ukládala by se veškerá data do jednoho řádku:

else: //všechny povinné údaje jsou zadány
$name = "<font class=jmeno>$jmeno</font><BR>\n"; //do proměnné "name" uloží Jméno, zformátuje jej pomocí tagu <FONT> a otevře nový řádek

Následující část je velice podobná té předchozí – do proměnných se opět uloží údaje z formuláře. Jelikož se ale jedná o e-mailovou adresu a adresu stránek je potřeba přidat odkaz. V případě e-mailu vytvoříme odkaz typu MAILTO, aby se po odkliknutí otevřel poštovní klient a bylo možné kontaktovat autora příspěvku. Položka Web nebyla povinná, proto musíme vytvořit podmínku if ($web!=““). Ta je splněna, pokud se obsah proměnné $web nerovná (! způsobí negaci) prázdnému řetězci (tz. obsahuje nějaký text). Opět se nabízí otázka, je-li podmínka nutná. Odpověď zní ano, pokud bychom ji neuvedli, přiřazení by se provedlo i při nezadání webové stránky. Potom by se vytvořil prázdný řádek, což by jistě nebylo estetické:

$e_mail = "<A class=odkaz HREF=mailto:$email>$email</A><BR>\n"; //do proměnné "e_mail" uloží Email, zformátuje jej, přidá odkaz typu MAILTO a otevře nový řádek
if ($web!=""): //pokud byl zadán Web, vytvoří proměnnou "www"
$www = "<A class=odkaz HREF=\"$web\">$web</A><BR>\n"; //do proměnné "www" uloží Web, zformátuje jej, přidá odkaz na danou stránku a otevře nový řádek
endif;

Důležité je také, aby se u každého příspěvku zobrazoval datum a čas odeslání. Práce s datem a časem již byla popsána v jednom článku, a tak není potřeba žádný komentář. Snad jen znak „j“ použitý namísto „d“. První vrací číslo dne v měsíci ve formátu „1- 31“, druhý pak „01-31“. Pro české zvyklosti je pochopitelně vhodnější „j“. Podobně je tomu u „m“, tam však žádný alternativní znak neexistuje. Šlo by to ale vyřešit přetypováním pomocí (int), ve výsledném kódu to ale neuvádím:

$cas = "<font class=cas>" . Date("j. " . "m. " . "Y, " . "H:i:s") . "</font><BR>\n"; //do proměnné "cas" uloží aktuální datum a čas ve formátu (př. 5. 11. 2000, 13:54:53), zformátuje a načne další řádek

Následuje zpracování Textu zprávy. Nejprve změníme funkcí NL2BR všechny konce řádků ve zprávě na tagy <BR> a zároveň nahradíme pomocí funkce HTMLSpecialChars znaky (<, >, „,&), které by mohly narušit formátování celého dokumentu, znakovými entitami (&lt, &gt, &quot, &amp). Poté vložíme do proměnné $zprava text zprávy, a přidáme čáru, která bude oddělovat jednotlivé příspěvky:

$popis2 = NL2BR(HTMLSpecialChars($popis)); //změna konců řádků na tagy <BR> a odstraní znaky, které by mohly porušit formátování
$zprava = "<BR><font class=text>$popis2</font><BR><BR><HR color=\"#00008B\"><BR>\n\n"; //do proměnné "www" uloží $popis2, zformátuje, přidá čáru, která bude oddělovat příspěvky a otevře nový řádek

Na závěr do proměnné $write uložíme všechny získané údaje a pomocí funkce StripSlashes odstraníme escape sekvence. Pakliže bychom toto neudělali a někdo zaslal třeba ‚ “ ‚ nebo ‚ \ ‚, objevilo by se v ppříspěvku ‚ \“ ‚ resp. ‚ \\ ‚:

$write = StripSlashes($name . $e_mail . $www . $cas . $zprava); //do proměnné "write" uloží všechna data, která se budou zapisovat a odstraní escape sekvence

Už zbývá pouze zápis do datového souboru. Nejprve zjistíme, zda soubor „book.dat“ existuje. Pokud ano, načteme do proměnné $data jeho obsah. Poté otevřeme soubor pro zápis (resp. přepis) a uložíme do něj data v pořadí $write, $data, aby se poslední příspěvek zobrazoval vždy nejvýše. V případě, že soubor ještě neexistuje zapíše se pouze $write:

if (File_Exists ("book.dat")): //existuje soubor book.dat
$fp = FOpen ("book.dat", "r"); //otevře soubor book.dat pro čtení
$data = FRead ($fp, FileSize("book.dat")); //přečte data ze souboru a uloží do proměnné "data" – kvůli tomu aby se zobrazoval poslední příspěvek nahoře
FClose($fp); //zavře book.dat
endif;
$fp = FOpen ("book.dat", "w"); //otevře book.dat pro přepis nebo vytvoření
FWrite ($fp, $write.$data); //zápis do souboru book.dat (nejprve aktuální příspěvek, poté předešlý obsah souboru book.dat)
FClose ($fp); //zavře soubor book.dat
endif;
endif;

Nakonec vypíšeme obsah souboru „book.dat“ (pokud existuje), přidáme ještě čáru, která bude oddělovat formulář od příspěvků a ukončíme tabulku a HTML stránku. Funkce FpassThru slouží k vypsání obsahu souboru a automaticky příslušný soubor zavře:

<hr color="#00008B"><br>
<?
if (File_Exists ("book.dat")): //existuje soubor book.dat
$fp = FOpen ("book.dat", "r"); //otevře soubor book.dat pro čteni
FPassThru($fp); //vypíše obsah souboru
endif;
?>
</td>
</tr>
</table>
</body>
</html>

Samozřejmě, ke konci článku bývá zvykem nabídnout zdrojový kód popisované aplikace. Tu si včetně souboru s kaskádovými styly můžete stáhnout zde. A to je pro dnešek vše.

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

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

13 Příspěvků v diskuzi

  1. odkaz „spustit“ nefunguje, odkazuje na er.404. Zkoušel jsem si je přidat do stránek, ale nějak mi to nechce fungovat, ví někdo jak poradit (Php není zrovna moje partie) – soubor ke stažení „kniha2“ jsem si stáhl, extrahoval , vyjmul jednotlivé soubory a nahrál na server do složky php (má to velký vliv, když je tam koncovka php3, nebo je to jedno? Já osobně mám jen php!) Děkuji za odpověď.

  2. Nevím jak to rozjet moc programovat v PHP neumím mohl by mě někdo poslat jak to má přesně vypadat aby to fungovalo?? Byl bych moc vděčný děkuji.

  3. Celkom fajn vecička pokiaľ sa niekomu nechce učiť php, dá sa to krásne využiť a oštýlovať v css, je to jednoduché a zároveň zaujímavé.

  4. Zdravim, ten soubor je naprosto v poradku. Ale zkusim proverit, zdali v tom adresari nekde neni nejaky „presmerovavaci iframe“

  5. Kniha je Ok, jediné co mi vadí je, že při F5 (refresh) se vždy poslední příspěvek kopíruje a zobrazuje se ještě jednou. Dokázal by někdo poradit, co mám upravit, aby tomu tak nebylo? Díky

  6. Nevím co dělám špatně, ale když v návštěvní knize vyplním všechna pole a dám odeslat, tak všechny pole zmizí a na stránce se nic neukáže

  7. Ahoj mám takový problém zkoušel jsem to dělat ve WordPressu a ty kody který zjišťují jestli je vše vyplněno se mi tam ukáží jako normální text :/ Nevíte někdo co s tým?

Odpovědět