Версия для печати
Архив документации на OpenNet.ru /
Раздел "Perl"
(Многостраничная версия)
Cборник часто задаваемых вопросов по языку PERL и программированию для WEB
Общий план
Часть A. Перл как язык
Часть B. Перл как средство для работы с CGI
Часть C. Perl и базы данных
Часть B. Перл как средство для работы с CGI
---------------------------------------------------------------------
(5) CGI-скрипты
(Q 5.1) Что такое CGI и как с ним работать
(Q 5.2) Как заставить браузеры не кешировать выдаваемый результат?
(Q 5.3) Как перенаправить клиента на другой URL?
(Q 5.4) Как загрузить файл на сервер?
(Q 5.5) Как получить файл по URL?
(Q 5.6) ! Как использовать плюшки (cookies)?
---------------------------------------------------------------------
(6) Web серверы
(Q 6.1) Как заставить WWW сервер исполнять CGI-программы?
(Q 6.2) Мой CGI-скрипт не работает! Как установить причину?
(Q 6.2) Ошибки HTTP 500 и 403. Что это значит и что с ними делать
(Q 6.3) ! Почему $ENV{REMOTE_HOST} пуста?
(Q 6.4) ! Почему $ENV{REMOTE_USER}} пуста?
* * *
(5) CGI-скрипты
(Q 5.1) Что такое CGI и как с ним работать
(A) CGI -- Common Gateway Interface. Cтандарт интерфейса внешних программ
с http-сервером.
Как работать:
HTTP -- клиент-серверный протокол, следовательно со стороны CGI, как
серверного процесса, все взаимодействие выглядит следующим образом:
1. Получение данных от клиента
2. Обработка данных
3. Выдача ответа клиенту.
Пункты 1 и 3 я в кратце опишу здесь, а 2, надеюсь, сделате сами.
Начнем с п.3 как наиболее простого.
3. Выдача данных клиенту: Обычно клиенту выдают текст в формате HTML (ничто
не мешает Вам отправить ему и картинку/видео/etc). Для того, чтобы сервер и
клиент вас поняли, необходимо сказать, что вы выдаете, c помощью заголовка
Content-Type: mime-type/mime-subtype. Обратите внимание на регистр и
последовательность -- если вы скажите нечто типа Content_type, то сервер
вас скорее всего не поймет. (Сообщение типа "500 Internal
Server Error" будет симптомом).
Пример:
print "Content-Type: text/html\n"; # Мы выдаем текст в формате HTML. Также
# можно: text/plain -- простой текст, в
# брузере отобразится аналогично тексту,
# заключённому между тегами <pre></pre>.
# image/gif -- Картинка, формат gif
# video/mpeg -- mpeg-видео
# И целая куча других форматов, см.
# файл mime.types из apache
print "\n"; # <-- еще одна пустая строка, обозначает конец вывода наших
# заголовков. ВАЖНО!
# Теперь мы можем написать свой текст клиенту
print "
<html>
<head>
<title>Моя первая CGI программа</title>
</head>
<body>
<h1>Моя первая CGI программа</h1>
</body>
</head>
";
## Все.
1. Прием данных от клиента
Взаимодействие с клиентом обеспечивается так: Он заполняет форму своими
значениями, нажимает на кнопку "submit", броузер кодирует данные
соответствующим образом и отправляет их серверу.
Определение форм
Производится тегами <form> и </form>. Тег определения форм имеет следующие
аттрибуты
action -- скрипт на сервере, который будет запущен на сервере для
обработки данных формы.
method -- тип взаимодействия с сервером. Может иметь значения GET и
POST.
+ еще некоторые специальные, которые вы можете посмотреть в учебнике
Формы не могут быть вложенными.
Элементы ввода
Определяются тегами <input>, <textarea> и <select>
тег <input>:
<input type=checkbox> -- Элемен ввода "Опция"
<input type=hidden> -- Элемент ввода, который не виден пользователю
<input type=file> -- в Netscape Navigator позволяет загрузить файл на сервер
<input type=image> -- Изображение. Если по нему шелкнуть, это вызовет submit
формы и серверу будут выданы две переменные вида name.x и name.y, где name
-- то, что вы пропишете в name=... тега <input>
<input type=password> -- Элемент ввода Пароль. Позволяет ввести строку,
которая на экране отображается звездочками. Никаких методов защиты при
передаче на сервер не применяется
<input type=radio> -- Радиокнопки
<input type=reset> -- Кнопка сброса значений формы на начальные
<input type=submit> -- Кнопка отправки формы на сервер
<input type=text> -- строка ввода
Все теги <input> имеют аттрибут name -- Наименование элемента. Служит для
идентификации при передаче на сервер, а также другие типа value, width, etc,
название и назначение которых можно опять-таки посмотреть в настоящем
руководстве.
Тег <textarea> -- Поле многострочного ввода.
Тег <select> -- списочный выбор
Пример:
<form action=/cgi-bin/myscript.pl method=GET>
Имя: <input type=string name=name><p>
Пол: <input type=radio name=gender value=male>Мужской
<input type=radio name=gender value=female>Женский
<input type=submit><input type=reset>
</form>
Как это будет видно в моей программе?
Это определяется методом формы, GET или POST
В случае GET сервер установит переменную окружения QUERY_STRING в виде
name1=vaue1&name2=value2&..&nameN=vauleN.
В случае POST аналогичная строка будет записана на стандартный ввод. Ее
длину можно получить через переменную окружения CONTENT_LENGTH.
В обоих случаях данные будут закодированы по следующему алгоритму:
Eсли ASCII код символа больше 32 и меньше 128, то он будет выдан без
изменения.
если символ - пробел, то он заменится на "+" (плюсик, без кавычек)
все остальное преабразуется в вид %xx, где xx -- шестнадцатеричный
код сивола. Если вам повезло и у вас "Русский apache", то он
преобразует его в нормальную кодировку.
Декодирование на perl
tr/+/ /;
s/%([0-9a-fA-F]{2})/pack("c",hex($1))/ge;
(списано из CGI.pm)
На самом деле, можно не возится со всем этим, а использовать модуль CGI.pm
(Имеется в поставке Perl 5.004 и более поздних. Если у вас perl версии 4
или 1, нужно срочно взять на CPAN новую версию perl)
Самый большой и последний пример
Предположим мы делаем поисковую систему, тогда у нас должен быть HTML с
формой и программа, которая будет выполнять поиск.
---- search.html
<html>
<head>
<title>Поиск</title>
</head>
<body>
<h1>Чего искать?</h1>
<form action=/cgi-bin/search.pl method=get>
Строка для поиска: <input type=text name=string width=70><p>
Искать в <input type=checkbox name=searchin value=internet>Интернет
<input type=checkbox name=searchin value=intranet>Интранет
<input type=checkbox name=searchin value=extranet>Экстранет<p>
<input type=submit value=Давай!><input type=reset value="Нет, не надо">
</form>
</body>
</html>
---- конец search.html
Программа:
---- начало search.pl
#!/usr/bin/perl -- поменяйте, как надо
use CGI qw(:standard);
print "Content-Type: text/html\n\n"; # Не забудьте про два "\n"
$string = param("string");
@searchin = param("searchin"); # searchin это checkbox и его значения
# возвращаются списком
# Искать мы сегодня ничего не будем
print "<html>
<body>
<h1>Мы сегодня ничего не ищем</h1>
Но, если бы искали, то: <br>
Искали бы строку <b>$string</b><br>\n";
print "В <b>" . join(" ", @searchin) . "</b>\n";
print "
</body>
</html>
";
---- конец search.pl
Да, кстати, если вы собираетесь писать в файлы с помощью CGI-программ, не
забывайте про file locking.
(Q 5.2) Как заставить браузеры не кешировать выдаваемый результат?
(A)
Выдавайте заголовки в таком виде:
print "Content-Type: type/sub-type\n"; # Подставьте Ваш тип/подтип
print "Pragma: no-cache\n"; # Для HTTP/1.0 клиентов
print "Cache-Control: no-cache\n"; # Для HTTP/1.1
print "Expires: Thu Jan 1 00:00:00 1970\n\n"; # Это уже любой браузер должен
понять
(Q 5.3) Как перенаправить клиента на другой URL?
(A)
В заголовке напишите:
print "Status: 302\n";
# Или 301. Разница состоит в том, что по стандарту 301 значит "перемещён
# навсегда", а 302 -- "перемещён временно"
print "Location: ВАШ Новый URL\n";
# URL должен быть указан абсолютный
print "URI: ВАШ новый URL\n\n"; # Для http/1.0
Подробности: см. rfc1945(http/1.0), rfc2068(http/1.1)
(Q 5.4) Как загрузить файл на сервер?
(A)
В поставку CGI.pm входит пример file_upload.cgi.
Подробности CGI(3)
(Q 5.5) Как получить файл по URL?
(A)
Возьмите на CPAN библиотеку libwww-perl и смотрите lwpcook(3), там
написаны основы использования библиотеки и есть примеры.
(Q 5.6) ! Как использовать плюшки (cookies)?
(A)
Плюшки работают следующим образом: программа CGI добавляет в свой
ответ директиву Set-Cookie, а клиент (если он поддерживает плюшки), при
следующих запросах возвращает их. Сами плюшки представляют из себя пары
имя=значение.
Ситаксис Set-Cookie:
Set-Cookie: имя=значение; expires=дата; path=путь; domain=домен; secure
Сервер может установить не более 20 плюшек, размер всей плюшки не может
превышать 4Kb.
* Имя=значение единственный обязательный параметр. И имя, и значение
могут быть строками текста, не содержащими символов перевода строки,
побелов, ; и табуляции. Если необходимо их использовать, можно эти
символы закодировать при помощи стандартного url-кодирования.
* expires=дата, устанавливается дата истечения срока действия плюшки.
После этой дата плюшка клиентом не возвращается. Если дата не
установлена, то плюшка действует до завершения работы браузера.
* path=путь, обозначает путь на сервере, для которого возвращается
эта плюшка, если не указано, то только для того, который ее создал.
* domain=домен, домен, для которого возвращается эта плюшка. Может
быть доменом уровня 2 и выше, т.е. .example.ru, а не .ru. Если не
установлен, то плюшка возвращается только серверу, который выдал
плюшку.
* secure, указывает, что плющка должна возвращаться только по
защищенному соединению (SSL).
Синтаксис ответа клиента:
Cookie: имя1=значение1; имя2=значение2;....;имяn=значениеn
Программы CGI могут получить пары имя-значение через переменную
окружения HTTP_COOKIE. В модуле CGI.pm значение можно получить при
помощи метода cookie().
Пример:
1. Установка плюшки
---- начало setcookie.pl
#!/usr/bin/perl
print "Content-Type: text/html\n";
print "Set-Cookie: mycookie=some+string\n\n";
print "<html><head><title>Установка плюшки</title></head>\n";
print "<body><h1>Установка плюшки</h1>\n";
print "<a href=getcookie.pl>Щелкни здесь,</a> чтобы посмотреть, что
получилось.
print "</body></html>";
---- конец setcookie.pl
2. Получение плюшки
файл getcookie.pl
---- начало getcookie.pl
#!/usr/bin/perl
use CGI qw(:standard);
print "Content-Type: text/html\n\n";
print "<html><head><title>Получение плюшки</title></head>\n";
print "<body><h1>Плюшка</h1>\n";
print "mycookie = ", getcookie('mycookie');
print "</body></html>";
---- конец getcookie.pl
* * *
(6) Web серверы
(Q 6.1) Как заставить WWW сервер исполнять CGI-программы?
(A)
Apache для Unix/Win32 Надо поправить конфигурационные файлы (я расчитываю, что у вас default
конфиги apache)
Способ 1
srm.conf
Директива ScriptAlias
ScriptAlias /cgi-bin/ /usr/local/apache/cgi-bin/
и в файле access.conf прописать
<Directory /usr/local/apache/cgi-bin/>
Options ExecCGI
</directory>
(если приглядется, там нужно только раскоментировать опции)
Это позволит вам помещать программы в каталог
/usr/local/apache/cgi-bin/ и они будут видны по URL
http://you/cgi-bin/program_name
Способ 2
Добавить в srm.conf директиву AddHandler cgi-script .cgi
и вы сможете вызывать cgi-программу из любого каталога. Но она должна иметь
окончание .cgi и для этого каталога должно быть разрешено исполнение CGI
(Options ExecCGI в access.conf, написано выше).
Оба способа можно без проблем использовать совместно.
(Q 6.2) Мой CGI-скрипт не работает! Как установить причину?
Прежде чем читать дальше, убедитесь в том, что:
1) Вы запустили скрипт с командной строки (не через CGI!!!) и
он работает, а не говорит 'compilation stopped due to errors'
2) Скрипт не только работает, но и выдает нужный заголовок с пустой
строкой после него
3) (Для многопользовательских систем) Вы сделали тоже под пользователем,
под которым работает сервер (su -m имя_пользователя -c script в Unix)
и он столь же благополучно работает
(Q 6.2) Ошибки HTTP 500 и 403. Что это значит и что с ними делать
(A) error_log для того и служит, чтобы туда смотреть :-)
Основные причины:
Ошибка 403 "Forbidden"
Возникает, если сервер не может отдать вам содержимое по причине отсутствия
полномочий.
Проверьте:
Может ли user (для apache под Unix это обычно nobody), под которым работает,
сервер исполнять файл?
В частности, может ли сервер исполнять интерпретатор (в случае
скриптовых языков)?
Можно ли для этого каталога исполнять CGI? (Options ExecCGI для
apache)
Ошибка 500 "Internal Server Error"
Возникает в случае внутренней ошибки.
Проверьте:
Выводите ли вы строку "Content-Type:"?
Правильно ли вы ее выводите? (Content-type, Content_Type --
неправильно)
Заканчиваете ли вы хедеры пустой строкой? (Нельзя написать
print "Content-Type: text/html\n";
print "<HTML>\n";
Надо писать:
print "Content-Type: text/html\n\n"; # Два "\n"
print "<HTML>\n";)
Также, эта ошибка возникает, если CGI-программа завершилась с ненулевым
кодом возврата, что часто встречается в случае некомпилируемости вашего
скрипта perl'ом.
Совет: делайте use CGI::Carp qw(fatalsToBrowser) во время отладки, тогда вам выдадут сообщение об ошибке perl.
(Q 6.3) ! Почему $ENV{REMOTE_HOST} пуста?
(A)
apache устнавливает переменную окружения REMOTE_HOST, если ему
разрешено проводить dns запросы для определения имени. Для 1.3.x
по-умолчанию это выключено. Включается/выключается директивой
HostNameLookups, которая может принимать 3 значения: on -- проводить
запросы, off -- не запрашивать dns и double -- делать двойные запросы:
запрашивать имя хоста, а затем по имени запрашивать ip адрес, для
безопасности.
(Q 6.4) ! Почему $ENV{REMOTE_USER}} пуста?
(A)
Переменная окружения REMOTE_USER устанавливается apache в случае, если
скрипт защищен паролем. Как это сделать рассказано на
http://www.apacheweek.com/features/userauth
и http://www.apacheweek.com/features/dbmauth
Часть С. Perl и базы данных
(1) БД на плоских файлах
(Q 1.1) Я хочу какую-нибудь простейшую БД и прямо сейчас!
(Q 1.2) Можно ли как-нибудь из Perl получить доступ к dbf файлам?
(Q 1.3) А к MS access .mdb?
(Q 1.4) Зачем и как нужно запирать (lock) файлы?
---------------------------------------------------------------------
(2) Реляционные, пост-реляционные и объектно-реляционные СУБД
(Q 2.1) Как использовать DBI?
(Q 2.2) Как работать с записями кусочками: первые N записей, следующие N...?
(Q 2.2) Где взять документацию/учебник по SQL?
* * *
(1) БД на плоских файлах
(Q 1.1) Я хочу какую-нибудь простейшую БД и прямо сейчас!
(A)
Вы можете использовать простой текстовый файл с разделителями. Например, если
мы пишем нечто типа телефонной книги, то вполне вероятно предположить, что ни
в чьем имени, ни в номере телефона не встретится последовательность::, так
что именно ее и можно использовать в качестве разделителей.
Файл с данными может выглядеть так:
Иванов И.И.::888-0000::Какая-то улица, 17, кв 40
Сидоров П.И.::888-8429::Другая улица, 5, кв 21
...... и тд.
тогда программа, которая читает данные, может быть примерно такого вида:
#!/usr/bin/perl
# открываем файл
open DATA, 'data.dat' or die "Невозможно открыть data.dat: $!";
# читаем построчно из файла
while (<DATA>) {
chomp; # удаление символа конца строки
# теперь в $_ есть строка и мы ее разделяем на переменные
($name, $phone, $address) = split(/::/);
# и выведем на печать
print "Имя: $name, телефон: $phone, адрес: $address\n";
}
close DATA;
#всё
Больше проблем возникает в случее, если надо удалить или отредактировать
запись, но и их можно довольно просто и элегантно решить, если использовать
механизм редактирования на месте (inplace edit) -- при использовании операции
"ромб"(<>), можно читать из одного файла, а писать в другой:
#!/usr/bin/perl
$^I = '~'; # запускаем inplace edit
while (<>) { # Обратите внимание, что мы не открывали файл: при такой
#конструкции имя файла берется из коммандной строки
chomp;
($name, $phone, $address) = split(/::/);
if (.... некоторое условие, при котором мы оставляем наши данные ... )
{
print "$name::$phone::$address\n"; # теперь данные есть в новом файле
}
}
# конец примера
если запустить это программу как
change.pl data.dat
,то в текущем каталоге будут два файла: data.dat, с записями, которые
удовлетворили нашим условиям и data.dat~ -- предыдущая копия.
(также, во многих случаях, всю программу такого типа можно записать как
one-liner:
perl -i~ -n -e 'print if(... условие)'
)
Двоичные файлы
Для чтения двоичных файлов в Perl можно использовать функции read и unpack.
К примеру, если использовать двоичный файл для хранения телефонной книги такого
формата:
40 символов -- фамилия, И.О.
10 символов -- номер телефона,
60 cимволов -- адрес,
то строка описания формата для unpack будет выглядеть так:
$format_str = 'A40 A10 A60';
а сама программа, аналогичная первому примеру:
#!/usr/bin/perl
$format_str = 'A40 A10 A60';
open DATA, 'binary.dat' or die "$!";
while (read(DATA, $buf, 40+10+60)) { # <DATA> не покатит: такая
# конструкция будет читать до символа перевода строки, а это не то, что нужно
($name, $phone, $address) = unpack($format_str, $buf);
# Теперь в $name, $phone, $address есть данные и с ними можно делать
# все, что захочется
}
close DATA;
Чтобы вывести в файл такую запись можно использовать конструкцию типа
print FILE pack($format_str, $name, $phone, $address);
(Q 1.2) Можно ли как-нибудь из Perl получить доступ к dbf файлам?
(A)
Да, можно. На http://www.fi.muni.cz/~adelton/
есть модуль XBase, которыйпозволяет читать/писать dbf. При чтении он даже поддерживает индексы.
Кроме того, в комплект поставки также входит модуль DBD::XBase, при помощи
которого можно даже оперировать dbf на SQL.
(Q 1.3) А к MS access .mdb?
(A)
К файлам MS Access нельзя обращаться из perl напрямую, по крайней мере, в
настоящее время.
К MS Access можно обращаться по ODBC, при помощи DBD::ODBC.
(Q 1.4) Зачем и как нужно запирать (lock) файлы?
(A)
Представьте себе ситуацию когда одновременно работают несколько копий одной и
той же программы (к примеру, cgi-скрипты, обслуживающие запросы),
читающие/пишушие в один файл, тогда рано или поздно создатся ситуация при
которой один скрипт прочитал данные, произвел над ними некоторые действия и
собрался записать их назад в файл, но в это же время другой скрипт тоже
прочитал данные, тоже произвел над ними действия, но (!) он прочитал старые
данные, которые он и запишет поверх данных, выданных другим скриптом. Таким
образом, в файле остануться данные записаные одним из скриптов -- в лучшем
случае, в худшем -- структура файла будет испорчена. Чтобы этого избежать в
Unix и большинстве других ОС есть системный вызов flock(2) или
аналогичный.
Как использовать flock
К примеру, скрипт который записывает имена вызывающих хостов в файл. (На деле
такой список, конечно, можно получить из журнала регистрации web-сервера).
#!/usr/bin/perl
use Fcntl; # Импорт констант
open (HOSTS, '>>hosts.log'); # Файл открыт для добавления записи
flock(HOSTS, LOCK_EX);
# Теперь файл заблокирован: Если любой другой скрипт тоже вызовет flock на
# этом файле, его flock не вернет управление в программу, пока мы не
# разблокируем файл. Обратите внимание: flock -- декларативная функция, если
# один из скриптов ее не использует при записи, то вся ваша блокировка не
# работает.
print HOSTS $ENV{REMOTE_HOST}, "\n"; # записали строку
close HOSTS; # Файл при закрытии разблокируется автоматически
# Вывести сообщение для пользователей
print "Content-Type: text/plain\n\n";
print "Название вашего хоста записано\n";
Более подробный рассказ о flock и пример доступны на
http://w3.stonehenge.com/merlyn/WebTechniques/col04.html
Чего делать на системах, где нет flock или для блокировок файлов на сетевых
дисках?
Судя по perlfaq5(1), можно использовать модуль File::Lock с CPAN.
* * *
(2) Реляционные, пост-реляционные и объектно-реляционные СУБД
(Q 2.1) Как использовать DBI?
(A)
DBI -- это интерфейс прикладных программ к СУБД, использующим SQL в качестве
языка запросов. Cам DBI определяет только набор функций, переменных и
соглашений. Вся непосредственная работа выполняется Database Drivers (DBD) --
модулями, обеспечивающими связь с СУБД. DBI только обеспечивает стандартный
интерфейс для этих драйверов.
Полная схема архитектуры при работе DBI выглядит примерно так:
+----------------------+
| Прикладная программа |
+----------------------+
| DBI |
+----------------------+
| DBD |
+----------------------+
| СУБД |
+----------------------+
Подсоединение к СУБД
обеспечивается при помощи метода connect класса DBI:
$dbh = DBI->connect($dsn, $user, $auth, {options});
$dbh Это об'ект, при помощи его методов осуществляются взаимодействия с
СУБД.
$dsn Строка, определяющая к какой базе данных подсоединятся и другие
параметры. Зависит от DBD. На сегодняшний момент стандарта нет, но
рекомендовано использовать стиль ODBC:
'dbi:<имя DBD>:databasename=<название БД>;host=<Имя хоста>;port=<порт>';
$user Имя пользователя.
$auth Нечто, авторизующее пользователя. Обычно пароль.
options Параметры DBI, передаются через анонимный хеш. В настоящее время
понимаются три параметра:
* RaiseError, если установлен, то при любой ошибке DBI убивает
программу
* PrintError, если установлен, то при ошибке DBI вызывает warn
* AutoCommit -- определяет порядок работы с транзакциями.
Например:
$dbh = DBI->connect('dbi:Pg:dbname=apavel', 'apavel', 'SomeSecret',
{RaiseError=>1, AutoCommit=>0});
Означает: Подсоедение к СУБД PostgreSQL, к базе данных apavel, с именем
пользователя apavel и паролем. Все ошибки будут вызывать die, что удобно при
отладке, а все изменения будут внесены только при подтверждении (commit)
транзакций.
Отсоединение обеспечивается при помощи метода disconnect: $dbh->disconnect();
Механизм курсоров и подготовки запросов
При работе с базами данных при помощи DBI используюся курсоры -- специальные
об'екты, обеспечивающие последовательный доступ к результатам запросов. (В
простейших случаях можно обойтись и без них, я расскажу об этом дальше.)
Пример таблицы, используемой в дальнейшем:
create table foo (
bar varchar(50),
baz int
)
Получение данных
$cursor = $dbh->prepare('select bar, baz from foo');
# теперь $cursor -- курсор, и его необходимо исполнить
$cursor->execute;
# После исполнения запроса, результат можно получить из курсора при помощи
# метода fetchrow_array
while (($bar, $baz) = $cursor->fetchrow_array) {
print "bar is: $bar, baz: $baz\n";
}
Placeholders
Очень часто бывает надо подготовить какой-либо запрос, а потом использовать
его с разными значениями данных. DBI предлагает для механизм placeholders:
В запросе на месте таких данных указываются вопросительные знаки, а сами
значения передаются в метод execute() курсора. Например:
$cursor = $dbh->prepare('select bar from foo where baz=?');
$cursor->execute($baz);
Особенно удобно это в случае вставки данных:
$cursor = $dbh->prepare('insert into foo(bar, baz) values(?, ?)');
while ( ... ) {
$cursor->execute($bar, $baz);
}
Таким образом, СУБД разбирает запрос толлько один раз, а затем просто
исполняет его, что экономит время. (Естественно, это верно только для DBMS с
раздельными parse и execute, сейчас ни MySQL, ни PostgreSQL такое не
поддерживают, поэтому их реализации DBD просто сохраняют запрос переданный
$dbh->prepare() и затем подставляют в него данные при каждом $sth->execute().)
Работа без курсоров
DBI предоставляет несколько методов для такого рода работы:
Методы для запросов:
* selectrow_array Возвращает одну строку запроса в виде
массива,
* selectall_arrayref Возвращает весь ответ сервера в виде
массива ссылок на массивы.
Методы для выражений, не возвращающих значений
* do исполняет запрос
Пример:
#получить значение bar при baz=3
($bar) = $dbh->selectrow_array('select bar from foo where baz=3');
# установить baz в некоторое значение при bar='somestring'
$dbh->do("update set baz=1 where bar='somestring'");
(Q 2.2) Как работать с записями кусочками: первые N записей, следующие N...?
Можно несколькими способами:
1. Самый грубый и не эстетичный -- Просто прокручивая курсор:
$c = $dbh->prepare('select baz, bar from foo');
$c->execute;
# если нужна последовательность с 26 по 50
for ($k = 0; $k < 26; $k++) {
$c->fetchrow_array;
}
# теперь можно вывести данные
print "<table border=1><tr><th>bar</th><th>baz</th></tr>\n";
while (($bar, $baz) = $c->fetchtrow_array) {
print "<tr><td>$bar</td><td>$baz</td></tr>\n";
}
$c->finish; # Закрыть курсор
print "</table>";
2. Используя курсоры СУБД
# Показан ситаксис PostgeSQL
$dbh->do('declare mycursor cursor for select bar, baz from foo');
$dbh->do('move 25');
# И теперь будем получать данные
$c = $dbh->prepare('fetch forward 25 in mycursor');
while (($bar, $baz) = $c->fetchrow_array) {
print ....;
}
$c->finish;
$dbh->do('close mycursor');
3. Для MySQL, авторы которого не в состоянии реализовать курсоры, можно
использовать директиву LIMIT
$c = $dbh->prepare('select bar, baz from foo limit 26,25');
while (($bar, $baz) = $c->fetchrow_array) {
print ....;
}
$c->finish;
(Q 2.2) Где взять документацию/учебник по SQL?
(A)
* В книжных магазинах сейчас есть неплохой набор книг по SQL. (От рекоммендаций
воздержусь -- ни одну из них я не читал)
* На MCP personal bookshelf ( http://pbs.mcp.com
) есть книга
"Teach yourself SQL in 21 days" -- весьма рекомендую, очень хорошая книга.
* На citforum (http://www.citforum.ru) были какие-то руководства
======================================================================
ИНФОРМАЦИЯ для тех, кто хочет добавить ответы!
Присылайте их координатору на apv@i-connect.ru
Присылайте ответ с указанием секции, но без номера (у меня нумерация автоматическая) в
таком формате:
----------------------------------------------
faq_Q(Что такое хорошо, а что такое плохо?)
faq_A Давно я не читал стихотворения Маршака,
так что наизусть не помню.
-----------------------------------------------
Слова faq_Q и faq_A будут автоматически заменены на
нужные номера. А аргумент faq_Q еще и вставлен в
оглавление. Кто хочет узнать, как это делается, см.
инфо про GNU m4 в самом конце.
---------------------------------------------------------------------
Timestamps, нумерция глав и вопросов, а также оглавление в этом тексте
сгенерированы автоматически с помощью макропроцессора GNU m4.
( ftp://ftp.nc.ras.ru/pub/gnu/m4-1.4.tar.gz
) GNU m4 рулит!!
А. Перл как язык
---------------------------------------------------------------------
(1) Где взять перл и все с ним связанное
(Q 1.1) Где можно взять перл?
(Q 1.2) Где можно перл под винды (OS/2, Mac, PDP, amiga) слить?
(Q 1.3) Где можно скачать перловскую библиотеку для работы с WWW?
(Q 1.4) C www.cpan.org слишком долго качается, нет ли где поближе?
(Q 1.5) Я скачал модуль Lib::Module. Как его установить?
(Q 1.6) Как автоматизировать процесс установки библиотек и модулей?
(Q 1.7) У меня нет root-привилегий. Можно ли использовать модуль
CPAN для установки модулей в этом случае?
---------------------------------------------------------------------
(2) Где взять документацию по перлу
(Q 2.1) Какие есть книжки про Перл?
(Q 2.2) Где взять стандартную документацию про такое-то свойство перла?
(Q 2.3) Я под виндами, man у меня нет, где брать стандартную
документацию?
(Q 2.4) Где взять описание модуля Lib::Module?
(Q 2.5) Есть ли подробный большой FAQ по перлу?
(Q 2.6) Я крутой разработчик, где лежит описание того, как сделать
perldoc/manpage к своей библиотеке?
(Q 2.7) А есть ли где в интернете хорошие доки по перлу?
(Q 2.8) А где можно найти русскую доку по перлу?
---------------------------------------------------------------------
(3) Как сделать на перле то-то (основные возможности языка)
(Q 3.1) Как пользоваться функцией pack (getpwuid, dmbopen)?
(Q 3.2) Как узнать размер файла (дату создания, атрибуты, разрешения на
доступ)?
(Q 3.3) Как отправить почту из скрипта на Perl?
(Q 3.4) Как отправить почту с вложениями (attachments)?
(Q 3.5) ! Как определить правильность адреса электронной почты Internet?
(Q 3.6) Как написать модуль?
(Q 3.7) ! Как получить доступ к n-му сиволу строки?
* * *
(1) Где взять перл и все с ним связанное
(Q 1.1) Где можно взять перл?
(A) На CPAN == Comprehensive Perl Archive Network. Homepage CPAN -- http://www.cpan.org/
-- там берут все, связанное с перлом. Собственно
исходники новейшей версии перла берут из файла
http://www.perl.com/CPAN/src/latest.tar.gz
(на самом деле с www.perl.com
стоит редирект на ближайший, по мнению www.perl.com, mirror).
(Q 1.2) Где можно перл под винды (OS/2, Mac, PDP, amiga) слить?
(A) Там же, где и под UNIX, то есть на CPAN, только не в src/, а в
ports/. Например, порты перла для платформы win32 лежат в
http://www.perl.com/CPAN/ports/win32/. Там лежат два порта:
стандартный (GURUSAMY-порт) и порт фирмы ActiveState (обычно устаревшие
версии перла).
Gurusamy (он же Standard) содержит исходники Perl 5.005, бинарный дистрибутив
Perl 5.004 и ряд библиотек для него.
perl5.00402-bindist04-bc.zip
perl5.00402-bindist04-bc.tar.gz
A popular binary distribution of Perl for the Win32 platform...
perl5.005_52.patch.gz
perl5.005_52.tar.gz
Latest development release of Perl. This is only for developers and
others who like to sit on bleeding edges (pun irrelevant)...
Каталог ActiveState на CPAN уже ничего не содержит, кроме рекомендации искать
их порт на www.activestate.com
ActivePerl основан на 5.005.
из README для Active Perl: The ActivePerl package contains all you'll need to get Perl up and running --
even with a Web server!
ActivePerl includes:
- Perl for Win32 - binary of core Perl distribution.
- Perl for ISAPI - IIS plug-in that makes Perl CGI lightning fast.
- PerlScript - ActiveX scripting engine, like JavaScript or VBScript with a
Perl brain.
- Perl Package Manager - Perl extension installer and manager.
Perl на Apple Macintosh посвящена страница http://www.iis.ee.ethz.ch/~neeri/macintosh.html
Для Netware Perl дают на /CPAN/ports/netware. Кроме того, perl входит в
поставку Netware 5.
Для мейнфреймов IBM System/390 perl 5.005 компилируется прямо из стандартной
unix поставки.
Для IBM AS/400 Perl можно взять опять-таки на CPAN в каталоге ports.
Для pdp-11 есть perl1.010, но url уже никто не помнит.
(Q 1.3) Где можно скачать перловскую библиотеку для работы с WWW?
(A) Там же, где и все, относящееся к перлу -- на CPAN. Полный
список всех модулей и библиотек -- http://www.cpan.org/CPAN.html
(Q 1.4) C www.cpan.org слишком долго качается, нет ли где поближе?
(A) Есть. Полный список зеркал находится в ftp://ftp.nluug.nl/pub/languages/perl/CPAN/MIRRORED.BY,
там можно найти funet или что там поближе, или даже российские зеркала, например
ftp://ftp.sai.msu.su/pub/lang/perl/CPAN/
(иногда в дауне).
(Q 1.5) Я скачал модуль Lib::Module. Как его установить?
(A) Обычно модуль приходит в формате tar+gzip, типа module-0.01.tar.gz.
Вам необходимо его развернуть:
gzip -dc module-0.01.tar.gz | tar xf - и перейти в образовавшуюся директорию, например module-0.01:
cd module-0.01
Обычно там находятся несколько файлов. Для вас будут важными
следующие:
README - что это за модуль
INSTALL - как его поставить
Makefile.PL - перловый скрипт для генерации Makefile
Обычно инсталляция происходит следующим образом:
perl Makefile.PL - генерация Makefile
make all - сборка модуля
make test - тестирование модуля
make install - инсталляция модуля
Необходимо внимательно смотреть, не возникли ли какие ошибки во время
первых трех команд. Внимание: вы должны иметь административные
привелегии для инсталлирование модуля в системе (обычно как root).
Но, если вы их не имеете, то можете инсталлировать модуль у себя.
Для этого вам необходимо выбрать, где это будет делаться. Для примера,
в $HOME/lib/perl5. Необходимо создать эти директории, если их нет:
mkdir ~/lib
mkdir ~/lib/perl5
Затем, при генерации Makefile для модуля, вы должны указать, где вы
хотите инсталлировать модуль:
perl Makefile prefix=$HOME
Все остальные шаги без изменений. В результате вы получите
альтернативное место, где у вас будут находиться модули.
Например, у меня это выглядит так:
artur@disco:~ (681) ls -alFg ~/lib/perl5/
total 704
drwxr-sr-x 8 artur staff 512 Oct 06 15:53 ./
drwxr-sr-x 9 artur staff 1024 Oct 08 10:50 ../
drwxr-sr-x 4 artur staff 512 Mar 31 1998 aix/
drwxr-sr-x 2 artur staff 512 Aug 06 13:40 CPAN/
-r--r--r-- 1 artur staff 126951 Jul 24 19:37 CPAN.pm
drwxr-sr-x 3 artur staff 512 Mar 31 1998 man/
drwxr-sr-x 31 artur staff 1024 Sep 09 15:41 site_perl/
Для того, чтобы их использовать, есть несколько путей:
1. указывать при запуске perl в командной строке:
perl -I$HOME/lib/perl5 -I$HOME/lib/perl5/site_perl script.pl
2. завести переменную шелла PERL5LIB:
для sh (bash,zsh,ksh)
PERL5LIB=$HOME/lib/perl5:$HOME/lib/perl5/site_perl
export PERL5LIB
для csh (tcsh)
setenv PERL5LIB $HOME/lib/perl5:$HOME/lib/perl5/site_perl
3. указывать в начале скриптов дополнительные библиотеки:
use lib "/home/you/lib/perl5";
use lib "/home/you/lib/perl5/site_perl";
Данный случай подходит к CGI-скриптам, которые не наследуют ваших
переменных окружения.
(Q 1.6) Как автоматизировать процесс установки библиотек и модулей?
(A) Скачивание и установка вручную -- достаточно сложное занятие,
требующее постоянного вмешательства с вашей стороны.
Можно простым способом: сделать su (желательно), набрать
perl -MCPAN -e shell. Если это первый запуск модуля CPAN, вам задатут
серию вопросов на тему URL вашего любимого зеркала CPAN. После этого
все просто: если вы знаете название модуля или библиотеки, то
набираете, скажем, install Net::NNTP. Тогда этот модуль (для работы с
NNTP) сам ищется на CPAN, сам скачивается, компилируется,
устанавливается. Все, поставили, можно выходить и использовать вновь
установленный модуль. Если название точно не известно, то набираем
там же help и испльзуем различные команды поиска типа i NNTP.
(Q 1.7) У меня нет root-привилегий. Можно ли использовать модуль
CPAN для установки модулей в этом случае?
(A) При использовании CPAN-модуля вам необходимо сконфигурировать его
таким образом, чтобы он сам инсталлировал модули туда, куда вы
укажете. Для этого вам необходимо подредактировать файл
~/.cpan/CPAN/MyConfig.pm: указать в строке 'makepl_arg' => q[prefix=/home/you],
и теперь всегда при автоматической инсталляции модули будут ставится к
вам в $HOME/lib/perl5
Более подробно обо всем этом можно прочитать в документации к
ExtUtils::MakeMaker.
* * *
(2) Где взять документацию по перлу
(Q 2.1) Какие есть книжки про Перл?
(A) Две классические книги по перлу, первая имеется в русском переводе и
продается в магазинах:
Рандал Шварц, Том Кристиансен.
Изучаем перл (aka Llama book)
Лэрри Уолл, Том Кристиансен, Рандал Шварц.
Programming Perl (aka Camel book, на русском, кажется, еще нет)
Llama book - учебник для начинающих,
Camel book - справочное руководство.
(Q 2.2) Где взять стандартную документацию про такое-то свойство перла?
(A) Перл приходит с полным набором документации и набором программ
для переведения в разные форматы. Обычно для подробного ознакомления с
некоторой особенностью перла пишут "perldoc perlсвойство" или "man
perlсвойство". Базовый набор "свойств" таков:
Основы perldata, perlvar, perlsyn, perlop, perlsub
Запуск perlrun, perldebug
Функции perlfunc
Objects perlref, perlmod, perlobj, perltie
Data Structures perlref, perllol, perldsc
Modules perlmod, perlmodlib, perlsub
Regexps perlre, perlfunc, perlop, perllocale
Moving to perl5 perltrap, perl
Linking w/C perlxstut, perlxs, perlcall, perlguts, perlembed
Various http://www.perl.com/CPAN/doc/FMTEYEWTK/index.html (not a man-page but still useful)
perl О перле вообще
perldelta Что нового в последней версии перла
perlfaq FAQ
perltoc Подробное оглавление ко всей документации
perldata Типы данных
perlsyn Синтаксис языка
perlop Арифметические, логические, строковые
операции и их приоритет
perlre Регулярные выражения (обработка текста и поиск)
perlrun Опции командной строки
perlfunc Встроенные функции
perlvar Специальные переменные
perlsub Как писать свои функции (процедуры)
perlmod Устройство и принцип работы модулей
perlmodlib Модули: создание собственных библиотек
perlmodinstall Поиск и установка модулей и библиотек на CPAN
perlform "Форматы", или шаблоны для выводимых данных
perllocale Поддержка интернационализации
perlref Ccылки и указатели на данные
perldsc Введение в структурные типы данных
perllol Структуры данных: массивы и списки
perltoot Введение в объектно-ориентированное
программирование
perlobj Объекты в перле
perltie Связь объектов с обыкновенными переменными
perlbot Perl OO tricks and examples
perlipc Связь между процессами: pipes, sockets,
сигналы и др.
perldebug Отладка программ
perldiag Сообщения об ошибках
perlsec Вопросы безопасности
F
perltrap Возможные грабли и ловушки
perlport Как писать портабельные программы
perlstyle Стиль программирования на перле
perlpod Формат стандартной документации и документация,
встраиваемая в исходные тексты программ
perlbook О книгах про перл
--- (для совсем крутых) ---
perlembed Способы внедрения перл-программ в программы на C/C++
perlapio Собственный API, использумый в исходниках перла
perlxs XS -- программирование перловских библиотек,
используемых вместе с библиотеками на C
perlxstut Учебник по XS
perlguts Внутренние функции перла для разработчиков
perlcall Соглашения о вызове перловских функций из C
perlhist История и полный список всех версий перла
(Q 2.3) Я под виндами, man у меня нет, где брать стандартную
документацию?
(A) Перл для win32 поставляется с программой perldoc (пользоваться:
"perldoc perlfunc" и т. д.) а также с документациией в HTML: если
хочешь perldoc perlfunc, ищи perlfunc.html.
(Q 2.4) Где взять описание модуля Lib::Module?
(A) Формат стандартной документации по перлу (pod) обладает
возможностью встраивания прямо в тексты программ, а программа perldoc
-- возможностью извлечения этой документации. Поэтому, чтобы получить
документацию по модулю Math::Trig, просто наберите perldoc Math::Trig
-- perldoc найдет этот модуль и покажет документацию из него. Если
модуль не является частью какой-то библиотеки, а существует сам по
себе, например, CGI.pm тогда просто perldoc CGI.pm или даже perldoc
CGI. NB: программа perldoc не очень расторопна, поэтому при установке
перла под UNIX производится создание manpages для всех модулей, так
что man CGI или man Math::Trig покажет быстрее, чем perldoc.
(Q 2.5) Есть ли подробный большой FAQ по перлу?
(A) Да, он тоже входит в набор стандартной документации. Отправная
точка -- perldoc perlfaq, это оглавление, из которого можно узнать,
что FAQ состоит из девяти больших частей.
(Q 2.6) Я крутой разработчик, где лежит описание того, как сделать
perldoc/manpage к своей библиотеке?
(A) Про это говорят в perldoc perlpod, в man pod2man.
(Q 2.7) А есть ли где в интернете хорошие доки по перлу?
(A) Да. На мой взгляд, серия статей Рандала Шварца для Unix Review
Perl Columns -- лучшее введение в перл, и намного интереснее и
полезнее книг Llama и Camel. Почитать их можно на
http://w3.stonehenge.com:80/merlyn/UnixReview/
Почему я считаю это лучшим введением в перл? Потому что это отдельные
небольшие статьи, каждая из которых иллюстрирует конкретные
возможности перла на примере написания программы для достаточно
простой задачи. Все же статьи охватывают практически весь спектр
возможностей перла -- от написания скрипта в одну строку, который
может поменять Иванов на Сидоров во всех файлах в дереве деректорий,
до основ объектно-ориентированного программирования и принципов
создания собственных модулей и библиотек.
(Q 2.8) А где можно найти русскую доку по перлу?
(A) Если нет возможности купить в магазине, то есть кое-что и в
Интернете: книга маслова "Введение в перл", например.
http://citforum.ru/koi/internet/perl_tut/
Есть и другие, особо хороших не видел.
* * *
(3) Как сделать на перле то-то (основные возможности языка)
(Q 3.1) Как пользоваться функцией pack (getpwuid, dmbopen)?
(A) man perlfunc или "perldoc -f имя_функции | pod2text"
Пара примеров для unpack:
Определение типа изображения и его размеров:
sub get_image_spec {
# Возвращает ($Тип_изображения, $ширина, $высота)
my $buf = $_[0];
my ($type, $width, $height);
if (unpack("n", $buf) == 0xffd8) {
return ('jpeg', 0, 0); # Про jpeg я пока не знаю как
# определить его размеры
} elsif (unpack("A4", $buf) eq "GIF8") {
my ($type, $width, $height) = unpack("A6 v v", $buf);
return ('gif', $width, $height);
}
}
read(STDIN, $buf, 120);
print join (", ", get_image_spec($buf));
(Q 3.2) Как узнать размер файла (дату создания, атрибуты, разрешения на
доступ)?
(A) С помощью так называемых файловых тестов, которые имеют вид
(-тест "имя файла"), например:
(-s "file.txt") размер файла
-e существует ли файл
-w доступен ли на запись
-M количество дней со дня модификации
-t является ли терминалом
(Q 3.3) Как отправить почту из скрипта на Perl?
(A)
Способ для Unix oт Alex Efros
----
open MAIL, '|/path/to/your/sendmail -t'; # Pipe к sendmail
print MAIL "From: mailrobot@my.host\n",
"To: webmaster@my.host\n",
"Subject: Wow! I got some mail for you!!!\n\n",
$message;
close MAIL;
-----
Подробности: man sendmail, http://www.sendmail.org
У меня не Unix! Что делать?
Вероятно, Вам поможет модуль Net::SMTP
(Q 3.4) Как отправить почту с вложениями (attachments)?
(A)
Возьмите на CPAN модуль MIME::Tools и прочтите от него README.
(MIME-tools.xxxxx.tar.gz)
(Q 3.5) ! Как определить правильность адреса электронной почты Internet?
(A)
Гарантированно -- никак. Вы можете проверить адрес на правильность
синтаксиса при помощи регулярного выражения, те, чтобы адрес соответствовал
некоторому образцу (В rfc823 приведены BNF'ы правильных адресов, также
доступно монстрообразное регулярное выражение для проверки e-mail от автора
книги "Mastering Regular Expressions" где-то XXX) , Вы также можете проверить
существование этого домена. И все. Если Вам нужен гарантированно правильный
e-mail для web-сайта, Вы можете воспользоваться методом от Алексея Тутубалина:
требовать пароль для доступа к информации, а сам пароль высылать по
электронной почте. Тогда человек должен будет указать свой e-mail, конечно же,
если ему интересна эта информация с вашего сайта.
(Q 3.6) Как написать модуль?
(A)
Простейший случай:
Сам модуль представляет из себя файл с именем MyModule.pm следуещего
содержания:
package MyModule;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(идентификаторы для экспорта: подпрограммы, имена переменных и
пр.);
# Теперь после того, как вы напишите use MyModule в своей программе, у вас все
# упомянутые здесь идентификаторы станут видны. Этот метод не рекомендуется,
# так как вы "засоряете" именное пространство программы.
# И/или
@EXPORT_OK = qw(идентификаторы для экспорта: подпрограммы, имена переменных и
пр.);
# Идентификаторы, прописанные здесь будут видны в Вашей пргорамме как
# MyModule::Идентификатор (подпрограммы) или $MyModule::Идетификатор
# (переменные)
# Или, Вы можете написать use MyModule qw(Ид1 Ид2 $Ид3); и все будет как в
# первом случае. Это рекомендуемый вариант.
... ваши подпрограммы и пр ....
1; # Обязательно
# конец МойМодуль
Программа, его используящая:
use MyModule qw(...);
# Ну и далеее
Подробности смотрите в perlmod(1), Exporter(3pm), Camel Book
(Q 3.7) ! Как получить доступ к n-му сиволу строки?
(A)
Надо использовать функцию substr. Например, получить 15й символ из
строки $string:
$char = ;
Установить 15й символ строки $string:
= 'A';
Можно даже использовать болле чем односимвольные последовательности:
$ss = ;
= 'Хо-Хо';