Ниже представлена таблица, предназначенная для хранения комментариев читателей. Данные в нее вводятся читателями с помощью прикладного интерфейса, который мы будем создавать на следующих страницах этой книги.
Листинг 20.32.
CREATE TABLE comments (
cid int(8) NOT NULL auto_increment, aid int(8) NOT NULL default '0',
cemail varchar(255) default NULL, ctimestamp datetime default NULL, csubject varchar(255) NOT NULL default ' ', cpost text NOT NULL, creply int(8) NOT NULL default '0', PRIMARY KEY (cid) ) TYPE=MyISAM;
Все введенные в эту таблицу комментарии ассоциируются с идентификатором опре­деленной статьи - здесь столбец aid служит ссылкой по внешнему ключу на предыдущую таблицу articles. Каждый комментарий обладает несколькими атрибутами: временной отметкой, электронным адресом лица, прокомментировавшего статью, строкой с темой комментария, текстом самого комментария и флага, отражающего тот факт, что комментарий начинает новую ветвь или является продолжением уже существующей ветви. Последняя задача возложена на поле creply, идентифицирующее уровень комментария в "дереве" дискуссии и поэтому облегчающее установку связи между сообщениями при воссоздании структуры дерева комментария. Значение поля creply, равное 0, свидетельствует о том, что над этим комментарием уже больше нет комментариев ... другими словами, это новая "ветвь" дискуссионного дерева. 
Создание индекса статьи
Имея в распоряжении таблицы, созданные в соответствии с определенными требо­ваниями, можно приступать к написанию программного кода, который бы отображал список всех имеющихся в наличии статей, краткое содержание каждой статьи и ссылку на ее полный текст. Эти данные будут выбраны из базы данных MySQL с использованием методов Perl DBI.
Этот сценарий представлен ниже.
Листинг 20.33.
#!/usr/bin/perl
# считать необходимые модули use DBI;
use CGI;
# инициировать объект CGI $cgi = new CGI();
# распечатать HTTP-заголовки print $cgi->header();
# распечатать заголовок страницы print $cgi->start_html;
print <<EOH;
<font face="Verdana, Arial" size="4" color="#66CCOO"> Архив статей: </font>
<p>
<font face="Verdana, Arial" size="2" color="Black"> <ul>
EOH
# подключиться к базе данных
my $dbh = DBI->connect("DBI:mysql:database=db1;host=localhost", "root", "pass", ('RaiseError' => 1});
# выполнить запрос
my $sth = $dbh->prepare("SELECT aid, atitle, adesc FROM articles"); $sth->execute();
# просмотр результирующего набора
# распечатка списка статей while($ref = $sth->fetchrow_hashref())
{
print "<li><a
href="article.cgi?aid=$ref->{'aid'}">$ref->{'atitle'}</a><br>n"; print "$ref->{'adesc'}<p>n";
}
# закрыть соединение с базой данных $sth->finish(); $dbh->disconnect();
# распечатать нижний колонтитул страницы print <<EOF;
</ul>
</font> EOF
print $cgi->end_html;
Подсказка по инструментарию
Напомним, что сценарии, представленные в этом разделе, в своей работе широко используют модуль CGI.pm Perl. Этот модуль используется Web-разработчиками для создания Web-приложений посредством Perl, прежде всего потому, что он обладает мощным и гибким API-интерфейсом, предназначенным для динамического конструи­рования Web-страниц с помощью вызова простых методов. Среди его возможностей есть функции отправки стандартных или адаптированных HTTP-заголовков, создание гиперссылок, форм, рамок и других HTML-конструктивов, форматирование текста в HTML-код и автоматическое присвоение данных, полученных методами POST или GET, переменным Perl.
Вот список наиболее важных методов модуля CGI.pm, использованных в этом разделе:
• header() - отправляет HTTP-заголовки клиенту;
• start_html() - распечатывает открывающие теги;
• end_html() - распечатывает закрывающие теги;
• url() - выбор URL выполняемого сценария;
• param() - выбор значения переменных из строки запроса (метод GET) или данных (метод POST).
Подробнее о CGI.pm можно узнать по адресу http://search.cpan.org/ author/JHI/perl-5.8.0/lib/CGI.pm.
Вспомогательные функции
 Теперь, когда вы хорошо понимаете, как работает DBI-интерфейс Perl, объяснить логику работы предыдущего сценария совсем несложно. Он открывает соединение с базой данных MySQL, отправляет запрос для получения списка всех существующих статей и отображает их на Web-странице в виде списка. Заголовки статей связаны с отдельным сценарием - article.cgi. Этому сценарию с помощью метода URL GET передается идентификатор статьи. Результирующий набор выбирается и обрабатывается с помощью обсужденного здесь метода fetchrow_hashref(). Окончательный результат его работы представлен на рис. 20.3.