2004 г.
Гостевая книга из Perl'овки
Дмитрий Лялюев,
«Издательский Дом «КОМИЗДАТ»
Многие начинающие веб-мастера ставят на свои сайты гостевые книги из бесплатных сервисов. Но как же хочется иметь свою собственную!
Собственная гостевая книга, со своим дизайном… Со своим дизайном. Что ж, на самом деле это вовсе не так сложно, как кажется. Давайте разберемся, как написать простую гостевую книгу на Perl.
Итак, прежде всего создаем файлик с именем guestbook.pl. Первая строка нашей гостевой книги будет:
#!/usr/bin/perl
Именно с такой строки начинается любой Perl-скрипт... Или почти с такой, в зависимости от того, где на сервере расположен Perl-интерпертатор.
Затем определим точный путь и имя файла, в котором будут храниться записи гостей нашего сайта:
$file = "/path/to/gb.txt";
Теперь укажем имя файла, из которого будет вызываться скрипт:
$html_file = "guest.shtml";
Так, хорошо… Но только нужно напомнить браузеру, что мы будем выводить HTML-текст, т.е. страничку. Это делается с помощью следующей строки:
print "Content-Type: text/html\n\n";
Обратите внимание на прописные буквы "C" и "T". Они должны быть именно такими, так как это имеет принципиальное значение для браузера.
Для обработки данных, которые передаются из формы, задействуем стандартный модуль CGI:
use CGI qw (:standard);
$q=new CGI ();
Затем читаем содержание элемента формы action и заносим эти данные в переменную $action:
$action = $q->param (action);
Проверяем форму на наличие входящих данных, то есть отсылал ли посетитель нам какое-либо сообщение. И если отсылал, то записываем его в файл:
&post if ($action eq 'post');
Обратите внимание, что &post - это вызов подпрограммы post, которая и записывает новое сообщение в файл. Ею мы займемся вплотную чуть позже.
А пока что нам еще нужно вывести страничку с уже оставленными сообщениями. Для этого мы - опять же, немного погодя - создадим другую подпрограмму - view. А в этом месте кода нам необходимо ее вызвать. Делается это следующей строкой:
&view;
Ну вот - каркас готов. Осталось написать подпрограммы записи (post) и просмотра (view) сообщений. Начнем с post.
Объявляем начало подпрограммы:
sub post {
Теперь нужно прочитать содержимое формы и записать его в переменные. Мы уже делали подобное для элемента action немного выше:
$nick = $q->param (nick);
$msg = $q->param (msg);
Каждое сообщение в гостевой книге имеет дату. Получим ее:
$date = localtime;
Прежде чем писать программу дальше, нужно хорошо продумать, как будут записываться данные в файл, в каком формате они будут хранится. Я предлагаю достаточно простой способ хранения данных:
Дата1 || Ник1 || Сообщение1
Дата2 || Ник2 || Сообщение2
Дата3 || Ник3 || Сообщение3
Таким образом, каждое сообщение занимает в файле отдельную строку, новые сообщения дописываются в конец файла. Но в этом способе есть свои "подводные камни". Что, если посетитель напишет нам послание на несколько строк? Тогда в файле получится "каша". Поэтому, чтобы ее избежать, лучше заменим признаки конца строки \n на переносы, которые поймет браузер (тег <BR>):
$msg =~ s/\n/<br>/g;
Теперь у нас есть все необходимые данные. Но прежде чем их записать, нужно их упорядочить, то есть сформировать строку для записи и в ее конец поставить знак перехода на новую строку. При этом необходимо учесть, что символ | является управляющим и для того чтобы отменить его управляющее действие, нужно перед ним поставить знак "\":
$to_base = "$date \|\| $nick \|\| $msg \|\| \n";
Итак, теперь у нас есть готовая для хранения строка. Осталось записать ее в файл. А для этого нужно открыть файл для записи.
Немного отвлекаясь от нашей программы, напомню, что файл можно открыть тремя способами: на чтение, на запись "с нуля" и на дописывание, соответственно с помощью символов <, > и >>. В нашем случае нужно добавлять новое сообщение в конец файла и при этом не удалять старые данные. Итак, открываем файл на дописывание:
open (OUT, ">>$file");
записываем в файл нашу строку:
print OUT $to_base;
и закрываем файл, а заодно и подпрограмму:
close (OUT);
}
Нам осталось написать подпрограмму просмотра записей. Объявляем ее начало:
sub view {
Открываем файл на чтение:
open (BASE, "<$file");
Читаем содержимое файла в массив @base:
@base = <BASE>;
И закрываем файл gb.txt:
close (BASE);
Теперь формируем цикл для чтения содержимого массива @base:
for ($i=$#base; $i>=0; $i--)
{
В начале цикла значение переменной $i равно количеству строк в массиве - мы будем читать массив с последней строки. Постепенно уменьшая значение $i до нуля, мы таким образом дойдем до первой записи в файле. Этот метод позволяет добиться "обратного" чтения файла - от самой свежей записи к самой ранней - и последняя добавленная запись будет появляться в самом верху страницы.
Как вы, надеюсь, помните, у нас все данные находятся в строках, причем каждая строка содержит дату, ник "гостя" и его сообщение без переносов строк. Для того чтобы на экране восстановить все "как было", нужно разбить эту строку, на чем цикл и закончится:
($date, $nick, $msg)=split (/ \|\| /, $base [$i]);
print "$nick ($date):<br>$msg<br><br>";
}
Итак, все сообщения выведены. Что остается? Внизу, под ними, вывести форму для отправки новых сообщений:
print "
<form action=$html_file method=get>
Nick: <input name=nick><br>
Message: <TEXTAREA ROWS=15 COLS=50 name=msg></TEXTAREA><br>
<input name=action value=post type=hidden>
<input type=submit value=Отправить>
</form>
";
}
Остается дизайн. Нет ничего проще. Делаем самую обычную HTML-страничку с таким дизайном, какой вам нравится, и вставляем в то место, где должны быть записи, такой SSI-код:
<!--#include virtual="/cgi-bin/guestbook.pl?$QUERY_STRING" -->
Называем файл так, как указано в переменной $html_file гостевой книги:
guest.shtml
И радуемся, потому что для приема гостей все готово. Напомню только, что это - очень простой вариант гостевой книги. В идеале нужно ввести запрет на HTML-теги, что не очень сложно. Можно еще организовать постраничный вывод записей, скажем, по 10 штук на страничке, картинки-смайлики, административный интерфейс… Давайте сделаем это домашним заданием. А в следующий раз проверим, как вы справились с административным скриптом, и если что-то не получилось, то напишем его вместе.