- Евгений ГРИВАСТОВ (tw@tv-gent.net)
Модернизация
гостевой книги.
В прошлый раз мы сделали
простейшую гостевую книгу. Теперь
давайте научим наш скрипт работать с
несколькими гостевыми книгами и
выдавать на просмотр не все сообщения
сразу, а пакетами по 20 штук. Чтобы было
понятней, сделаем два скрипта: один для
просмотра гостевой книги, второй - для
добавления записей. У нас уже есть
директория gb, в которой лежит файл
нашей первой гостевой книги. Создайте в
этой директории новую поддиректорию,
например firstgb - это будет директория
для первой из гостевых книг,
обрабатываемых нашими новыми
скриптами. В директорию firstgb положите
два пустых файла - counts.txt и countf.txt.
Назначьте этим файлам права доступа 666.
Их предназначение - хранить информацию
о количестве файлов с сообщениями
гостевой книги (countf.txt) и количестве
записей в последнем из файлов (counts.txt). В
директорию gb положите файл listgb.txt со
следующей строкой:
first::firstgb
Это будет список гостевых книг,
обслуживаемых нашими скриптами. Первым
в строке идет идентификатор гостевой
книги, вторым - название директории
гостевой книги. Разделитель между ними
- "::" (два двоеточия). Если вам
понадобится добавить еще одну гостевую
книгу - просто допишите в этот файл
строку с информацией об этой книге.
Например:
second::secondgb
После чего создайте соответствующую
директорию и положите в нее все те же
два файла - counts.txt и countf.txt, назначив им
права доступа 666. В результате
получится такая структура директорий,
как на рис. 1.
Сначала сделаем скрипт просмотра
записей гостевой книги. Назовем его showgb.cgi.
Сообщения у нас будут храниться в
файлах по 20 штук. Именами файлов у нас
будут их порядковые номера (1.txt, 2.txt
и т. п.). Скрипт этот мы будем вызывать,
указывая в качестве параметра (после
знака "?") идентификатор
гостевой книги, а через "&" -
номер двадцатки, сообщения из которой
надо показывать. Т. е. примерно так:
http://www.your_domen.com/cgi-bin/countstat.cgi?first
&1
причем второй параметр будет
необязательным - при его отсутствии
скрипт просто будет показывать
последние записи в книге.
Итак, переходим к рассмотрению кода
программы.
#!/usr/local/bin/perl
$gbid=$ENV{'QUERY_STRING'};
($gbid,$numzap)=split(/&/,$gbid);
# Здесь мы используем переменную $gbid два
раза - сначала мы помещаем
# в нее полностью всю строку запроса,
потом, разделив строку запроса на
# два параметра (с помощью функции split),
присваиваем этой переменной
# значение идентификатора гостевой
книги. В переменной $numzap будет
# номер файла с сообщениями, содержимое
которого надо показать.
$dir='/home2/your_domen/public_html/gb/';
# В переменной $dir будет храниться полный
путь к директории gb.
$filename=$dir.'listgb.txt';
open (FLFL, "$filename");
foreach $stroka (<FLFL>) {
($id,$gbdir)=split(/::/,$stroka);
last if ($id eq $gbid);
}
close FLFL;
# Здесь мы открываем файл со списком
гостевых книг и находим в нем запись
нашей.
# В результате получим в переменной $gbdir
имя директории той гостевой книги,
# с которой мы работаем. Теперь, чтобы
проверить, действительно ли мы нашли
# запись запрошенной гостевой книги или
не нашли ничего, еще раз проверим,
# равно ли значение переменной $id запрошенному
# значению идентификатора гостевой
книги:exit if ($id ne $gbid);
# Если в переменные $id и $gbid не
равны - завершаем работу скрипта.
Отвлечемся немного,
чтобы рассмотреть подробней операции
сравнения, одну из которых мы
использовали в последней строке.
Операция
сравнения
|
Числовая
|
Строковая
|
Равно
|
==
|
Eq
|
Не равно
|
!=
|
Ne
|
Меньше чем
|
<
|
Lt
|
Больше чем
|
>
|
Gt
|
Меньше или равно
|
<=
|
Le
|
Больше ил равно
|
>=
|
Ge
|
Как видно, для чисел и
строк (т. е. текста) предусмотрены
собственные операции сравнения. Связано
это с тем, что скалярная переменная в Perl
может рассматриваться и как строка, и
как число. Поэтому надо указывать, в
каком виде вы производите сравнение. В
нашем случае - в строковом: мы проверяем,
равны ли значения переменных $id и $gbid.
Значит, используем оператор "ne".
И немного об условном операторе if. Он
проверяет условие, заданное в круглых
скобках, и в зависимости от результата
выполняет блок команд. Синтаксис его
может быть таким:
if (выражение) {блок команд};
или таким:
if (выражение) {блок команд} else {блок
команд};
или:
if (выражение) {блок команд} elsif (выражение)
{блок команд} else {блок команд};
или просто:
команда if (выражение);
Т. е. в случае, когда в результате
выполнения условия необходимо
выполнить только одну команду -
используется последний вариант
синтаксиса. Его мы и использовали для
проверки, найдена ли запись с нужным нам
идентификатором гостевой книги. Если
такой записи не найдено, выполняется
команда exit - скрипт завершает свою
работу.
Вернемся к нашему скрипту. Для начала
получим количество файлов с записями
этой гостевой книги.
# Составим путь к файлу-счетчику
и считаем из него число.
$filename=$dir.$gbdir.'/countf.txt';
open (FILE, "$filename");
$countf = <FILE>;
close(FILE);
# Если записей в этом файле нет, то в
переменной $countf окажется
значение "0" (ноль).
# Если номер, требуемый скриптом, больше,
чем количество файлов
#с записями - завершаем работу скрипта. А
тот, кто хотел найти в этом
#месте скрипта дыру - пусть отдыхает... :-).
exit if ($countf<$numzap);
# Если в переменной $numzap ничего нет (т.
е. этот параметр
#не передавался скриптом) - присвоим ему
значение количества файлов с
#записями. Таким образом мы будем по
умолчанию выводить последние записи.
$numzap=$countf if (! $numzap);
# Выведем в броузер собственно страницу
гостевой книги
print "Content-Type: text/html\n\n";
print '<html><head></head><body><p><b>Моя
гостевая книга</b></p><hr>';
# Выведем список для доступа к архиву
записей гостевой книги
for ($iii=$countf; $iii>=1; $iii--) {
if ($iii==$numzap) {
print '<b>'.$iii.'</b> ';
} else {
print '<a href=hОшибка! Закладка не
определена..'&'.$iii.'>'.$iii.'</a>';
} #if
} #for
# Теперь покажем записи из запрошенного
файла
$filename=$dir.$gbdir.'/'.$numzap.'.txt';
open (FILE, "$filename");
@zapisi = <FILE>;
close(FILE);
foreach $stroka (@zapisi) {
($nik,$email,$message)=split(/|/,$stroka);
print '<hr>';
print '<a href=mailto:'.$email.'>'.$nik.'</a><br>'.$message;
} #foreach
# Форма для добавления новых записей
print '<hr>';
print '<form action="http://your_domen.com/cgi-bin/addgb.cgi"
method="post">';
print '<input type="hidden" name="gbid" value='.$gbid.'><br>';
print 'Ник: <input type="text" name="nik" size="20"><br>';
print 'E-mail: <input type="text" name="email" size="20"><br>';
print 'Сообщение: <input type="text" name="message"
size="20"><br>';
print '<input type="submit" value="Записать"></form>';
print '</body></html>';
exit;
Теперь сделаем скрипт,
который будет добавлять записи в нашу
гостевую книгу. Это будет тот самый addgb.cgi,
который мы прописали в форме добавления
новых записей в предыдущем скрипте.
#!/usr/bin/perl
# С помощью подпрограммы GetFormInput данные,
полученные
# из формы, поместим в хэш %field:
&GetFormInput;
# Присвоим данные полей html-формы
переменным $gbid,
# $nik, $email и $message:
$gbid=$field{"gbid"};
$nik=$field{"nik"};
$email=$field{"email"};
$message=$field{"message"};
# В переменной $dir - полный путь к
директории gb:
$dir='/home2/your_domen/public_html/gb/';
# Далее идет то, что мы уже проделывали в
предыдущем скрипте просмотра
гостевой книги:
$filename=$dir.'listgb.txt';
open (FLFL, "$filename");
foreach $stroka (<FLFL>) {
($id,$gbdir)=split(/::/,$stroka);
last if ($id eq $gbid);
}
close FLFL;
exit if ($id ne $gbid);
# Составим путь к файлу - счетчику
количества записей в последней
#из файлов гостевой книги и считаем из
него цифру.
$filename=$dir.$gbdir.'/counts.txt';
open (FILE, "+<$filename");
flock (FILE,2);
$counts = <FILE>;
# Переместим указатель позиции в файле
на его начало.
seek (FILE,0,0);
# Усечем файл по указатель позиции (т. е. в
нашем случае - очистим).
truncate(FILE,0);
# Если количество записей меньше 20, то
сделаем новую запись в этот
# же файл. Заодно увеличим значение
счетчика записей на единицу:
if ($counts<20) {
$counts=$counts+1;
$filename=$dir.$gbdir.'/countf.txt';
open (FILEF, "$filename");
$countf = <FILEF>;
close(FILEF);
} else {
# Если количество записей не меньше
20, то запишем новую запись
#в новый файл. Заодно значение
счетчика записей установим в единицу
и
#увеличим значение счетчика файлов
гостевой книги:
$counts=1;
$filename=$dir.$gbdir.'/countf.txt';
open (FILEF, "+<$filename");
flock (FILEF,2);
$countf = <FILEF>;
$countf=$countf+1;
seek (FILEF,0,0);
truncate(FILEF,0);
print FILEF "$countf";
close(FILEF);
}
$filename=$dir.$gbdir.'/'.$countf.'.txt';
chmod (0666, $filename);
open (FILEF, ">>$filename");
print FILEF $nik.'|'.$email.'|'.$message;
close(FILEF);
print FILE "$counts";
close(FILE);
# Перенаправим браузер на
отредактированный файл нашей
гостевой
#книги (пропишите здесь правильный
полный URL скрипта просмотра гостевых
#книг на вашем сайте).
print "Location: http://www.your_domen.com/cgi-bin/countstat.cgi?first
\n\n";
exit;
# Подпрограмма, разбирающая полученные
из формы данные и помещающая
# их в хэш %field:
sub GetFormInput {
# Не будем ее здесь повторять, дабы не
занимать напрасно место.
#Я уже писал, что эта подпрограмма
стандартна для всех скриптов.
Поэтому
#возьмите ее код из программ,
рассмотренных нами ранее.
}
Если вы
последовательно читали все статьи этого
цикла и разбирали все приведенные в
тексте примеры, то должны понять и то,
что мы проделали в последнем скрипте.
Ничего нового в нем нет. Однако остались
некоторые операторы, назначение которых
мы еще не рассматривали подробно. Это
операторы цикла. Например, сегодня мы
использовали оператор for. Основных
таких операторов три: for, foreach и while.
Оператор цикла for имеет следующий
синтаксис:
for (выражение1; выражение2; выражение3) {блок
операторов}
Выражение1 вычисляется вначале
цикла и обычно задает начальное
значение переменной-счетчика цикла. Выражение2
является логическим: если оно станет
ложью, то цикл прерывается. Наконец, выражение3
вычисляется в конце каждого прохода
цикла, перед проверкой истинности выражения1.
Если в начале цикла выражение2 оказывается
ложью - блок операторов цикла не
выполняется ни разу.
Оператор цикла foreach является
подобием for и используется, когда
необходимо перебрать все данные из
какого-нибудь списка, массива или хэша.
Его синтаксис такой:
foreach переменная (список) {блок
операторов};
При каждом проходе цикла из списка
извлекается очередное значение и
присваивается переменной. После этого
выполняется блок операторов цикла.
Когда все значения списка перебраны,
цикл завершается.
Синтаксис оператора while выглядит так:
while (выражение) {блок операторов};
Блок операторов будет выполняться,
пока выражение будет оставаться
истинным. Поэтому будьте внимательны:
если вы умудритесь сделать так, что
выражение будет истинным всегда - цикл
не завершится никогда :-). Удобно
использовать оператор while в паре с
оператором each для перебора всех
записей хэша, что мы успешно применили в
нашем скрипте countstat.cgi ("МК"
№48(115)).
(...продолжение следует...)
Источник: http://www.mycomp.com.ua/
|