Jednoduchá návštěvní kniha v PHP

Znovu aktualizováno! Přidal jsem variantu s ukládáním do databáze (viz konec článku).

Aktualizováno! Viz konec článku (teď již ne tak docela konec) a diskusi.

Pokud máte webhosting bez databáze a toužíte po návštěvní knize, můžete zkusit skript z tohoto článku. Návštěvní kniha je uložená v jednom .csv souboru.

Toto řešení má samozřejmě určitá omezení – například v situaci, kdy se 50 uživatelů sejde a všichni najednou provedou zápis do návštěvní knihy … tak vlastně zápis neprovedou, protože pro zápis si soubor otevře v daný okamžik vždy jen jeden z nich. Pro málo frekventovaný web mi však toto nebezpečí přijde malé – jestli se toho obáváte, musíte vytvořit návštěvní knihu s pomocí databáze.

Současně je následující kód hezkým příkladem na základy zpracování .csv dat pomocí PHP.

Pokud byste chtěli nějakou část kódu ode mě dovysvětlit (případně vylepšit), napište to do komentáře pod článek.

< ?php
 
function mail_utf8($to, $subject = '(No subject)', $message = '', $header = '') {
  $header_ = 'MIME-Version: 1.0' . "\r\n" 
                . 'Content-type: text/plain; charset=UTF-8' . "\r\n";
  mail($to, '=?UTF-8?B?'.base64_encode($subject).'?=', $message, $header_ . $header);
}
 
$soubor_vzkazu = "./vzkazy.csv";
 
if($_POST['sent']){
  //sestavení vzkazu
  $string = strip_tags($_POST['jmeno']) . ";" . date("j. n. Y H:i:s") . ";"
          . ereg_replace("[\r|\n]+","<br>",strip_tags($_POST['vzkaz'])) . ";" . PHP_EOL;
  //odeslání emailu s upozorněním na nový vzkaz
  mail_utf8("webadmin@domena.tld", "NOVY VZKAZ",
        str_replace(";", PHP_EOL, $string), 'From: webengine@domena.tld');
  //uložení vzkazu do souboru
  $fp = fopen($soubor_vzkazu, 'a');
  fwrite($fp, $string);
  fclose($fp);
}
?>
<br />
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
  <input type="hidden" name="sent" value="1"/>
  <table align="center" border="0">
    <tr valign="top">
      <td><b>Jméno:</b></td>
      <td><input type="text" name="jmeno"/> (< ?php echo date("j. n. Y H:i:s") ?>)</td>
    </tr>
    <tr valign="top" align="right">
      <td><b>Vzkaz:</b></td>
      <td><textarea name="vzkaz" cols="40" rows="5"></textarea></td>
    </tr>
    <tr align="center">
      <td colspan="2">Jakožto autor stránek si vyhrazuji právo vzkazy cenzurovat
        <br />... až k úplnému smazání ;-)</td>
    </tr>
    <tr align="center">
      <td colspan="2"><input type="submit" value="Odeslat"/></td>
    </tr>
  </table>
</form>
< ?php
echo "<p align=left><b>Vzkazy:</b>";
$r = 0;
$soubor = fopen($soubor_vzkazu,"r"); 
echo "<ul>";
while($radek = fgetcsv($soubor, 100000, ";")){
  $vzkazy[$r] = $radek;
  $r++;
} 
fclose($soubor);
for($i=--$r;$i>=0;$i--){
  echo "<li>vzkaz " . ($i+1) . ".: ";
  echo "<b>".$vzkazy[$i][0]."</b> (".$vzkazy[$i][1].")<br />&nbsp;";
  echo "<ul><li>\"".$vzkazy[$i][2]."\"<br />&nbsp;</li></ul>";
  if($i > 0)
    echo "<hr width=\"20%\" align=\"left\" size=\"1\"/>";
  echo "</li>";
}
echo "</ul>";
?>

Aktualizace 11. 8. 2011:

Mohou se objevit problémy s diakritikou (viz diskuse pod článkem).
Tyto se dají řešit tak, že část kódu:

while($radek = fgetcsv($soubor, 100000, ";")){
  $vzkazy[$r] = $radek;
  $r++;
}

nahradíte kódem:

while($radek = fgets($soubor)){ 
  $vzkazy[$r] = explode(";",$radek);
  $r++;
}

Aktualizace 17. 5. 2017:

Nejprve potřebné funkce pro připojení k MySQL databázi (a pro jistotu i původní pro odesílání emailů):

< ?php
mysql_connect("host_name", "database_name", "database_password")
  or die("Nelze se připojit k MySQL serveru :-(");
mysql_select_db("database_name")
  or die("Nelze vybrat databázi."); 
mysql_query("SET CHARACTER SET utf8");
 
function dotaz_any($dotaz){
  $query = mysql_query($dotaz);
  return $query;
}
 
