Глава
№12.
PHP
и другие средства поддержки
HTML, управляемого
базами данных
Есть несколько
простых в использовании программных расширений HTML, обеспечивающих поддержку
доступа к серверам баз данных MySQL и mSQL с веб-страниц. В этой главе мы начнем
с W3-mSQL -средства для mSQL. Затем покажем менее связанный с конкретной базой
данных подход с помощью РНР и двух небольших расширений Perl. Имеющийся в W3-mSQL
язык сценариев Lite позволяет встраивать в HTML-файлы целые программы. CGI-программа
выполняет сценарий и посылает клиенту результат в виде динамически создаваемого
документа HTML.
Поскольку
W3-mSQL и другие расширения, рассматриваемые в данной главе, используют собственные
языки сценариев и скрывают всякие признаки использования CGI, в этой главе не
требуется знания предшествующего материала данного раздела. Однако при чтении
главы может оказаться полезным понимание того, как работает CGI, a также наличие
некоторого предшествующего опыта программирования (Lite сходен как с С, так
и с Perl).
Альтернативные
методы создания динамического содержания Web
Впервые то,
что сейчас мы называем Dynamic HTML, появилось в Web в виде Server Side Includes
(SSI) - «включений на стороне сервера». В основе SSI лежит та мысль,
что есть ряд часто встречающихся величин, таких как текущие дата и время, которые
включать в HTML-страницу
полезно, но непрактично, поскольку они очень часто изменяются. SSI дает способ,
которым HTML-страница может потребовать от сервера включить в нее значения таких
параметров перед тем, как послать страницу конечному пользователю. Благодаря
этому параметр всегда имеет текущее значение, а создателю страницы нет необходимости
непрерывно ее обновлять. Типичная директива SSI на странице HTML выглядит так:
<!--#echo
var="DATE_LOCAL" -->
Проблема
SSI в том, что набор данных, который сервер может легко предоставить, очень
ограничен. Сверх даты, времени и способности включать другие файлы остается
не много возможностей без того, чтобы сам веб-сервер не начал серьезно разрастаться.
Вскоре стало
ясно, что если сам веб-сервер не обеспечивает динамического HTML, он может появиться
только из двух источников. Либо клиент, то есть веб-броузер, интерпретирует
команды, либо какая-нибудь другая программа на сервере осуществляет предварительную
обработку команд, выдавая конечному пользователю чистый HTML.
Первый путь
привел к JavaScript и аналогичным технологиям. В JavaScript, как и в SSI, команды
встраиваются в HTML. В отличие от SSI, сервер не трогает команды JavaScript,
их обрабатывает броузер. Такой способ предоставляет значительно лучшее взаимодействие
с пользователем. Например, JavaScript позволяет определить действия, которые
должны производиться при перемещении пользователем мыши над различными участками
экрана. Благодаря этому удается создать ощущение непосредственности и интерактивности,
недостижимые другими средствами. Вот пример типичного кода JavaScript:
<SCRIPT>
<! onMouseOver("станцевать
джигу"); -->
</script>
Трудность,
вызываемая решениями, работающими только на стороне клиента, такими как JavaScript,
состоит в том, что, как только клиент заканчивает загрузку страницы, связь с
сервером теряется. Очень часто на сервере располагаются ресурсы, например, серверы
баз данных, с которыми хотелось бы взаимодействовать. Однако сценарии, выполняемые
на стороне клиента, обычно делают невозможной или неэффективной связь с сервером
или другой удаленной машиной после того, как страница загружена. Такого рода
функциональность больше соответствует решениям на стороне сервера.
При наличии
интерпретатора на стороне сервера документ HTML просматривается перед тем, как
быть отосланным конечному пользователю. Какая-либо программа, обычно программа
CGI, выявляет и выполняет программный код, встроенный в HTML. Преимущество такой
системы в том, что используется мощь CGI-программы и значительная доля сложности
остается скрытой.
Предположим,
что есть морская организация с базой данных об акулах. База данных содержит
важную статистику по различным видам акул, а также имена файлов с изображениями
этих тварей. Для создания веб-интерфейса к этой базе данных идеально применим
HTML с интерпретацией на сервере. Все выходные страницы с информацией о выбранном
виде акулы имеют идентичный формат. В местах, где требуются динамические данные
из базы, можно вставить команды, которые будут выполнены до того, как пользователь
увидит страницу. Можно даже генерировать динамические теги <IMG> для показа
желаемых изображений. Позднее в этой главе мы покажем, как можно реализовать
этот пример с помощью различных интерпретаторов на сервере.
W3-mSQL является,
в сущности, одной программой CGI, называющейся w3-msql. Программа фильтрует
страницы HTML со встроенными командами W3-mSQL и посылает клиенту очищенный
результирующий HTML. Команды W3-mSQL пишутся на специальном языке программирования,
называемом Lite. Lite во многом схож с Perl и С, но разработан специально для
взаимодействия с базами данных mSQL. Краткий справочник по функциям Lite есть
в конце главы 18 «Справочник по PHP Lite». Для осуществления
этого к URL для w3-msql добавляется путь к HTML-файлу, с расширениями W3-mSQL,
например, http://www.me.com/cgi-bin/w3-msql/~me/mypage.html.
Содержимое
HTML-файла внутри тега <! > интерпретируется как команды Lite. Например,
эквивалент программы "Hello world!" на Lite выглядит так:
<HTML><HEAD><TITLE>Hello
world!</title></head>
<BODY>
<!
echo("Hello world!");
>
</body></html>
Все, что
не находится внутри тегов <! >, остается чистым HTML.
mSQL автоматически
устанавливает программу w3-msql, и вам остается только поместить ее в
свой каталог cgi-bin.
W3-Auth
W3-Auth является
механизмом, обеспечивающим защиту страниц, управляемых W3-mSQL. Он включается
вместе с W3-mSQL и устанавливается автоматически с mSQL. С помощью W3-Auth можно
создать иерархию пользователей и групп, которым разрешено использовать различные
страницы с расширениями W3-mSQL.
W3-Auth использует
три различных уровня доступа: пользователь, группа и область. Пользователь
отдельное имя, обычно относящееся к отдельному лицу, примерно как имя пользователя
в Unix. Груп па является собранием пользователей. Область является
разделом веб-сайта, который вы хотите защитить.
Такая схема
особенно полезна для сайтов со многими виртуальными узлами на одном веб-сервере.
Допустим, например, что на вашем компьютере расположены виртуальные серверы
с именами serverl, ser-ver2 и server3. Каждое из этих различных
имен администрируется различными группами людей. Вы можете создать три разные
области, охватывающие эти три сайта, и тогда члены каждой группы будут в состоянии
управлять доступом к своей странице с расширениями W3-mSQL, но не смогут вмешаться
в управление другими сайтами.
Установка
Обе программы,
W3-mSQL и W3-Auth, компилируются и устанавливаются автоматически, вместе с дистрибутивом
mSQL. После установки они находятся в MSQL_HOME/bin, где MSOL_HOME есть
местонахождение файлов mSQL - по умолчанию /usr/local/Hughes. Исполняемые
файлы w3-msql и w3-auth нужно скопировать в каталог cgi-bin
вашего сервера или эквивалентный ему.
После установки
W3-Auth предполагает, что она сама и программа w3-msql находятся в каталоге
cgi-bin вашего сайта. Если вы хотите поместить эти программы в другой
каталог, нужно вручную изменить исходный код перед установкой mSQL. С помощью
Perl это можно сделать следующим образом. Находясь в каталоге src/w3-msql
дистрибутива mSQL, введите: perl -pi -e 's/cgi-bin/yourcgidirectory/g'
*.c. Другой возможностью сделать то же самое является использование такого
сценария:
#!/bin/sh
# Запустите
это из каталога src/w3-msql своего дистрибутива с исходным кодом mSQL.
for file in
'Is *.c'; do
sed -e "s/cgi-bin/$1/"
$file > $file.tmp
mv $file.tmp $file
done
Скопируйте
этот сценарий в ваш каталог src/w3-msql и введите следующую команду:
./scriptname yourcgidirectory
Здесь scriptname
является именем сценария, a yourcgidirectory - именем
каталога, который будет содержать исполняемые файлы w3-msql и w3-auth.
W3-Auth в
настоящее время не совместим с распространяемой версией веб-сервера Apache из-за
одной небольшой особенности системы безопасности
Apache. Apache не позволяет программам CGI иметь доступ к данным авторизации.
Без этой возможности ни одна CGI-программа, включая W3-Auth, не может выводить
пользователю стандартное окно для ввода имени пользователя/пароля и получать
из него результаты. Ввиду важности Apache для сообщества пользователей mSQL,
был быстро выпущен патч, позволяющий W3-Auth работать вместе с Apache. После
его установки необходимо перекомпилировать Apache. Заметьте, что установка данного
патча позволяет любым CGI-програм-мам получать имя пользователя и пароль у посетителей
сайта. Если вы доверяете тем, кто имеет доступ к CGI-программам на вашей машине,
то подобный метод относительно безопасен.
После установки
mSQL в каталоге misc домашнего каталога mSQL появляется сценарий с именем
setup_www. Выполнение этого сценария приводит к созданию баз данных и
таблиц, необходимых для использования W3-Auth на вашей машине. Этот сценарий
создает имя пользователя и пароль для того, кто будет иметь полный контроль
над W3-Auth. После завершения работы этого сценария можно использовать собственно
W3-Auth для создания и изменения других прав доступа.
Пример
использования W3-mSQL
Для иллюстрации
использования W3-mSQL и Lite снова рассмотрим пример с морской организацией.
У организации свой собственный вебсайт. На этом сайте есть интерактивная база
данных, содержащая сведения о различных видах акул, обитающих в океанах. В нашем
примере пользователь сначала получает простую HTML-страницу, содержащую форму.
Задав в форме значения, пользователь может осуществлять поиск в базе данных
по акулам для извлечения информации об отдельных видах. Форма HTML будет выглядеть
примерно так:
<НТМL><НЕАD><TITLЕ>АКУЛЫ!</TITLЕ></head>
<BODY BGCOLOR="white">
<h1>Поиск
в базе данных по акулам</h1>
<Р>
<FORM METHOD=POST
ACTION="/cgi-bin/w3-msql/"sharks/search_result.html">
Вид: <SELECT
NAME="species">
<OPTION>
<OPTION>Heterodontus
Portusjackson
<OPTION>Galeocerdo
Cuvier
<OPTION>Carcharodon
Carcharias
<OPTION>Isurus
Paucus
</select>
Возраст: <SELECT
NAME="age">
<OPTION>
<OPTION>Молодые
<OPTION>Взрослые
<OPTION>Старые
</select>
Район: <SELECT
NAME="location">
<OPTION>
<OPTION>Atlantic
<OPTION>Pacific
<OPTION>Caribean
<select>
<p>
<INPUT TYPE="SUBMIT"
VALUE=" Ввести "> <INPUT TYPE=RESET>
</form>
</body>
</html>
Таблица mSQL, содержащая сведения об акулах, имеет следующую структуру:
Файл HTML
/~sharks/search_result.html является файлом с расширениями W3-mSQL, извлекающим
данные о запрошенном виде и выводящим данные об этой акуле.
<НТМL>
<НЕАD><ТITLЕ>Результаты
поиска акулы</ТITLЕ></head>
<BODY>
<Н1>Вот
акулы, удовлетворяющие условиям поиска...</h1>
<Р> <!
$sock = msqlConnectO;
if ($sock <
0) {
ech-o("Error
: $ERRMSG\n");
exit(1);
}
if (msqlSelectDB($sock,
"sharks") < 0) {
echo("Error
: $ERRMSG\n");
exit(1); }
/* Начинаем построение запроса. В результате типичный запрос
*может выглядеть так:
* SELECT * FROM
SHARK WHERE SPECIES='Isurus Paucus' AND AGE=2
*/
$query = "select
* from sharks ";
if (Sspecies
| Sage || Slocation) {
Squery +-
" where "; }
if (Sspecies) { $query += $species = '$species'"; }
if ($age) {
if (Sspecies)
{ $query += " and "; }
$query += "age = Sage"; }
if (Slocation)
{
if ($species
| Sage) { $query += " and "; }
Squery += "location
= 'Slocation''";
}
if (msqlQuery($sock,Squery) < 0) { echo("Error : $ERRMSG\n");
exit(1); }
Sresult = msqlStoreResultO;
Snumresults = msqlNumRows(Sresult); >
<UL>
<!
if (! Snumresults
) {
echo ("<Н2>Результатов
не найдено </h2>"); else{
$shark = msqlFetchRow(Sresult);
while USshark
> 0) {
Sid = $shark[0];
echo("<LI>");
printf("<IMG
SRC=\"graphics/shark%s.gif\" ALIGN=LEFT>", $shark[0]);
еспо("<В>Вид:</b>
$shark[1]<br>");
if ($shark[2]
== 1) { Sage = "Молодые"; }
else if ($shark[2]
== 2) { Sage = "Взрослые"; }
else if {$shark[2]
== 3) { Sage = "Старые"; }
echo("<В>Возраст:</b>
$age<br>");
еспо'("<В>Район</b>
$shark[3]<br>");
$shark = msqlFetchRow(Sresult); } }
>
</ul>
<A HREF="search.
html">Hoвый поиск </а>
</body></html>
Обратите
внимание, что код Lite и HTML могут перемежаться произвольным образом. В любом
месте статического HTML можно завершить
код Lite и вводить просто HTML. Это особенно полезно, если ваша страница
в основном статична и лишь в некоторых местах требуется динамическое содержание.
Обратите
также внимание на то место, где генерируется тег для изображения акулы с использованием
ее ID. Это полезный способ включения данных, которые неудобно хранить в базе.
Поскольку mSQL не может хранить большие двоичные поля, часто полезно хранить
картинки, другие двоичные данные или даже большие объемы текста в виде плоских
файлов, помеченных уникальными ID записей базы данных.
По самой
своей природе W3-mSQL узко специализирована для использования с СУБД mSQL. Если
вы используете MySQL или же W3-mSQL не покрывает всех ваших потребностей, то
есть другие препроцессоры HTML, предлагающие поддержку баз данных.
РНР, что
означает «PHP: Hypertext Preprocessor» (препроцессор гипертекста),
является приложением, очень близким по духу W3-mSQL. Оба приложения являются
CGI-программами, интерпретирующими HTML перед отправкой броузеру окончательной
страницы. Оба имеют встроенный язык сценариев. Более того, в обе программы тесно
интегрированы возможности работы с базами данных. Однако РНР идет дальше W3-mSQL,
предлагая совместимость с несколькими серверами баз данных, включая MySQL и
mSQL.
Язык сценариев
РНР более богат и может использоваться в большем числе приложений, чем W3-mSQL.
Короче, предпочтительнее использовать РНР, если только вы не привязаны к использованию
mSQL в качестве сервера баз данных. В последнем случае более удобной для вас
будет некоторая оптимизация, имеющаяся в W3-mSQL.
С использованием
РНР пример с базой данных по акулам может выглядеть так:
<НТМL>
<НЕАD><TITLЕ>Результат
поиска акул </title></head>
<BODY>
<Н1> Вот
акулы, удовлетворяющие условиям поиска...</ht>
<Р> <?
/* Начинаем
построение запроса. В результате типичный запрос
* может выглядеть
так:
* SELECT * FROM
SHARK WHERE SPECIES='Isurus Paucus' AND AGE=2 */
$query = "select
* from sharks where ";
if ($species
|| $age || Slocation) {
$query += "
where "; }
if ($species) { $query += "species = '$species'";
}
if ($age) {
if ($species)
{ $query += " and "; }
$query += "age
= Sage";
}
if ($location)
{
if ($species
|| $age) { Squery += " and "; } $query += "location = '$location'";
}
$result = msql("sharks",Squery);
if (result ==
-1) {
echo("Error
: $phperrmsg\n");
exit(1); }
Snumresults = msql_numrows($result);
>
<UL>
<!
if (! $numresults
); >
<Н2>Результатов не найдено </h2>
<!
else {
while-($i <
$numresults) {
$id[$i] = msql_result($result,$i,"id");
$species[$i] = msql_result($result,$i,"species");
$age[$i] = msql_result($result,$i,"age");
$loc[$i] = msql_result($result,$i,"location");
echo("<LI>");
printf("<IMG SRC=\"graphics/shark%s,gif\" ALIGN=LEFT>", $id[$i]); echo("<В>Вид:</b> $species[$i]<br>");
if ($age[$i] == 1) { $age = "Молодые"; }
else if ($age[$i] == 2) { $age = "Взрослые"; }
else if {$age[$i] == 3) { $age = "Старые"; }
echo("<B>Age:</b> $age<br>");
echo("<B>Paйoн</b> $location[$i]<br>");
}
}
}
</ul>
<A HREF="search.html">Hoый поиск </а>
</body></html>
Несколько
модулей Perl и соответствующих программ позволяют встраивать код Perl в документ
HTML. Перед отправкой окончательной страницы HTML броузеру этот код выполняется
CGI-программой.
Наиболее
очевидное преимущество таких решений перед W3-mSQL и РНР заключается в том,
что в качестве языка сценариев в HTML-файле используется обычный Perl. Будучи
простыми в изучении и схожими по стилю с С и Perl, языки сценариев Lite и РНР
все же являются уникальными патентованными языками, используемыми лишь с единственной
целью. Напротив, Perl практически вездесущ. Это стандартный язык программирования,
отлаживавшийся на протяжении многих лет и обладающий развитыми возможностями
в отношении безопасности. В пользу такого типа решений есть убедительные аргументы.
ePerl
Первым приложением,
позволившим встраивать код Perl в текст ASCII и, в частности, в документ HTML,
был ePerl. Сама программа ePerl написана на С и предназначена для использования
в качестве интерпретатора Perl общего назначения для документов ASCII. Она прекрасно
работает с HTML, но не имеет специфических для HTML или веб-возможностей, предоставляемых
некоторыми другими пакетами.
EmbPerl
Программа
EmbPerl создана позднее, чем ePerl, и более ориентирована на HTML и Web. Она
позволяет использовать дополнительные «метакоманды» - теги в стиле
HTML, обрабатываемые EmbPerl, - которые вводят в сам HTML возможности ветвления
и другие элементы программирования .
В качестве
примера встраивания кода Perl в файл HTML рассмотрим форму для вывода данных
из базы данных по акулам, приводившуюся выше. Мы будем использовать в нашем
примере EmbPerl, но поскольку используется стандартный Perl, код практически
одинаков для различных средств встраивания Perl.
<HTML>
<НЕАD><ТIТLЕ>Результаты
поиска акул</title></head>
<BODY>
<Н1> Вот
акулы, удовлетворяющие условиям поиска...</h1>
<р>
[-
use Msql;
use CGI qw(:standard);
$dbh = Msql->connect;
$dbh->selectdb("sharks");
%age = ( '0' => 'Молодые',
'1' => 'Взрослые',
'2' => 'Старые'
);
# Начинаем построение
запроса. В результате типичный запрос
# может
выглядеть так:
# SELECT * FROM
SHARK WHERE SPECIES='Isurus Paucus' AND AGE=2
$query = "select
* from sharks where ";
if (Sspecies
or Sage or $location) {
$query .= "
where ";
$query .= join("
and ", param); }
Sresult = $dbh->query($query);
if (result ==
-1) {
echo("Error
: " . Msql->errmsg . "\n");
exlt(l);
}
Snumresults
= $result->numrows;
-]
<UL>
[$if (! Snumresults ) $]
<Н2>Результатов
не найдено </h2> [SelseS]
[Swhile (%shark
= $Msql->fetchhash($result)) $]
<LI>
<IMG SRC="graphics/shark[+$shark{'id'}+].gif"
ALIGN=LEFT>
<В>Вид:</b>
[+$shark{'species'}+]<br>
<В>Возраст:</b>
[+$age{$shark{'age'}}+]<br>
<В>Район </b> [+$shark{'location'}+]<br>
[;endwhile$] [;endif] </ul>
<A HREF="search.html">Hoвый
поиск </а>
</body></html>