MySQL / 17. Внедрение результатов запросов в веб-страницы

Представление результатов запроса в виде гиперссылок

Задача
Вы хотите генерировать гиперссылки на основе содержимого базы данных.

Решение
Добавьте к содержимому теги ссылок.

Обсуждение
Примеры предыдущих разделов формируют статический текст, но на основе содержимого базы данных можно создавать и гиперссылки. Если вы храните в таблице адреса веб-сайтов или адреса электронной почты, то без труда можно преобразовать их в активные ссылки на веб-страницах. Нужно лишь соответствующим образом перекодировать информацию и добавить теги HTML.

Предположим, что у вас есть таблица с названиями компаний и их веб-сайтами, например, таблица book_vendor со списком книготорговцев и издателей:

mysql> SELECT * FROM book_vendor ORDER BY name;

+-----------------------+------------------------+
| name                       | website                      |
+-----------------------+------------------------+
| Barnes & Noble        | www.bn.com            |
| Bookpool                 | www.bookpool.com |
| Borders                    | www.borders.com    |
| Fatbrain                   | www.fatbrain.com     |
| O'Reilly & Associates | www.oreilly.com       |
+-----------------------+------------------------+

Содержимое таблицы легко преобразуется в гиперссылку. Чтобы превратить строку в гиперссылку, добавьте спецификатор протокола http:// к значению website, используйте результат как атрибут href тега (a) и используйте значение name в теле тега в качестве текста ссылки. Например, строку для Barnes & Noble можно записать так:

(a href="http://www.bn.com")Barnes & Noble(/a)

Код JSP, выводящий маркированный (неупорядоченный) список гиперссылок для содержимого таблицы, выглядит так:

<sql:query var="rs" dataSource="${conn}">
SELECT name, website FROM book_vendor ORDER BY name
</sql:query>
<ul>
<c:forEach var="row" items="${rs.rows}">
<li>
(a href="http://<c:out value="${row.website}" />")
<c:out value="${row.name}" />(/a)
</li>
</c:forEach>
</ul>

При отображении на веб-странице название каждого продавца из списка становится активной ссылкой, выбрав которую вы попадете на его веб-сайт. В Python аналогичная операция выполняется так:

query = "SELECT name, website FROM book_vendor ORDER BY name"
cursor = conn.cursor ()
cursor.execute (query)
items = []
for (name, website) in cursor.fetchall ():
items.append ("%s" \
% (urllib.quote (website), cgi.escape (name, 1)))
cursor.close ()
# вывести элементы, но не кодировать, так как они уже закодированы
print make_unordered_list (items, 0)

Сценарии на Perl, использующие CGI.pm, выводят гиперссылки при помощи вызова функции a():

a ({-href => "url-значение"}, "наименование ссылки")

Эту функцию можно использовать для вывода списка ссылок на продавцов:

my $sth = $dbh->prepare (
"SELECT name, website
FROM book_vendor
ORDER BY name");
$sth->execute ();
my @items = ();
while (my ($name, $website) = $sth->fetchrow_array ())
{
push (@items, a ({-href => "http://$web-site"}, escapeHTML ($name)));
}
print ul (li (\@items));

Еще одной часто встречающейся задачей веб-программирования является формирование ссылок для адресов электронной почты. Предположим, чтоу вас есть таблица newsstaff, в которой перечислены отдел (department), фамилия (name) и (если известен) адрес электронной почты (email) для корреспондентов и обозревателей службы новостей телекомпании WRRR:

mysql> SELECT * FROM newsstaff;

+---------------------+--------------------+-------------------------------+
| department            | name                  | email                                  |
+---------------------+-------------------+--------------------------------+
| Sports                   | Mike Byerson     | mbyerson@wrrr-news.com  |
| Sports                   | Becky Winthrop | bwinthrop@wrrr-news.com |
| Weather                | Bill Hagburg       | bhagburg@wrrr-news.com  |
| Local News            | Frieda Stevens    | NULL                                  |
| Local Government | Rex Conex          | rconex@wrrr-news.com      |
| Current Events      | Xavier Ng           | xng@wrrr-news.com           |
| Consumer News    | Trish White         | twhite@wrrr-news.com       |
+---------------------+-------------------+--------------------------------+

По таблице можно сформировать каталог он-лайн со ссылками на электронные адреса всех служащих, чтобы посетители сайта могли без проблем отправить письмо любому сотруднику. Например, строка для спортивного обозревателя Mike Byerson (электронный адрес mbyerson@wrrr-news.com) будет содержать такую конструкцию:

Sports: (a href="mailto:mbyerson@wrrr-news.com")Mike Byerson(/a)

Содержимое таблицы без труда преобразуется в такой каталог. Для начала давайте поместим код генерирования ссылки на электронный адрес во вспомогательную функцию, поскольку такая операция наверняка пригодится нам и во многих других сценариях. В Perl эта функция может выглядеть так:

sub make_email_link
{
my ($name, $addr) = @_;
# вернуть имя в виде статического текста, если адрес пустой или undef
return (escapeHTML ($name)) if !defined ($addr) || $addr eq "";
# в противном случае вернуть гиперссылку
return (a ({-href => "mailto:$addr"}, escapeHTML ($name)));
}

Функция обрабатывает возможность отсутствия у кого-то электронного адреса, выводя в таком случае имя как обычный текст. Используем функцию в цикле, который будет извлекать имена и адреса и выводить перед ссылкой на каждый адрес название отдела сотрудника:

my $sth = $dbh->prepare (
"SELECT department, name, email
FROM newsstaff
ORDER BY department, name");
$sth->execute ();
my @items = ();
while (my ($dept, $name, $email) = $sth->fetchrow_array ())
{push (@items, escapeHTML ($dept) . ": " . make_email_link ($name, $email));
}
print ul (li (\@items));

Такие же функции генерирования ссылок на адреса электронной почты для PHP и Python будут выглядеть так:

function make_email_link ($name, $addr)
{
# вернуть имя в виде статического текста, если адрес не задан или пустой
if (!isset ($addr) || $addr == "")
return (htmlspecialchars ($name));
# в противном случае вернуть гиперссылку
return (sprintf ("%s",
$addr, htmlspecialchars ($name)));
}
def make_email_link (name, addr):
# вернуть имя в виде статического текста, если адрес None или пустой
if addr is None or addr == "":
return (cgi.escape (name, 1))
# в противном случае вернуть гиперссылку
return ("%s" % (addr, cgi.escape (name, 1)))

Для страницы JSP можно вывести список newsstaff так:

<sql:query var="rs" dataSource="${conn}">
SELECT department, name, email
FROM newsstaff
ORDER BY department, name
</sql:query>
<ul>
<c:forEach var="row" items="${rs.rows}">
<li>
<c:out value="${row.department}" />:
<c:set var="name" value="${row.name}" />
<c:set var="email" value="${row.email}" />
<c:choose>
<%-- null or empty value test --%>
<c:when test="${empty email}">
<c:out value="${name}" />
</c:when>
<c:otherwise>
(a href="mailto:<c:out value="${email}" />")
<c:out value="${name}" />(/a)
</c:otherwise>
</c:choose>
</li>
</c:forEach>
</ul>

Статьи по MySQL на эту тему:

Извлечение изображений и других двоичных данных
Использование результатов запроса для загрузки файлов
Работа с баннерами
Создание навигационного индекса
Хранение изображений и других двоичных данных