function dotaz_select($dotaz){
  $r = 0; $s = 0;
  $query = mysql_query($dotaz);
  if(!mysql_num_rows($query)){
    $pole[$r][$s] = 'No records found';
  }else{
    for($i = 0; $i < mysql_num_rows($query); ++$i){
      while($row = mysql_fetch_array($query, MYSQL_NUM)){
        foreach($row as $cell){
          $pole[$r][$s] = $cell;
          $s++;
        }
        $r++; $s = 0;
      }
    }
  }
  mysql_free_result($query);
  return $pole;
}
 
function mail_utf8($to, $subject = '(No subject)', $message = '', $header = '') {
  $header_ = 'MIME-Version: 1.0' . "\r\n" 
                . 'Content-type: text/plain; charset=UTF-8' . "\r\n";
  mail($to, '=?UTF-8?B?'.base64_encode($subject).'?=', $message, $header_ . $header);
}
?>

A nyní samotný kód (jen pro úplnost – tabulka vzkazy má čtyři pole (sloupce) v tomto pořadí id, kdo, kdy, text):

< ?php
if($_POST['sent']){
  //uložení vzkazu
  $query_string = "INSERT INTO `vzkazy` (`kdo`,`kdy`,`text`)
                   VALUES ('".strip_tags($_POST['jmeno']))."'
                          ,'".date("Y-m-d H:i:s")."'
                          ,'".ereg_replace("[\r|\n]+","<br>",strip_tags($_POST['vzkaz']))."'
                          )";
  dotaz_any($query_string);
  //odeslání emailu s upozorněním na nový vzkaz
  mail_utf8("webadmin@domena.tld", "NOVY VZKAZ",
        str_replace(";", PHP_EOL, $string), 'From: webengine@domena.tld');
}
?>
<br />
<form method="post" action="index.php?kam=<?php echo $_SERVER['PHP_SELF']; ?>">
  <input type="hidden" name="sent" value="1"/>
  <table align="center" border="0">
    <tr valign="top"><td><b>Jméno:</b></td>
        <td>&nbsp;<input type="text" name="jmeno"/> (< ?php echo date("j. n. Y H:i:s") ?>)</td></tr>
    <tr valign="top" align="right"><td><b>Text:</b></td>
        <td><textarea name="vzkaz" cols="60" rows="10"></textarea></td></tr>
    <tr align="center"><td colspan="2">Po odeslání textu jej již nebudeš moci změnit.</td></tr>
    <tr align="center"><td colspan="2"><input type="submit" value="Odeslat"/></td></tr>
  </table>
</form>
< ?php
echo "<p align=left><b>Vzkazy:</b>";
echo "<ul>";
 
$vzkazy = dotaz_select("SELECT `kdo`,`kdy`,`text` FROM `vzkazy`");
$vzkazy_count = dotaz_select("SELECT count(id) FROM `vzkazy`");
 
for($i=--$vzkazy_count[0][0];$i>=0;$i--){
  if($i == $vzkazy_count[0][0]){
    $_SESSION["datum_aktualizace"] = substr($vzkazy[$i][1],0,strripos($vzkazy[$i][1]," "));
  }
  if($vzkazy[$i][3] != ""){
    echo "<li>vzkaz ".($i+1).".: ";
    echo "<b>".$vzkazy[$i][0]."</b> (".date("j. n. Y G:i:s", strtotime($vzkazy[$i][1])).")<br />&nbsp;";
    echo "<ul><li>\"".$vzkazy[$i][2]."\"<br />&nbsp;</li></ul>";
    if($i > 0) echo "<hr width=\"20%\" align=\"left\" size=\"1\"/>";
    echo "</li>";
  }
}
echo "</ul>";
?>

3 komentářů

  1. Ahoj, rád bych s drobnou úpravou Tvůj skript použil na jednom webu, kde se mi nechce tvořit databázi. Ale našel jsem tak jednu chybu, která mi celkem vadí 🙂 a bohužel nevím jak ji odstranit.
    Když zadáš vzkaz „čočka“, tak se zobrazí pouze „očka“. V souboru je to uloženo dobře, do emailu to také přijde správně, ale na webu se to zobrazuje špatně. Nevíš jak to opravit?
    Díky

    1. Díky „testere“ 😉
      zkus tuto část kódu:

      while($radek = fgetcsv($soubor, 100000, ";")){
        $vzkazy[$r] = $radek;
        $r++;
      }

      nahradit kódem:

      while($radek = fgets($soubor)){ 
        $vzkazy[$r] = explode(";",$radek);
        $r++;
      }

      a napiš, prosím, jestli to pomohlo

  2. Wow to je rychlost… super, díky moc, funguje.
    Pokud bys měl chuť a čas se zamyslet nad stránkováním vzkazů (např. po 20) bylo by to fajn.

    Jinak první část skriptu doporučuji dát do solo souboru (a na konec přidat meta tagy pro refresh na index) a volat ho jako action. Zamezí to posílání dvou stejních vzkazů při refresh stránky.

Napsat komentář

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

*