IZONE - http://www.izcity.com/ - бесплатный софт, вэб-сервисы, ресурсы для раскрутки, свежие номера журнала "Internet Zone".

 IZONE 


Perl для веб-мастера-4

Евгений ГРИВАСТОВ (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/

 


Copyright © "Internet Zone"info@izcity.com
Копирование и использование данных материалов разрешается только в случае указания на журнал "Internet Zone", как на источник получения информации. При этом во всех ссылках обязательно явное указание адреса вэб-сайта http://www.izcity.com/. При наличии у копируемого материала авторов и источника информации - их также нужно указывать, наряду со ссылкой на нас.