Теперь мы знаем, как вводить комментарии в систему. А как их оттуда извлекать? В предыдущих разделах уже обсуждался механизм подключения комментариев к определенной статье (с помощью столбцов из обеих таблиц) и друг к другу (с помощью поля creply в таблице comments, которое используется для идентификации порождающей ветви определенного комментария). Итак, теперь необходимо превратить эту логическую связь в визуальную.
Для этого нам нужна функция build_tree() . Это рекурсивная функция, запро­граммированная специально для решения задачи итерации по набору узлов "родитель-потомок" и установления связи между ними. В качестве аргументов эта функция требует идентификатор статьи и начальный комментарий. Она использует эту информацию для создания иерархического дерева комментариев по определенной статье. Рассмотрим пример.
Листинг 20.37.
# это рекурсивная функция
# построения дерева комментариев sub build_tree()
{
# получить идентификатор начального комментария и статьи
# в качестве входных параметров $cid = shift; $aid = shift;
# подключиться с базе данных
my $dbh = DBI->connect("DBI:mysql:database=dbl;host=localhost", "root", "pass",
('RaiseError' => 1));
# выполнить запрос
my $sth = $dbh->prepare("SELECT cid, csubject FROM comments where aid = '$aid' AND creply = '$cid'"); $sth->execute();
# если получен результат
# распечатать строку темы комментария
# в противном случае - сообщение, констатирующее отсутствие ком­ментариев
if ($sth->rows() <; 0 && $cid ;; 0)
{
print "<font face;Verdana size;2 color;Black><b>Нет коммента-риев</b></font>"; }
else {
# просмотр результирующего набора while($ref; $sth->fetchrow_hashref())
{
# распечатать комментарии в виде списка
# построить иерархическое дерево с применением рекурсии print "<ul>";
print "<li><a href;"details.cgi?cid;$ref->{'cid'}&aid;$aid"><font
face;Verdana size;2 ;color;Black><b>$ref->{'csubject'}</b></a>&nbsp;</li>n"
build_tree($ref->{'cid'}, $aid);
print "</ul>";
}
}
}
Эта функция сначала открывает соединение с базой данных, используя для этого уже известный метод connect(). Для него также требуются переменные: уровень, с которого необходимо начинать построение структуры дерева, и идентификатор статьи (передаются в виде параметров).
Функция build_tree() выполняет оператор SELECT, получает список комментариев "нулевого уровня" и распечатывает его. Таким образом, для каждой возвращенной записи функция build_tree() вызывает себя рекурсивно с номером записи, снова подключается к базе данных и отображает комментарии уровня 1. Этот процесс продолжается до достижения конца дерева. Для обеспечения правильной идентификации различных уровней используется HTML-конструкция печати списков <ul>. Если на уровне 0 комментариев не обнаружено, отображается сообщение, которое отражает это же самое.
Каждый элемент отображенного списка в конечном итоге ссылается на страницу de-tails.cgi, которая отображает полное содержание комментария. Сама функция build_tree() вызывается описанным выше сценарием article.cgi по ссылке, раз­мещенной под текстом статьи и отделенной от текста парой горизонтальных линий. Предлагаем вашему вниманию доработанный сценарий article.cgi, в который добавлена новая функциональность.