русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

PHP. Синтаксис языка. Доступ к базам данных. Технологии применения. Примеры программ


Дата добавления: 2013-12-23; просмотров: 3032; Нарушение авторских прав


Quot; - -//- по центру. "####.###" - формат числа с точкой. "@*" - многострочная строка. Данные выводятся в колонку. Размер поля равен количеству указанных символов. Символ '^' в начале поля имеет специальное значение. Так: · "^####" - пусто если переменная не определена. для строчного скаляра: · "^<<<<<" - Выводится сколько возможно символов, а значение переменной меняется на остаток, вывод которого можно продолжить на следующих строках, которые могут иметь свои поля. Специальные переменные: · $~ - построчный формат содержимого. · $^ - формат заголовка листа. · $% - номер листа. · $= - строк в листе. Если вы хотите использовать одни форматы для разных файлов, то самый простой путь: use FileHandle; # Указать в начале программы format_name файл имя_формата; # Формат содержимого листа. format_top_name файл имя_формата; # Формат заголовка листа. write(файл); # вывод данных. Здесь 'файл' имеется в виду указатель файла, полученный командой open(); Если вам нужно в теле листа выводить разного рода форматы (например, заголовки групп или отбивку листа), то применяйте format_name. CGI-программирование. Использование CGI.pm.Итак, как coздается CGI сценарий? Теоретически это очень просто - программа CGI, как и любая другая программа на Perl, выполняет обычные команды Perl, когда она вызывается броузером (то есть когда броузеру в качестве URL задается CGI-сценарий). Все, что вы направляете в стандартный вывод, передается броузеру. Так, если CGI-сценарий выполняет команду print "Hello!", этот текст будет возвращен броузеру, и на странице появится надпись "Hello'" Но это рудиментарный способ. Требуется ли прочитать данные, введенные пользователем с помощью элементов управления, расположенных на странице? Или вы захотите создать эти элементы управления из сценария? Чтобы сделать все это и многое другое, используется прилагающийся к Perl пакет CGI.pm. (Далее мы рассмотрим другой популярный пакет — cgi-lib.pl.) С одной стороны, это стандартный способ работы с CGI средствами Perl, с другой — отличное введение в CGI.pm. Итак, интерпретатор Perl содержит, среди других модулей, стандартный модуль CGI.pm. По­этому если у вас установлен Perl, то, скорее всего, есть и CGI.pm. Начиная с пятой версии Perl CGI.pm стал объектно-ориентированным, хотя упрощенный функционально-ориентиро­ванный интерфейс все еще существует. В наших примерах мы будем использовать объектно-ориентированное программирование. Создавая с помощью CGI.pm объекты CGI, мы будем вызывать различные методы этого объекта. Существуют методы, соответствующие практи­чески всем основным тегам HTML, и при их вызове создается нужный тег с указанными ат­рибутами. Все они могут получать именованные параметры (за исключением методов, тре­бующих один аргумент), иными словами, требуется указать не только значение атрибута HTML, но и его имя. В следующем примере объект CGI создает Web-страницу посредством встроенных методов. Обратите внимание на именованные параметры метода textarea, за­дающие имя области редактирования текста ('textarea'), значение по умолчанию и размеры: Листинг 5.6.Создание Web-страницы. #!/usr/local/bin/perl use CGI; $co = new CGI; print $co->header, $co->start_html(-title=>'CGI Example'), $co->center($co->h1('Welcome to CGI!')), $co->textarea ( -name => 'textarea', -default => 'No opinion', -rows => 10, -columns => 60 ), $co->end_html; Если возможности объектно-ориентированного интерфейса не требуются, пакет CGI.pm также поддерживает простой функционально-ориентированный интерфейс. Мы рассмотрим пример применения функционально-ориентированного интерфейса CGI.pm ниже. Создание и использование элементов управления HTML.Изучать программирование лучше всего на примерах. Потому ниже приводятся два CGI-сценария: один создает Web-страницу с элементами управления — полями ввода текста, переключателями, кнопками, включая Submit, а второй читает данные, введенные пользователем на этой странице. Оба сценария — вариации с небольшими дополнениями на тему оператора print, который собственно и создает страницу. Первый сценарий хранится в файле cgil.pl, и в справочных целях полностью приводится в листинге 6-7. Когда пользователь открывает сценарий в броузере (переходя по его адресу — например, http://www.yourserver.com/user/cgi/cgil.pl), сценарий возвращает страницу с элементами управления HTML и текстом. В данном случае это страница анкеты. Страница содержит приветствие и сообщение о том, что посетители, не желающие заполнять анкету, могут перейти по ссылке на сервер CPAN (Comprehensive Perl Archive Network — всеобъемлющий архив, посвященный языку Perl). Затем вы увидите запрос имени пользователя с текстовым полем и вопрос о его мнении с областью редактирования текста (многострочное текстовое поле). Просматривая анкету дальше, вы увидите еще несколько элементов управления — кнопки с зависимой и независимой фиксацией, списки, а также кнопка подтверждения и очистки анкеты. Позже мы рассмотрим, как создать все эти элементы управления на примере предложенных сценариев. Когда пользователь нажимает на кнопку Submit, расположенную в конце анкеты, броузер собирает данные, введенные на странице, и передает их другому CGI-сценарию, cgi2.pl. В справочных целях он приведен в листинге 6-8. В общем, нет никакой необходимости создавать CGI-сценарий, генерирующий анкету, — можно просто написать страницу HTML, которая будет вызывать cgi2.pl по нажатию пользователем кнопки Submit. Подход, требующий генерации кода, выбран лишь затем, чтобы продемонстрировать обе стороны процесса — как создать элементы управления HTML из CGI-сценария и как прочесть данные из этих элементов управления. Листинг 5.7. cgi1.pl #!/usr/local/bin/perl use CGI; $co = new CGI; $labels{'1'} = 'Sunday'; $labels{'2'} = 'Monday'; $labels{'3'} = 'Tuesday'; $labels{'4'} ='Wednesday'; $labels{'5'} = 'Thursday'; $labels{'6'} = 'Friday'; $labels{'7'} = 'Saturday'; print $co->header(-charset=>'windows-1251', -lang=>'ru'), $co->start_html( -title => 'CGI Example', -author => 'Andrew', -meta => {'keywords' => 'CGI Perl'}, -BGCOLOR => 'white', -LINK => 'red' ), $co->center($co->h1('Here is the Survey!')), $co->h2('Please fill out survey...'), "Reasons for filling out our survey:", $co->p, $co->ul( $co->li('Fame'), $co->li('Fortune'), $co->li('Fun' ) ), "If you would rather not fill out our survey, ", "you might be interested in ", $co->a({href=>"http://www.cpan.org/"},"CPAN"),".", $co->hr, $co->startform( -method=>'POST', -action=>'http://inna/scripts/web/l6/e8.pl'), "Please enter your name: ", $co->textfield('text'), $co->p, "Please enter your opinion: ", $co->p, $co->textarea( -name => 'textarea', -default => 'No opinion', -rows => 10, -columns => 60 ), $ co->p, "Please indicate what products you use: ", $co->p, $co->checkbox_group( -name => 'checkboxes', -values => ['Shampoo','Toophpaste','Bread', 'Cruise missiles' ], -defaults => ['Bread','Cruise missiles'] ), $co->p, "Please indicate your income level: ", $co->p, $co->scrolling_list('list', ['Highest','High','Medium','Low' ], 'High'), $co->p, "Please indicate your day of a week: ", $co->p, $co->radio_group( -name => 'radios', -values =>['1','2','3', '4' ,'5' ,'6','7'], -default => '1', -labels => \%labels), $co->p, "Thank you for filling out our survey. Please indicate ", "How much unsolicited mail you like to get: ", $co->popup_menu( -name => 'popupmenu', -values => ['Very much','A lot','Not so much','None'] ), $co->p, $co->hidden(-name=>'hiddendata', -default=>'Rosebud'), $co->center( $co->submit, $co->reset, ), $co->hr, $co->endform,$co->end_html; Листинг 5.8.cgi2.pl #!/usr/local/bin/perl use CGI; $co = new CGI; print $co->header(-charset=>'windows-1251', -lang=>'ru'), $co->start_html( -title => 'CGI Example', -author => 'Andrew', -meta => {'keywords'=>'CGI Perl'}, -BGCOLOR => 'white', -LINK => 'red' ), $co->center($co->h1('Thanks for filling out our survey.')), $co->h3('Here is your responses...'), $co->hr; if ($co->param()) { print "Your name is: ", $co->em($co->param('text')), ".", $co->p, "Your opinions are: ", $co->em($co->param('textarea')), ".",$co->p, "You use these products: " , $co->em(join(", ", $co->param('checkboxes'))), ".", $co->p, "Your income level is:", $co->em($co->param('list')),".", $co->p, "Today is day ", $co->em($co->param('radios')), "</em> of the week.", $co->p, "How much unsolicited mail you like: ", $co->em($co->param('popupmenu')),".", $co->p, "The hidden data is ", $co->em(join(", ", $co->param('hiddendata')))} print $co->hr; print $co->end_html; Начинаем HTML-документ.Начало работы над документом HTML строится следующим образом. Вначале вы создаете CGI объект, затем с помощью метода headerэтого объекта — HTTP-заголовок (в данном примере создается простая шапка документа, но допустимы сколь угодно сложные шапки с любыми атрибутами, например, -charset=>'windows-1251'). Заголовок можно сформировать и самостоятельно, напимер, командой print. Метод start_htmlначинает сам документ HTML. Этот метод создает секцию <HEAD>,а также позволяет указать некоторые атрибуты <BODY>, как-то: цвет для изображения фона и ссылок. Ниже приведен фрагмент кода cgil.pl, открывающий страницу. Обратите внимание: чтобы результаты работы методов header и start_htmlпопали на страницу, необходимо использовать функцию print: #! /usr/local/bin/perl $со = new CGI, print $co->header, $co->start_html( -title => 'CGI Example', -author => 'Andrew', -meta => {'keywords'=>'CGI Perl'}, -BGCOLOR => 'white', -LINK => 'red' ) Создаем заголовки HTML.После создания шапки CGI-методы типа h1, h2, h3 и др. помогут создать заголовки, соответствующие тегам <Н1>, <Н2>, <НЗ>и т. д. Ниже приведен фраг­мент кода, генерирующий заголовки <Н1> и <Н2>в начале Web-страницы с анкетой. В данном случае это простое приглашение пользователю. #!/usr/local/bin/perl $со = new CGI; print $co->h1('Here is the Survey!,'), $co->h2('Please fill out survey...') Центрируем элементы.Чтобы центрировать текст с помощью тегов <CENTER>,используется CGI-метод center.В следующем примере центрируется заголовок, созданный в предыдущем примере: #'/usr/local/bin/perl $со = new CGI; print $co->center($co->h1('Here is the Survey!')), $co->h2('Please fill out survey...'), Создаем маркированный список.CGI-методы ul и li создают несортированный маркированный список (теги <UL> и <LI>соответственно). Ниже приведен фрагмент кода, представляющий пользователю несколько аргументов, побуждающих заполнить анкету: #!/usr/local/bin/perl $со = new CGI; print "Reasons for filling out our survey:", $co->p, $co->ul( $co->li('Fame'), $co->li('Fortune '), $co->li('Fun'), ) Создаем гиперссылку.Гиперссылки помещаются на страницу CGI-методом а, как в примере ниже, где выводится URL для перехода (на случай, если пользователь не заинтересован в заполнении анкеты, созданной сценарием cgil.pl): #!/usr/local/bin/perl $со = new CGI; print "If you would rather not fill out our survey, ", "you might be interesed in", $co->a({href=>"http://www. cpan.org/"}, "CPAN"), ". " Создаем горизонтальную полосу.Для создания горизонтальной линии (метка <HR>)используется CGI-метод hr: #!/usr/local/bin/perl $со = new CGI; print $co->hr Создаем HTML-форму.Элементы управления HTML группируются в формы. В примере с анкетой для создания формы использовался GGI-метод startform.После нажатия кнопки Submit данные из элементов управления должны быть прочитаны и переданы сценарию, формирующему сводку данных, то есть cgi2.pl. URL этого сценария указывается в атрибуте actionформы: #!/usr/local/bin/perl $со = new CGI; print $co->startform( -method=>'POST', -action=>'http://www.yourself.com/user/cgi/cgi2.pl') #$co->startform() Все последующие элементы управления будут включены в форму, потому что метод startformгенерирует тег <FORM>. Замечание. Если startform вызывается без аргументов, кнопка Submit возвращает введенные данные той же форме. Ниже рассказывается, как использовать такую возможность. Работаем с текстовыми полями.Для создания текстового поля, позволяющего вводить текст, используется CGI-метод textfleld.В примере ниже создается текстовое поле, предназначен­ное для хранения имени пользователя. #!/usr/local/bin/perl "Please enter your name: ' , $co->textfield('text') Чтение данных из элементов управления HTML.Элементы управления созданы (точнее, пока только текстовое поле), но как считать из них данные? Когда пользователь нажмет на кнопку Submit, броузер отправит данные формы сценарию cgi2.pl; CGI-метод paramв нем как раз и предназначен для чтения данных. Ему достаточно передать имя, присвоенное текстовому полю, в данном случае — 'text'(см. предыдущий раздел), а вывод выполняется следующим образом: #!/usr/local/bin/perl $co = new CGI; print "Your name is: ", $co->em($co->param( 'text')), "."; Метод emсоздает метку <ЕМ>,которая большинством броузеров воспринимается как указание на переход к курсивному начертанию. Работаем с текстовыми областями.Текстовая область может содержать несколько строк текста. Вот как в cgil.pl создается текстовая область, предназначенная для ввода любого мнения пользователя (задается как описание самой области в 10 строк по 60 символов в каждой, так и некоторого текста по умолчанию, а также имени области, 'textarea'): #!/usr/local/bin/perl $со = new CGI; print "Please enter your opinion; ", $co->p, $co->' textarea' ( -name => 'textarea', -default => 'No opinion', -rows => 10, -columns => 60 ) А во фрагменте ниже, CGI-метод paramсчитывает текст и выводит данные анкеты: print "Your opinions are: ", $co->em($co->param('textarea')), "."; Работаем с кнопками с независимой фиксацией.Кнопки с независимой фиксацией (check­buttons) обычно объединяются в группу, что позволяет возвращать имена выбранных эле­ментов управления в одном списке. Во фрагменте кода, приведенном ниже, с помощью CGI-метода , checkbox_groupкак раз и создается такая группа. Ей присваивается имя, кноп­ки получают подписи и задаются пункты, выбранные по умолчанию при выводе Web-страницы: #!/usr/local/bin/perl $со = new CGI; print "Please indicate what products you use. ",$co->p, $co->checkbox_group( -name => 'checkboxes', -values => ['Shampoo', 'Toothpaste', 'Bread', 'Cruise missiles'], -defaults => ['Bread', 'Cruise missiles'] ) Код ниже предназначен для проверки и вывода выбора пользователя. В данном случае paramвозвращает список имен помеченных кнопок, поэтому потребовался вызов функции join, объединяющей элементы списка в строку: print "You use these products: ", $co->em(join(", ", $co->param('checkboxes'))), Работаем со списками.Список с готовыми значениями можно прокрутить в случае, когда невозможно одновременно вывести па экран все его строки. Этот элемент управления созда­ется CGI-методом scrolling_list.В сценарии cgil.pl список позволяет выбрать уровень доходов. Он называется 'list'и включает строки 'Highest', 'High', 'Medium'и 'Low',причем по умолчанию выбрано 'High': #! /usr/local/bin/perl $со = new CGI; print "Please indicate your income level: ",$co->p, $co->scrolling_list('list', ['Highest', 'High', 'Medium', 'Low'], 'High', ) Ниже приведен пример чтения и вывода выбранной строки: print "Your income level is: ", $co->em($co->param('list')), "."; Работаем с кнопками с зависимой фиксацией.Кнопки с зависимой фиксацией (radiobuttons) позволяют сделать однозначный выбор из нескольких значений. Например, в cgil.pl создается семь таких кнопок. Они объединяются в группу 'radios'и получают значения от '1' до '7', а метки прикрепляются к ним с помощью хэша %labels: #!/usr/local/bin/perl $со = new CGI; $labels{'1'} = 'Sunday'; $labels{'2'} = 'Monday': $labels{'3'} = 'Tuesday'; $labels{'4'} = 'Wednesday'; $labels{'5' } = 'Thursday', $labels{'6'} = 'Friday'; $labels{'7'} = 'Saturday'; print "Please indicate your day of a week: ", $co->p, $co->radio_group ( -name->' radios', -values=>['1', '2', '3', '4', '5', '6', '7'], -default=>'1', -labels=>\%labels ) Ниже приведен пример чтения и печати выбранного элемента, взятый из сценария cgi2.pl: print "Today is day ', co->param('radios'), " of the week."; Работаем с раскрывающимся списком.В HTML раскрывающийся список представляет собой набор элементов, который пользователь может открыть нажатием кнопки, обычно сопровождающийся изображением стрелки вниз. Пользователь может выбрать элемент списка, а вы - определить, на чем он остановился. Вот как делается выбор количества непрошеной почты, которое пользователь согласен получать (пример взят из нашей анкеты). Элементы задаются при помощи метода popup_menu: #!/usr/local/bin/perl $со = new CGI; print $co->popup_menu ( -name => 'popupmenu', -values => ['Very much', 'A lot','Not so much', 'None'] ) Далее приведен пример чтения и печати выбора пользователя, взятый из сценария cgi2.pl: print "How much unsolicited mail you like", $co->param('popupmenu'); Работаем со скрытыми полями данных.Данные, хранящиеся в скрытом поле на Web-странице, невидимы для пользователя. (Это удобно, когда сценарий ожидает получить некоторые неизменные сведения о странице.) Такие поля создаются следующим образом: #!/usr/local/bin/perl $со = new CGI; print $co->hidden(-name=>'hiddendata', -default=>'Rosebud'), И вот как вывести эти данные из cgi2.pl: print "The hidden data is: ", join(", ", $co->param('hiddendata')); Создаем кнопки отмены и подтверждения.Чтобы отправить на сервер данные формы, пользователь должен нажать кнопку Submit. Она создается CGI-методом submit.Аналогично, кнопка Reset, которая очищает данные формы, создается методом reset.Ниже приведен пример кода, создающий кнопки Submit и Reset на Web-странице: #!/usr/local/bin/perl $со = new CGI; print $co->center( $co-> submit(-value=>'Отправить'), $co->reset(-value=>'Отмена')) После нажатия на кнопку Submit данные отправляются сценарию cgi2.pl. Закрываем HTML-форму.Все элементы управления, описанные ранее, являются частью одной формы анкеты, созданной в cgil.pl. Для открытия формы использовался метод startform,а для ее закрытия — endform: #!/usr/local/bin/perl $со = new CGI; print $co->endform, Закрываем HTML-документ.Чтобы завершить работу с HTML-документом, используйте метод end_html,который выводит теги </BODY></HTML>.Вот как заканчивается страница с анкетой в сценарии cgil.pl: #!/usr/local/bin/perl $со = new CGI; print $co->end_html; На этом cgil.pl кончается. Когда пользователь введет данные и нажмет кнопку Submit, будет вызван сценарий cgi2.pl, который выведет сводку анкеты. Функционально-ориентированное CGI-программирование.До сих пор мы использовали объектно-ориентированные методы. Однако пакет CGI имеет и функционально-ориентированный интерфейс (Впрочем, при обращении к нему некоторые возможности объектно-ориентированною интерфейса становятся недоступными). В примере ниже используется функционально ориентированный интерфейс пакета CGI. Код генерирует текстовое поле с предложением ввести имя пользователя. После нажатия на кнопку Submit данные возвращаются к тому же CGI-сценарию, который с помощью функции рагаmвыводит введенное имя в нижней части Web-страницы: Листинг 5.9. Функционально ориентированный интерфейс пакета CGI. #!/usr/local/bin/perl use CGI qw/:standard/; print header(-charset=>'windows-1251', -lang=>'ru'), start_html(' CGI Functions Example' ),h1('CGI Functions Example'), start_form, "Please enter your name: ", textfield('text'), p, submit(-value=>'Отправить'), reset(-value=>'Отмена'), end_form,hr; if(param()) {print "Your name is: ",em(param('text')), hr;} print end_html; Использование cgi-lib.pl.Ранее рассказывалось о CGI-программировании на базе методов стандартного модуля CGI.pm. He менее популярен среди программистов пакет cgi-lib.pl. Поскольку многие CGI-сценарии на Perl написаны с его помощью, далее рассказывается именно о нем. Авторские права на этот пакет принадлежат его создателю Стивену Е. Бреннеру, на домашней странице которого (http://cgi-lib.stanford.edu/cgi-lib) можно получить копию cgi-lib.pl. Вам разрешается работать с cgi-lib.pl и даже изменять его до тех пор, пока ваши действия не будут ущемлять описанные в начале файла авторские права. Особая процедура установки не требуется — файл cgi-lib.pl копируется в каталог, где хранятся CGI-сценарии, и с помощью команды require подключается к ним: require 'cgi-lib.pl'; Если у вас нет этого пакета - просто используйте модуль CGI.pm в таком контексте: use CGI qw/:ReadParse, PrintHeader, HtmlTop, HtmlBot, SplitParam/; Далее создаются два сценария, генерирующие те же страницы, что и в предыдущей главе, но вместо CGI.pm на сей раз будет использован пакет cgi-lib.pl. Предыдущие сценарии назывались cgil.pl и cgi2.pl, а в этой речь пойдет о libl.pl и lib2.pl. Пакет cgi-lib.pl подключается к сценарию с помощью команды require. (He запрещено использовать также use, но вряд ли вам встретится такой вариант.) В отличие от модуля CGI.pm, количество функций, генерирующих теги HTML в cgi-lib.pl, крайне ограничено. Обычно эти теги приходится выводить вручную. (Пакет cgi-lib.pl предназначался в первую очередь для разбора посланных сценарию данных.) Впрочем, некоторые теги HTML все же генерируются автоматически: подпрограмма PrintHeader создает шапку HTML, необходимую для страницы, раздел HtmlTop (метки <HEAD> и <BODY>). Также с ее помощью можно создать заголовок страницы, как показано в следующем примере, задающем страницу с заголовком "My Web Page": #!/usr/local/bin/perl require 'cgi-lib. рl'; print &PrintHeader; print &HtmlTop ("My Web Page"); После описания начала страницы остальная разметка HTML (в том числе формы) создается путем непосредственного вывода тегов. Например, вот так задается заголовок <Н1>: print "<CENTER><H1>Hello!</H1></CENTER>"; Чтобы прочитать данные, переданные CGI-сценарию, используется подпрограмма ReadParse. Она создает хэш (обычно называемый %in) и записывает в него значения элементов данных, переданных сценарию. Элементы данных адресуются по именам, присвоенным соответствующим элементам HTML. Например, следующий код создает хэш %in и, читая данные текстового поля 'text', выводит их: &ReadParse(*in); print "Here is the text: <EM>", $in('text'), "</EM>."; Чтобы завершить Web-страницу метками HTML </BODY> и </HTML>, можно использовать подпрограмму HtmlBot (она просто возвращает строку "</BODY>\n</HTML>\n"): print &HtmlBot; Вот так, вкратце, и работает cgi-lib.pl. Листинг 5.10. lib1.pl #!/usr/local/bin/perl #require 'cgi-lib.pl'; use CGI qw/:ReadParse, PrintHeader, HtmlTop, HtmlBot, SplitParam/; print &PrintHeader; print &HtmlTop ("CGI Example Using cgi-lib.pl"); print "<BODY BGCOLOR=\ white\ LINK=\ red\><p> <CENTER><H1>Here is the Survey!</H1></CENTER> <H2>Please fill out our survey</H2> Reasons for filling out our survey: <P><UL> <LI>Fame</LI><LI>Fortune</LI><LI>Fun</LI></UL> If you would rather not fill out our survey, you might be interested in <A HREF=http://www.cpan.org>CPAN</A> <HR><FORM METHOD=\"POST\" ACTION=\"http://inna/scripts/web/l6/lib2.pl\" ENCTYPE=\"application/x-www-form-urlencoded\"> Please enter your name. <INPUT TYPE=\"text\" NAME=\"text\" VALUE=\"\"><P> Please enter your opinion:<P><TEXTAREA NAME=\"textarea\" ROWS=10 COLS=60>No opinion</TEXTAREA><P> Please indicate what products you use <P> <INPUT TYPE=\"checkbox\" NAME=\"checkboxes\"VALUE=\"Shampoo\"> Shampoo <INPUT TYPE=\"checkbox\" NAME=\"checkboxes\"VALUE=\"Toophpaste\"> Toothpaste <INPUT TYPE=\"checkbox\" NAME=\"checkboxes\" VALUE=\"Bread\" CHECKED> Bread <INPUT TYPE=\"checkbox\" NAME=\"checkboxes\" VALUE=\"Cruise missiles\" CHECKED>Cruise missiles </P> Please indicate your income level:<P><SELECT NAME=\"list\" SIZE=4> <OPTION VALUE=\"Highest\">Highest <OPTION SELECTED VALUE=\"High\">High <OPTION VALUE=\"Medium\">Medium <OPTION VALUE=\"Low\">Low </SELECT><P> Please indicate your day of the week:<P> <INPUT TYPE=\"radio\" NAME=\"radios\" VALUE=\"1\" CHECKED>Sunday <INPUT TYPE=\"radio\" NAME=\"radios\" VALUE=\"2\">Monday <INPUT TYPE=\"radio\" NAME=\"radios\" VALUE=\"3\">Tuesday <INPUT TYPE=\"radio\" NAME=\"radios\" VALUE=\"4\">Wednesday <INPUT TYPE=\"radio\" NAME=\"radios\" VALUE=\"5\">Thursday <INPUT TYPE=\"radio\" NAME=\"radios\" VALUE=\"6\">Friday <INPUT TYPE=\"radio\" NAME=\"radios\" VALUE=\"7\">Saturday <P> Thank you for filling out our Survey. Please indicate how much unsolicited mail you like to get. <SELECT NAME=\"popupmenu\"> <OPTION VALUE=\"Very much\">Very much <OPTION VALUE=\"A lot\">A lot <OPTION VAlUE=\"Not so much\">Not so much <OPTION VALUE=\"None\">None</SELECT><P> <INPUT TYPE=\"hidden\" NAME=\"hiddendata\" VALUE=\"Rosebud\"> <CENTER><INPUT TYPE=\"submit\" NAME=\"submit\"> <INPUT TYPE=\"reset\"></CENTER><HR></FORM>"; print &HtmlBot; Листинг 5.11. lib2.pl #!/usr/local/bin/perl #require 'cgi-lib.pl'; use CGI qw/:ReadParse, PrintHeader, HtmlTop, HtmlBot, SplitParam/; print &PrintHeader; print &HtmlTop ("CGI Example Using cgi-lib.pl"); print "<BODY BGCOLOR=\white\ LINK=\ red\><p> <CENTER><H1>Thank you for filling out our survey.</H1></CENTER> <H3>Here are your responses...</H3>"; if (&ReadParse(*in)) {print "Your name is: <EM>", $in{'text'}, "</EM>.", "<p>","Your opinions are. <EM>", $in{'textarea'}, "</EM>.","<p>", "You use these products. <EM>", join(", ", &SplitParam($in{'checkboxes'})), "</EM>.<p>", "Your income level is: <EM>",$in{'list'}, "</EM>.<p>Today is day <EM>", $in{'radios'}, "</EM> of the week.<p>","How much uncolicited mail you like<EM>", $in{'popupmenu'}, "</EM>.", "<p>", "The hidden data is <EM>", $in{'hiddendata'}, "</EM>."; } print &HtmlBot; Какие подпрограммы входят в состав cgi-lib.pl?Вот их список: CgiDie — как и CgiError, печатает сообщение об ошибке и, кроме того, останавливает программу. CgiError — печатает сообщение об ошибке, используя стандартные заголовки и HTML-код. HtmlBot — возвращает строку"</BODY>\n</HTML>\n". HtmlTop — возвращает раздел <HEAD> документа HTML и открывает раздел <BODY>. Необязательный строковый параметр используется в качестве названия Web-страницы: добавляется тег HTML <H1> с этим названием. MethGet — возвращает значение истина, если текущий вызов CGI сделан при помощи метода GET. В противном случае возвращается значение ложь. MethPost — возвращает значение истина, если текущий вызов CGI сделан при помощи метода POST. В противном случае возвращается значение ложь. MyBaseUrl — возвращает базовый адрес (base URL) CGI-сценария, без дополнительного пути или строк запроса. MyFullUrl — возвращает базовый адрес (base URL) CGI-сценария, включая дополнительный путь и строки запроса. PrintEnv — форматирует и печатает переменные среды, доступные сценарию. PrintHeader — возвращает строку "Content-type: text/html\n\n". С нее должны начинаться все Web-страницы, создаваемые cgi-lib.pl. PrintVariables — форматирует и печатает значения данных. Ей передается хэш или запись таблицы символов (для вывода элементов соответствующего массива). Без аргументов PrintVariables выводит содержимое хэша %in. ReadParse — основная подпрограмма библиотеки cgi-lib.pl. Она читает и разбирает данные, переданные CGI-сценарию методами GET или POST. Обычно она используется для создания хэша %in: ей передается запись таблицы символов *in. Хэш содержит данные, переданные сценарию, упорядоченные по именам соответствующих элементов управления. Необязатель­ные второй, третий и четвертый параметры указывают на то, что надо заполнить соответствующие хэши данными из принятых файлов. SplitParam — разбивает параметр, содержащий несколько значений, на список из единичных параметров. Эта подпрограмма предназначена для работы с элементами HTML, способными хранить несколько значений, — например, группой кнопок. Начинаем документ HTML.Прежде всего, необходимо подключить пакет cgi-lib.pl. HTTP-заголовок ("Content-type: text/html\n\n") обычно генерируется функцией PrintHeader. Секции <HEAD> и <BODY> создает подпрограмма HtmlTop. Ее необязательный строковый аргумент используется в качестве названия Web-страницы и вставляется в начало страницы как заголовок первого уровня. Пример (lib1.pl): #!/usr/local/bin/perl require 'cgi-lib.pl'; print &PrintHeader; print &HtmlTop ("CGI Example Using cgi-lib.pl"); Если для тега <BODY> требуется задать дополнительные атрибуты, их выводят вручную: print "<BODY BGCOLOR=\ white\ LINK=\ red\><p>"; Подсказка. Конечно же, можно пропустить HtmlTop и создать собственные <HEAD> и <BODY>, выводя теги HTML со всеми необходимыми атрибутами. Файл cgi-lib.pl не имеет специальных подпрограмм для создания разметки HTML, поэтому почти все, что требуется, приходится выводить вручную. Читаем данные из элементов управления HTML.Для чтения данных из различных элементов управления в cgi-lib.pl предназначена подпрограмма ReadParse. Обычно создается хэш %in, с данными, полученными от элементов управления. Он адресуется по именам элементов. Например, в листинге 6-8 мы задавали текстовое поле с именем text. Вот как создается хэш %in и выводятся данные, полученные от элемента управления: require 'cgi-lib.pl'; if (&ReadParse(*in)) {print "Your name is: ", $in{'text'}, "<p>";} Обратите внимание: значение ReadParse проверяется до обращения к хэшу %in. Если ReadParse возвращает значение ложь, значит, получить данные не удалось. Работаем с текстовыми областями.Содержимое текстовой области выводится так: if (&ReadParse(*in)) {print "Your opinions are: ", $in{'textarea'};}; Работаем с кнопками с независимой фиксацией.Когда данные группы кнопок будут переданы сценарию lib2.pl, $in('checkboxes') возвратит строку с несколькими значениями. Подпрограмма SplitParam пакета cgi-lib.pl делает из этой строки список: if (&ReadParse(*in)) { print 'You use these products: ", join(", ", &SplitParam($in{'checkboxes'}));} Работаем со списками. Вот как lib2.pl читает и выводит на экран данные, выбранные пользователем из списка: if (&ReadParse(*in)) {print "Your income level is: ",$in{'list'};} Работаем с кнопками с зависимой фиксацией. Сценарий lib2.pl проверяет, какая кнопка была выбрана, и выводит ее значение: if (&ReadParse(*in)) {print "Today is day", $in{'radios'};} Работаем с раскрывающимися списками.Сценарий lib2.pl проверяет выбор пользователя и выводит его на экран: if (&ReadParse(*in)) {print 'How much unsolicited mail you like:", $in{ 'popupmenu'}, "<p>";} Работаем со скрытыми полями данных.Вот часть кода lib2.pl, читающая текст из скрытого элемента управления и выводящая его на экран: if (&ReadParse(*in)) {print "The hidden data is ", $in{'hiddendata'};} Завершаем документ HTML.Подпрограмма HtmlBot пакета cgi-lib.pl закрывает Web-страницу. Она возвращает строку "</BODY>\n</HTML>\n": print &HtmlBot; Часто эта строка оказывается последней в сценарии, как и в lib1.pl с lib2.pl. Выводим все переменные.В этих примерах значения данных, переданных элементами управления HTML, выводились непосредственно оператором print. Но это можно сделать и проще: то же самое делает подпрограмма PrintVariables, но только в фиксированном фор­мате. Например, можно заменить lib2.pl кодом, приведенным ниже: Листинг 5.12. Вывод всех переменных. #!/usr/local/bin/perl #require 'cgi-lib рl'; use CGI qw/:ReadParse, PrintHeader, HtmlTop, HtmlBot, Vars/; print &PrintHeader; print &HtmlTop ("CGI Example Using cgi-lib.pl"); if (&ReadParse(*in)) { print &Vars; } print &HtmlBot; Все данные, переданные lib2.pl, действительно есть, но не сопровождаются пояснительным текстом. PrintVariables полезна при отладке, но вряд ли нужна в завершенном проекте. Примеры приложений. Огромное количество CGI-сценариев на языке Perl уже доступно в Интернете и готово к использованию. Вот список нескольких полезных источников (проверяйте каждый такой сценарий на защищенность, а также на предмет наличия любых других проблем): · архив Ясона (Jason's Perl Archive) — www.aquapal.co.uk/perl/perl.html; · архив сценариев Мэтта (Matt's Script Archive) — www.worldwidemart.com/ scripts/; · архив фирмы Yahoo! (Yahoo Perl Scripts) — dir.yahoo.com/Computers_And_-Internet/ProgrammingLanguages/Perl/Scripts/; · страница ссылок и сценариев на Perl, принадлежащая Дэйлу Бьюли (Dale Bewley's Perl Scripts and Links), — www.bewley.net/perl/; · страничка на www.perl.com, посвященная CGI, — reference.perl.com/query.cgi?cgi. · русскоязычный сайт, посвященный Perl - www.perl.ru. Когда вы начнете писать сценарии, которые делают больше, чем простенькие предыдущие, проблема защиты станет актуальной. Это одна из тем, которая будет обсуждаться далее. Защита CGI.Обеспечение безопасности всегда было серьезной проблемой. В наши дни она еще более актуальна, так как но мере развития операционных систем становится все сложнее и сложнее затыкать бреши в защите. Поэтому на Unix-системах CGI-сценарии обычно запускаются от имени идентификатора пользователя "nobody" («никто»). Такой процесс имеет минимум привилегий. Считалось, что процесс, имеющий минимум привилегий, принесет меньше вреда. Однако и по сей день могут возникать проблемы — в частности, из-за неаккуратности в CGI-сценариях. Ниже рассказывается, как обойти некоторые наиболее вероятные неприятности. Вот несколько Web-страниц, посвященных безопасности CGI, которые я рекомендовал бы прочитать до того, как вы начнете создавать для широкого использования что-либо серьезнее простейших CGI-сценариев: страница WWW-консорциума, посвященная безопасности CGI (The World Wide Web Consortium's CGI security page), — www.w3.org/Security/Faq/ www-security-faq.html; часть сборника вопросов и ответов (FAQ) по CGI-программированию на Perl, посвященная проблемам безопасности, - www.perl.com/CPAN-local/doc/ FAQs/cgi/perl-cgi-faq.html; страничка Селены Сол (Selena Sol), рассказывающая, как вы рискуете при установке чужих сценариев — Stars.com/Authoring/Scripting/Sequrity; Следующий шаг — непосредственное изучение кода. В примерах вы найдете информацию о безопасности и о том, как писать CGI-сценарии для счетчиков и гостевых книг. Серьезно беремся за защиту.CGI-сценарии могут порождать множество потенциальных брешей в безопасности. В качестве предельного случая рассмотрим сценарий, запускающий программы, имена которых передаются ему в качестве аргумента. Данные форм HTML посылаются в виде строк, причем в качестве разделителя аргументов используется вопросительный знак. Строка данных записывается в конце URL, что означает, что если вы хотите просто запустить сценарий Perl, URL должен выглядеть, например, так: http://www yourserver.com/user/perl.exe?script.pl Но если хакер увидит, что вы используете технику вроде этой, он может послать собственную строку такого вида: http://www.yourserver.com/user/perl.exe?-e+ nasty commands В результате он сможет выполнить любые команды Perl, что вряд ли вас порадует. Этот пример указывает на одну из самых больших опасностей CGI-сценариев, написанных на Perl, — вызовы внешних программ без проверки кода, передаваемого в конце строки. В Perl внешние программы вызываются многими способами, например с помощью строки, заключенной в обратные апострофы (backtics), вызовов system или ехес. Даже операторы eval требуют осторожного обращения. Очень важно настроить CGI так, чтобы нельзя было легко сделать ничего опасного. Хакеры собаку съели на использовании этого класса ошибок и CGI-сценариев для выполнения кода, нужного им. На самом деле в Perl существует прекрасный механизм безопасности, предназначенный для латания дырок подобного типа, —меченые данные. Если разрешено отслеживание данных, Perl не позволяет передавать пришедшие извне данные функциям system, ехес и т. д. Простое правило, позволяющее обеспечить безопасность, — никогда не передавать непроверенные данные внешней программе и всегда стараться обойтись без запуска командной оболочки. Если же это невозможно, следует всегда проверять аргументы на предмет наличия метасимволов командной оболочки и, по крайней мере, удаления их. Вот метасимволы командной оболочки Unix: &;''\"*?`<>^(){}$\n\r Еще одно важное замечание: не позволяйте другим перезаписывать ваши сценарии или файлы данных, неважно — случайно или намеренно. Другими словами будьте особенно внимательны к правам доступа к файлам, чтобы их нельзя было заместить. И, конечно же, обычные ограничения: не посылайте пароли по электронной почте, не набирайте их при работе с бесплатными утилитами. He оставляйте ваш счет в системе (account) на долгое время неиспользуемым — хакеры следят за такими вещами, чтобы получить контроль над ними. Не позволяйте CGI-сценариям получать слишком много системной информации. И так далее, и тому подобное — большинство хакеров пролезут там, где вы и не думали. Работаем с мечеными данными.Одной из самых больших дыр в защите CGI-сценариев является передача непроверенных данных командному интерпретатору. В Perl для предотвращения таких ситуаций можно использовать механизм меченых данных (tainted data). В этом случае любые переменные, связанные с данными, полученными извне (включая переменные среды, стандартный поток ввода и командную строку), считаются мечеными. Пока они остаются таковыми, их нельзя использовать для чего бы то ни было за пределами вашей программы. Если меченая переменная используется для установки другой переменной, последняя также становится меченой, что означает, что помеченные (или «запачканные») данные могут распространяться по программе сколь угодно далеко и сколь угодно сложными путями, но они все равно будут аккуратно помечены. Подсказка.Этот механизм работает только для скалярных значений. Некоторые элементы массива могут быть мечеными, в то время как остальные — нет. В общем, меченые данные не могут быть использованы при помощи вызовов eval, system, exec. Perl следит за тем, чтобы они не попали в команды, вызывающие оболочку, в команды, модифицирующие файлы, каталоги или процессы. Однако есть одно важное исключение: если вызовам system или eval передается список аргументов, он не проверяется на наличие меченых элементов. Если вы попробуете произвести какую-либо операцию с мечеными данными за пределами программы, Perl остановится с предупреждающим сообщением. В ре­жиме меченых данных Perl прекращает работу также в случае вызова внешней программы без предварительной установки переменной среды PATH. В Perl версии 4 для включения отслеживания меченых данных используется специальная версия интерпретатора, называемая taintperl: #!/usr/local/bin/taintperl Однако в версии 5 проверка меченых данных включена в состав Perl, и вы можете включить ее, передав интерпретатору Perl ключ -T: #!/usr/local/bin/perl -T В следующем примере включается отслеживание меченых данных, но программа не делает ничего опасного — соответственно, проблем нет: #!/usr/local/bin/perl -T print "Hello!\n"; Однако при выполнении потенциально опасных операторов типа system при включенной проверке меченых данных Perl сообщит о возможной бреши в защите, обусловленной использованием данных окружения. Даже если вы не используете PATH при вызове внешней программы, не исключено, что его использует вызываемая программа. Вот сообщение об ошибке, которое вы увидите: #!/usr/local/bin/perl -Т print system( 'date'); Insecure $ENV(PATH) while running with -T switch at taint.pl line 5, <> chunk 1 Чтобы исправить это, вы можете при включенной проверке меченых данных са­мостоятельно установить $ENV{'PATH'}: #!/usr/local/bin/perl -T $ENV{'PATH'} = '/bin:/usr/bin:/usr/1ocal/bin'; print system('date'), Thu Nov 12 19-55 53 NSK Вот еще пример, в котором делается попытка передать системному вызову меченые данные. Даже если $ENV{'PATH'} устанавливается в программе, сценарий все равно прекращает работу, так как пытается передать меченые данные оператору system: #!/usr/local/bin/perl -T $ENV{'PATH'} = /bin:/usr/bin:/usr/local/bin'; while(<>) { $command = $_; system($command); } Insecure dependency in system while running with -T switch at taint.pl line 5, <> chunk 1 Данные, даже будучи переданными в $command из $_, все равно считаются мечеными. Как очистить данные, если вы уверены в них? Очистка данных.Единственный способ очистить меченую переменную — использовать шаблоны, по которым из нее выбираются подстроки. В следующем примере предполагается, что меченая переменная $tainted содержит электронный адрес. Мы можем извлечь его и сохранить как не меченый в другой переменной следующим образом: $tainted =~/(^[\w]+)\@(^[w]+)/ $username = $1; $domain = $2; print "$username\n", print "$userdornain\n'; Таким образом, мы извлекли безопасные данные. То есть способ создания «чистых» данных заключается в извлечении из меченых данных подстрок, которые априори безопасны (и, конечно же, не содержат метасимволы командного интерпретатора). Создаем счетчик посещений.Создание счетчика посещений — достаточно простая задача: вы просто должны хранить текущее значения счетчика в файле и показывать его при необходимости. Я приведу пример создания счетчика counter.pl. Подсказка. Заметьте, что этот счетчик просто выводит текущее значение как тексто­вую строку, но в принципе можно сделать более интересные вещи, например, создать гра­фический счетчик, имея набор файлов с изображениями цифр и выводя их один за другим на Web-странице. Можно также воспроизводить цифры с помощью тега HTML <IMG>, если установить атрибут SRC в соответствии с URL сценария, выводящего цифры. Сценарий называется counter.pl, приведен он в листинге 6-12. Чтобы он работал, в том же каталоге, что и counter.pl, должен находиться файл counter.dat. Для начала отсчета запишите в counter.dat 0 (ноль) с помощью любого текстового Листинг 5.13. counter.pl #!/usr/bin/perl use CGI; $co = new CGI; open (COUNT, "<counter.dat") or die "Could not open counter data file!"; $count = <COUNT>; close COUNT; $count++; open (COUNT, ">counter.dat"); print COUNT $count; close COUNT; print $co->header, $co->start_html( -title=>'Counter Example' , -author=>'Andrew', -BGCOLOR=>'white'), $co->center($co->h1('Counter Example')), $co->p, $co->center($co->h3("Current count ", $count)), $co->p, $co->center($co->h3("Reload the page to update the count")), $co->end_html; Этот сценарий очень прост: все, что он делает, — это читает число, хранящееся в counter.dat, увеличивает его на единицу, записывает обратно в counter.dat и затем показывает увеличенный счетчик Создаем гостевую книгу.Создание гостевой книги — шаг вперед по сравнению со счетчиком. Гостевая книга собирает комментарии пользователей и сохраняет их в файле, обычно имеющем формат HTML, чтобы затем выводить их на странице. Наша гостевая книга использует три файла, хранящихся в одном каталоге: guestbook.htm (листинг 6-14), guestbook.pl (листинг 6-15) и book.htm (листинг 6-16). Первый является лицом гостевой книги, то есть именно эта страница указывает пользователю, что он может добавить запись в книгу посетителей. Она получает имя пользователя и комментарий. Когда пользователь нажимает на кнопку подтверждения, данные посылаются сценарию guestbook.pl; иными словами, если вы используете этот сценарий, вам следует сменить указанный URL в guestbook.htm на реальный URL guestbook.pl: <BODY><H1>Please add to my guestbook</H1> <FORM METHOD=POST ACTION= "http://www.yourself.com/cgi/guestbook.pl"> В guestbook.pl (см. листинг 6-15) мы открываем собственно гостевую книгу, хранящуюся в файле book.htm. Основная идея — добавить в нее имя пользователя и его комментарий, но book.htm заканчивается тегами </BODY></HTML>. Поэтому сначала надо установить указатель файла перед этими словами с помощью следующего кода: open (BOOK, ">>book.htm") or die "Could not open guestbook!"; seek (BOOK, -lenght($co->end_html), 2); Поскольку строки </BODY></HTML> в данном случае создаются с помощью CGI-метода end_html, мы откатываемся назад на длину генерируемой строки, что позволяет нам не зависеть от того, что метод end_html будет выводить в следующих версиях модуля CGI.pm. После этого код записывает вместо тегов </BODY></HTML> новые данные, добавляя в конце те же теги вызовом CGI-метода end_html. Затем guestbook.pl создает страницу, на которой располагается благодарность пользователю за комментарии и гиперссылка, позволя­ющая просмотреть содержимое гостевой книги. Иными словами, если вы используете этот сценарий, вам следует сменить URL, приведенный в листинге, на реальный URL book.htm (убедившись, что права доступа для этого файла достаточно низки, чтобы guestbook.cgi мог записывать в него данные): "If you whant to take a look at the guest book, " $co->a({href=> "http://www.yourserver.com/cgi/book.htm"}, "click here"),".", Если пользователь щелкает на гиперссылке, открывается гостевая книга, а ссылки на нее можно расположить на любой другой Web-странице вашего раздела. Имя пользователя и комментарии отображаются в гостевой книге вместе со временем добавления записи. Файл guestbook.pl приводит в безопасное состояние любой код HTML, который пользователь может попытаться ввести в гостевую книгу, замещая любые символы < HTML-кодом &lt (это делается так: $username =~ s/</&lt и $text =~ s/</&lt), который выводит "<", чтобы не позволять броузеру пытаться разобрать комментарии пользователя как HTML. Это означает, что любой код HTML, который пользователь попытается ввести в гостевую книгу, будет выведен как текст и не будет исполняться. Заметьте, что вы можете настроить guestbook.pl так, чтобы он принимал электронные адреса посетителей (впрочем, все больше и больше пользователей не желают оставлять свои адреса не столько из соображений секретности, сколько из-за программ, которые сканируют сеть в поисках адресов электронной почты, а затем продают полученные списки распространителям рекламы). Вы также можете видоизменить файл гостевой книги book.htm, добавив графику с по мощью тега HTML <IMG>, установив фоновое изображение и т. д. Просто следите, чтобы последним, что вы выводите в book.htm был текст </BODY></HTML> (или вывод текущей версии CGI-метода end_html, поскольку в новой версии пакета CGI.pm он может смениться), чтобы guestbook.pl мог откатиться на необходимое число символов и заменить эти теги новым комментарием. Подсказка. Если вы не хотите зависеть от версии модуля CGI.pl, записывайте в отдельный файл длину текста, выведенного методом end_html при последней записи в гостевую книгу и используйте для установки указателя это значение, а не длину строки, выводимой end_html. Листинг 5.14. guestbook.htm <HTML><HEAD><TITLE>Add to the guest book</TITLE></HEAD><BODY> <Н1>Р1еаsе add to my guestbook</H1> <FORM METHOD = POST ACTION = http://www.yourself.com/cgi/guestbook.pl > <BR><CENTER>Please enter your name<P> <INPUT TYPE = "TEXT" NAME ="username"></INPUT> <BR>Please enter your comments <TEXTAREA ROWS = 8 COLS = 40 NAME = "comments"> </TEXTAREA><BR><BR> <INPUT TYPE =SUBMIT VALUE =Send><INPUT type = RESET VALUE =Reset> </CENTER></FORM> </BODY></HTML> Листинг 5.15. guestbook.pl #!/usr/bin/perl use CGI; $co = new CGI; open (BOOK ">>book.htm") or die "Could not open guestBOOK"; seek (BOOK -lenght($co->end_html), 2) $date = date; chop($date); $username = $co->param("username"); $username =" s/<l&lt/; print BOOK, $co->h3("New comments by :, $username, "on ", $date,$co->p,$text,), $co->hr, $co->end_html; close BOOK; print $co->header, $co->start_html( -title=> "Guest Book Example" , -author=> "Andrew", -BGCOLOR=> "white", -LINK=> "red" ); print $co->center($co->h1('Thanks for adding to the guest book!')), "If you whant to take a look at the guest book, ", $co->a({href=> http://www.yourserver.com/cgi/book.htm"}, " click here"),".", $co->hr, $co->end_html; Листинг 5.16. book.htm <HTML><HEAD><TITLE>The Guest Book</TITLE></HEAD> <BODY><CENTER> <H1>Here is the guest book </H1><HR> </BODY></HTML> Теневые посылки (cookies).Создание и чтение теневой посылки (английское cookie, на современном новоязе именуемая также "кука", "кукис") стало популярным в Интернете - по крайней мере, среди Web-программистов. Под этим именем подразумевается использование протокола HTTP для хранения информации, полученной от сервера, на машине клиента и обмен этой информацией между компьютерами и программами-броузерами незаметно от пользователя, то есть в теневом режиме. Теневые посылки и любимы и ненавидимы. Некоторые пользователи протестуют против получения и обработки теневых посылок на своих компьютерах и запрещают этот режим для своих броузеров. Поэтому приведенный ниже пример не активизирует их до тех пор, пока пользователь сам не введет данные для работы теневой посылки. Этот сценарий хранит данные в хеше, поэтому его легко подстроить для использования в других сценариях. Использование теневых посылок.Многие пользователи терпеть не могут, когда на их компьютерах сохраняются мегабайты информации подобного рода. Мне приходилось видеть Web-страницу, на которой было более 70 теневых посылок. Это не столь безобидно как кажется. В большинстве броузеров верхний предел теневых посылок — число порядка 200. Поскольку теневые посылки позволяют отслеживать передвижение пользователей по разделам, а также хранить настройки пользователя, то теплые чувства к теневым посылкам иногда все же преобладают над раздражением. Сценарий, приведенный в листинге 6-17, позволяет посетителю изменить страницу так, чтобы при следующих визитах она бы приветствовала ею по имени, а в день рождения еще и поздравляла бы. Этот сценарий вполне корректен — он не устанавливает никаких теневых посылок до тех пор, пока пользователь сам не предоставит или не обновит необходимую информацию. Сценарий проверяет данные, полученные от пользователя чтобы убедиться, что день рождения введен в формате месяц/день (mm/dd), содержит лишь цифры, а единственный символ / находится в нужном месте, и удаляет теги HTML, которые он мог ввести в строку для имени. Когда пользователь впервые открывает сценарий hellocookie.pl, он может настроить эту страницу, введя имя и цату рождения в формате mm/dd. После нажатия на кнопку подтверждения сценарий записывает информацию под именем greetings, сохраняя имя и день рождения, на компьютере клиента. Когда пользователь снова открывает hellocookie.pl, сценарий проверяет, нет ли у посетителя теневой посылки greetings, и, если она есть, выводит приветствие, включая при необходимости поздравление с днем рождения. Вот и все. Как записать теневую посылку.Записать теневую посылку с помощью CGI.pm несложно. В нашем примере она будет называться "greetings" и хранить информацию в хэше %greetings, уничтожая ее по истечении года: $со = new CGI: $greetingcookie = $co->cookie( -name=>'greetings', -value=>\%greetings, -expires=>'+365d' ); print $co->header(-cookie=>$greetingcookie); Заметьте, что для создания теневой посылки вы передаете ее в качестве именованного параметра CGI-методу header. Как прочитать теневую посылку.Для чтения теневой посылки используется обычный CGI-метод, получающий в качестве параметра имя посылки. После этой операции можно использовать данные хэша %greetings: $со = new CGI; %greetings = $co->cookie('greeting'); print $greetings{'name'} Вот и вся работа с теневыми посылками. Но имейте в виду, что многие пользователи не желают, чтобы программы хранили какие бы то ни было данные на их машинах. Листинг 5.17. Hellocookie.pl #!/usr/bin/perl use CGI; $co = new CGI; %greetings = $co->cookie('greeting'); if ($co->param('name')) {$greetings{'name'} =$co->param('name')} print $greetings{'name'}; if ($co->param('birthday') ) =~ m/\d\d\/\d\d/) {$greetings{'birthday'} = $co->param('birthday');} ($date, $month, $year) = (lockaltime)[3, 4, 5]; $date = join ("/", $month + 1, $day); if(exists($greetings{'name'})) { $greetingstring = "Hello ". $greetings{'name'}; $greetingstring .= ", happy birthday!" if ($date eq $greetings{'birthday'}); $greetingstring =~ s/</&lt/; $promt = "If you want to change this page's settings, just enter new data below."; } else { $promt = "To have this page greet you next time, enter your data below "; } $greetingcookie = $co->cookie( -name=>'greetings', -value=>\%greetings, -expires=>'+365d' ); if ($co->param('name') || $co->param('birthday')) { print $co->header(-cookie=>$greetingcookie); } else { print $co->header;} print $co->start_html(-title=>"Cookie Example",), $co->center( $co->h1("Cookie Example"), $co->p, $co->h1("$greetingstring"), $promt, $co->startform, "Your name: ", $co->textfield( -name=>'name', -default=>'', -override=>1 ), $co->p, "Your birthday (mm/dd): ", $co->textfield( -name=>'birthday', -default=>'', -override=>1 ), $co->p, $co->submit, $co->reset, $co->endform), $co->end_html; Доступ к базам данных. Язык программирования Perl превратился из инструмента, используемого преимущественно администраторами Unix-систем, в наиболее распространенную платформу разработки для World Wide Web. Perl не предназначался изначально для Web, но простота его использова­ния и мощные функции для работы с текстом сделали естественным его применение для CGI-программирования. Сходным образом, MySQL со своей высокой скоростью и широкми возможностями стала очень привлекательным средством для веб-разработчиков. Естественно поэтому, что был разработан интерфейс Perl к MySQL, объединив, таким образом их достоинства. В настоящий момент существуют два интерфейса между Perl и MySQL. Более ранний состоит из специализированного интерфейса Mysql.pm. Другой, более новый интерфейс является подключаемым модулем в комплекте DBI (DataBase Independent) - независимых от базы данных модулей. DBI является попыткой обеспечить общий Perl API для доступа к любым базам данных и предоставления более высокой переносимости. Интерфейс DBI стал наиболее надежным и стандартным, и разработчики MySQL рекомендуют пользоваться только DBI, поскольку дальнейшая разработка модуля Mysql.pm прекращена. Однако многие унаследованные системы все еще используют их, поэтому мы расскажем здесь и о них. DBI.Рекомендуемым методом доступа к базам данных MySQL из Perl является интерфейс DBD/DBI. DBD/DBI означает DataBase Dependent/DataBase Independent (Зависимый от базы данных/Независимый от базы данных). Название связано с двухъярусной реализацией интерфейса. В нижнем ярусе находится зависимый от базы данных уровень. На нем существуют свои модули для каждого типа базы данных, доступного из Perl. Поверх этого уровня находится независимый от базы данных уровень. Это тот интерфейс, которым вы пользуетесь при доступе к базе данных. Выгода такой схемы в том, что программисту нужно знать только один API уровня независимости от базы данных. Когда появляется новая база данных, кому-нибудь нужно лишь написать для нее модуль DBD (зависимый), и она станет доступна всем программистам, использующим DBD/DBI. Как и в любом модуле Perl, для получения доступа нужно указать DBI в директиве use: #!/usr/bin/perl -w use strict; use CGI qw(:standard); use DBI; При запуске программ Perl для MySQL/mSQL следует всегда задавать аргумент командной строки -w. Благодаря этому DBI будет перенаправлять все специфические для MySQL сообщения об ошибках на STDERR, и вы сможете увидеть ошибки, вызванные работой с базой данных, не прибегая к явной проверке их в программе. Всякое взаимодействие между Perl, с одной стороны, и MySQL— с другой, производится с помощью объекта, известного как описатель базы данных (handle). Описатель базы данных (database handle) - это объект, представленный в Perl как скалярная ссылка и реализующий все методы, используемые для связи с базой данных. Одновременно можно открыть любое число описателей базы данных, ограничение накладывают только ресурсы системы. Метод connect() использует для создания описателя формат соединения DBI:ser­vertype:database:hostname:port (имя узла и порта необязательны), дополнительными аргументами служат имя пользователя и пароль: my $dbh= DBI->connect( 'DBI:mysql:mydata ', undef, undef); my $dbh = DBI->connect('DBI:mysql:mydata', 'me', 'mypass"}; Атрибут servertype является именем специфического для базы данных DBD-модуля, в нашем случае «mysql» (обратите внимание на точное использование регистра). В первом варианте создается соединение с сервером MySQL на локальной машине через сокет Unix. Это наиболее эффективный способ связи с базой данных, который должен использоваться при соединении на локальном сервере. Если указано имя узла, оно используется для соединения с сервером на этом узле через стандартный порт, если только не задан и номер порта. Если при соединении с сервером MySQL вы не указываете имя пользователя и пароль, то пользователь, выполняющий программу, должен обладать достаточными привилегиями в базе данных MySQL. В Perl 5 используются два соглашения по вызову модулей. В объектно-ориентированном синтаксисе для ссылки на метод определенного класса используется символ стрелки «->» (как в DBI->connect). Другой метод - использование непрямого синтаксиса, в котором за именем метода следует имя класса, а затем - аргументы. В последнем примере метод connect следовало бы записать как connect DBI 'DBI:mysql:mydata', 'me', 'mypass'. После соединения с сервером MySQL описатель базы данных - во всех примерах этого раздела $dbh - становится шлюзом к базе данных. Например, так готовится запрос SQL: $dbh->prepare($query); При работе с MySQL можно включать в запрос другие базы данных, явно указывая их имена. Кроме того, в MySQL, при необходимости одновременного доступа к нескольким базам данных можно создать несколько описателей базы данных и использовать их совместно. Для иллюстрации использования DBI рассмотрим следующие простые программы. В листинге 5.18 datashow.pl принимает в качестве параметра имя узла; при отсутствии параметра принимается имя «localhost». Затем программа выводит список всех баз данных, имеющихся на этом узле. Листинг 5.18. Скрипт datashow.pl показывает базы данных, имеющиеся на сервере MySQL #!/usr/bin/perl -w use strict; use CGI qw( standard); use CGI Carp; # Использовать модуль DBI use DBI CGI use_named_parameters(1), my ($server, $sock, $host); my $output = new CGI; $server = param('server') or $server =""; # Подготовить DBD-драйвер для MySQL my $driver = DBI->install_driver('mysql'); my @databases = $driver->func($server '_ListDBs'); # Если параметр §databases не определен, # предполагаем, что на # этом узле не запущен сервер MySQL Однако это может быть вызвано # другими причинами Полный текст сообщения об ошибке # можно получить проверив $DBI errmsg if (not @databases) { print header, start_html( title => Данные по $server , BGCOLOR => white ), print <<END_OF_HTML, <H1>$server</h1> Ha $server , по-видимому не запущен сервер mSQL </body></html> END_OF_HTML exit(0)} print header, start_html(title =>"Данные по $host", BGCOLOR => white), print <<END_OF_HTML, <H1>$host</h1> <P>Соединение с $host на сокете $sock<P>Базы данных <br><UL> END_OF_HTML foreach(@databases) { print "<LI>$_\n";} print << END_OF_HTML </ul></body></html> exit(0) В листинге 5.19 tableshow.pl принимает в качестве параметров имя сервера базы данных (по умолчанию «localhost») и имя базы данных на этом сервере. Затем программа показывает все таблицы, имеющиеся в этой базе данных. Листинг 5.19. Скрипт tableshow.pl выводит список всех таблиц в базе данных #!/usr/bin/perl -w use strict; use CGI qw( standard); use CGI Carp; # Использовать модуль Msql.pm use DBI; CGI use_named_parameters(1); my ($db); my $output = new CGI; $db = param( db ) or die( He указана база данных' ); # Connect to the requested server my $dbh = DBI->connect( DBI mysql $db $server, undef, undef); # Если не существует $dbh значит, попытка соединения с сервером # базы данных не удалась Возможно, сервер не запущен, # или не существует указанной базы данных if (not $dbh) { print header, start_html( title => Данные по $host => $db , BGCOLOR => white ) print <<END_OF_HTML <H1>$host</h1> <H2>$db</h2> Попытка соединения не удалась по следующей причине <BR> $DBI errstr </body></html> END_OF_HTML exit(0) } print header, start_html( title => Данные по $host => $db , BGCOLOR => white ), print <<END_OF_HTML, <H1>$host</h1> <H2>$db</h2><р> Таблицы:<br><UL> END_OF_HTML # $dbh->listtable возвращает массив таблиц, # имеющихся в текущей базе данных. my @tables = $dbh->func('_ListTables'); foreach (@tables) { print "<LI>$_\n"; } print <<END_OF_HTML; </ul> </body></html> END_OF_HTML exit(0); И наконец, листинг 5.20 показывает, как вывести все сведения о некоторой таблице. Листинг 5.20. Скрипт tabledump.pl выводит сведения об указанной таблице #!/usr/bin/perl -w use strict; use CGI qw(:standard); use CGI::Carp; # Использовать модуль DBI use DBI; CGI::use_named_parameters(1); my ($db,$table); my $output = new CGI; $server = param('server') or $server = ''; $db = param('db') or die("He указана база данных !"); # Соединиться с указанным сервером. my $dbh = DBI->connect("DBI:mysql:$db:$server", undef, undef); # Готовим запрос к серверу, требующий все данные таблицы. my $table_data = $dbh->prepare("select * from $table"); # Посылаем запрос серверу. $table_data->execute; # Если возвращаемое значение не определено, таблица не существует # или пуста; мы не проверяем, что из двух верно, if (not $table_data) { print header, start_html('title'=> "Данные no $host => $db => $table", 'BGCOLOR'=>'white'); print <<END_OF_HTML; <H1>$host</h1><H2>$db</h2> Таблицы'$table' нет в $db на $host. </body></html> END_OF_HTML exit(0); } # Теперь мы знаем, что есть данные для выдачи. Сначала выведем # структуру таблицы. print header, start_html('title'=>"Данные по $host => $db => $table",'BGCOLOR'=>'white'); print <<END_OF_HTML; <H1>$host</h1> <H2>$db</h2> <H3>$table</h3><p><TABLE BORDER> <CAPTION>Поля</caption> <TR> <TH>Поле<TH>Тип<TH>Pa3Mep<TH>NOT NULL </tr> <UL> END_OF_HTML # $table_data->name возвращает ссылку # на массив полей таблицы. my @fields = @{$table_data->NAME}; # $table_data->type возвращает ссылку на массив типов полей. # Возвращаемые типы имеют стандартные обозначения SQL, # а не специфические для MySQL. my @types = @{$table_data->TYPE}; # $table_data->is_not_null возвращает ссылку на массив типа Boolean, # указывающий, в каких полях установлен флаг 'NOT NULL'. my @not_null = @{$table_data->is_not_null}; # $table_data->length возвращает ссылку на массив длин полей. Они фиксированные для типов INT и REAL, но переменные ( # заданные при создании таблицы) для CHAR. my @length = @{$table_data->length}; # Все перечисленные выше массивы возвращаются в одном и том же # порядке, поэтому $fields[0],$types[0], $not_null[0] and # $length[0] относятся к одному полю. foreach $field (0. .$#fields) { print "<TR>\n"; print "<TD>$fields[$field]<TD>$types[$field]<TD>"; print $length[$field] if $types[$field] eq 'SQL_CHAR'; print "<TD>"; print 'Y' if ($not_null[$field]); print "</tr>\n"; } print <<END_OF_HTML; </table> <P><B>Data</b><br><OL> END_OF_HTML #построчно перемещаемся по данным: DBI::fetchrow_array(). # Мы сохраним данные в массиве в таком же порядке, как и в # массивах (@fields, @types, etc.), которые мы создали раньше. while(my((@data)=$table_data->fetchrow_array) { print "<LI>\n<UL>"; for (0..$#data) { print "<LI>$fields[$_] => $data[$_]</li>\n"; } print "</ul></li>"; } print <<END_OF_HTML; </ol> </body></html> END_OF_HTML Пример приложения, использующего DBI.DBI допускает любые SQL-запросы, поддерживаемые MySQL. Например, рассмотрим базу данных, используемую в школе для ведения учета учащихся, состава классов, результатов экзаменов и т. д. База данных должна содержать несколько таблиц: одну для данных о предметах, другую для данных об учащихся, таблицу для списка экзаменов и по одной таблице для каждого экзамена. Возможность MySQL выбирать данные из нескольких таблиц, используя объединение таблиц, позволяет совместно использовать таблицы как согласованное целое для создания приложения, облегчающего работу учителя. Для начала мы хотим учесть данные об экзаменах по разным предметам. Для этого нам нужна таблица, содержащая названия и числовые идентификаторы для экзаменов. Нам потребуется также отдельная таблица для каждого экзамена. В этой таблице будут содержаться результаты испытаний для всех учащихся, а также высший балл для проведения сравнения. Таблица test имеет следующую структуру: CREATE TABLE test ( id INT NOT NULL AUTO_INCREMENT, name CHAR(100), subject INT, num INT Для каждого отдельного экзамена структура таблицы такая: CREATE TABLE t1 ( id INT NOT NULL, q1 INT, q2 INT, q3 INT, q4 INT, total INT ) К имени таблицы t присоединен идентификатор экзамена из таблицы test. При создании таблицы пользователь определяет количество вопросов. Поле total содержит сумму баллов по всем вопросам. Программа, обрабатывающая данные экзаменов, называется test.pl. Эта программа, текст которой следует ниже, позволяет только добавлять новые экзамены. Просмотр экзаменов и их изменение не реализованы и оставлены в качестве упражнения. Этот сценарий хорошо показывает возможности DBI: Листинг 5.21. Скрипт test.pl добавляет новые экзамены #!/usr/bin/perl -w use strict; require my_end; use CGI qw(:standard); my $output = new CGI; use_named_parameters(1); # Использовать модуль DBI. use DBI; # DBI::connect() использует формат 'DBI:driver:database' # используется драйвер MySQL и открывается база данных 'teach', my $dbh = DBI->connect('DBI:mysql:teach'); # Операция добавления распределена между тремя функциями. Add - # выводит пользователю форму шаблона для создания нового экзамена, sub add { $subject = param('subject') if (param('subjects')); $subject = "" if $subject eq 'all'; print header, start_html('title'=>'Create a New Test', 'BGCOLOR'=>'white'); print <<END_OF_HTML; <Н1>Создание нового экзамена</п1> <FORM ACTION="test.pl" METHOD=POST> <INPUT TYPE=HIDDEN NAME="action" VALUE="add2"> Предмет: END_OF_HTML my @ids = (); my %subjects = (); my $out2 = $dbh->prepare("select id,name from subject order by name"); $out2->execute; while(my($id,$subject)=$out2->fetchrow_array) {push(@ids,$id); $subjects{"$id"}'= $subject; } print popup_menu( 'name'=>'subjects', 'values'=>[@ids], 'default'=>$subject, 'labels'=>\%subjects); print <<END_OF_HTML; <br> Число вопросов: <INPUT NAME="num" SIZE=5><br> Название или идентификатор (например, дата) экзамена: <INPUT NAME="name" SIZE=20> <Р> <INPUT TYPE=SUBMIT VALUE=" Следующая страница "> <INPUT TYPE=RESET> </form></body></html> END_OF_HTML } Эта функция выводит форму, позволяющую пользователю выбрать предмет для экзамена, а также количество вопросов и название. Для вывода списка имеющихся предметов выполняется запрос к таблице предметов. При выполнении в DBI запроса SELECT он должен быть сначала подготовлен, а затем выполнен. Функция DBI::prepare полезна при работе с некоторыми серверами баз данных, позволяющими осуществить операции над подготовленными запросами, прежде чем выполнить их. Для MySQL это означает лишь запоминание запроса до вызова функции DBI:: execute . Результаты работы этой функции посылаются функции add2, как показано ниже: Листинг 5.21. Продолжение скрипта test.pl sub add2 { my $subject = param('subjects'); my $num = param('num'); $name = param('name') if param('name'); my $out = $dbh->prepare("select name from subject where id=$subject"); $out->execute; my ($subname) = $out->fetchrow_array; print header, start_html('title'=>"Создание экзамена по предмету $subname", 'BGCOLOR'=>'white'); print <<END_OF_HTML; <H1> Создание экзамена по предмету $subname</h1> <h2>$name</h2> <P><FORM ACTION="test.pl" METHOD=POST> <INPUT TYPE=HIDDEN NAME="action" VALUE="add3"> <INPUT TYPE=HIDDEN NAME="subjects" VALUE="$subject"> <INPUT TYPE=HIDDEN NAME="num" VALUE="$num"> <INPUT TYPE=HIDDEN NAME="name" VALUE="$name"> Введите количество баллов за каждый правильный ответ. Сумма баллов не обязательно должна равняться 100. <Р> END_OF_HTML for (1.,$num) { print qq%$_: <INPUT NAME="q$_" SIZE=3> %; if (not $_ % 5) { print "<br>\n", } } print <<END_OF_HTML; <P>Введите текст экзамена:<br> <TEXTAREA NAME="test" ROWS=20 COLS=60> </textarea><P> <INPUT TYPE=SUBMIT VALUE="Ввести экзамен "> <INPUT TYPE=RESET> </form></body></html> END_OF_HTML } Эта функция динамически генерирует форму для экзамена, основываясь на параметрах, введенных в предыдущей форме. Пользователь может ввести количество баллов для каждого вопроса экзамена и полный текст самого экзамена. Выходные данные этой функции посылаются завершающей функции add3, как показано ниже: Листинг 5.21. Продолжение скрипта test.pl sub add3 { my $subject = param('subjects'); my $num = param('num'); $name = param('name') if param('name'); my $qname; ($qname = $name) =" s/'/\\'/g; my $q1 = "insert into test (id, name, subject, num) values ("'', $qname', $subject, $num)"; my $in = $dbh->prepare($q1); $in->execute; # Извлечем значение ID , которое MySQL создал для нас my $id = $in->insertid, my $query = "create table t$id (id INT NOT NULL, "; my $def = "insert into t$id values ( 0, "; my $total = 0; my @qs = grep(/"q\d+$/,param); foreach (@qs) { $query = $_ " INT,\n', my $value = 0, $value = param($_) if param($_); $def = '$value, "; $total += $value; } $query = "total INT\n)"; $def = "$total)', my $in2 = $dbh->prepare($query); $in2->execute; my $in3 = $dbh->prepare($def); $in3->execute, open(TEST,">teach/tests/$id") or die('A: $id $' ), print TEST param('test'), \n", close TEST; print header, start_html('title =>'Экзамен создан', ;'BGCOLOR'=>'white'); print <<END_OF_HTML; <Н1>Экзамен создан</H1> <p>Экзамен создан<P> <A HREF='..'>Перейти</а> на домашнюю страницу 'В помощь учителю'.<br> <А HREF='test.pl'>перейти</a> на главную страницу экзаменов.<br> <А HREF= 'test.pl'?action=add'>Добавить</a> следующий экзамен </body></html> END_OF_HTML } MysqlPerl.Монти Видениус, автор MySQL, написал также и интерфейс Perl к MySQL, Mysql.pm. Mysql.pm входит составной частью в пакет msql-mysql-modules Йохена Видмана (Jochen Wiedmann). Чтобы показать некоторые функции Mysql.pm, вернемся к примеру с экзаменами. Займемся таблицей предметов. Ее структура описана выше. Чтобы продемонстрировать, как работает Mysql.pm, мы подробно изучим ту часть subject.pl, которая позволяет пользователю добавлять предметы. Операция «add» (добавление) была так же разбита на две отдельные функции. Первая функция - изменения, выводит форму, позволяющую ввести название предмета и фамилию преподавателя: Листинг 5.22. Скрипт subject.pl #!/usr/bin/perl -w use strict; use CGI qw(:standard); my $output = new CGI; use_named_parameters(1); # Использовать модуль MySQL use MySQL; # используется localhost и открывается база данных 'teach', my $dbh = Mysql->connect(undef,'teach', 'teacher',undef); # Операция добавления распределена между двумя функциями. Add - # выводит пользователю форму шаблона для создания нового предмета, &add if not (param('action')); foreach(param('action')){ /add2/ and do{&add2; last;}; } sub add { print header, start_html('title'=>'Добавить предмет','BGCOLOR'=>'white'); print <<END_OF_HTML; <H1>Добавить предмет</h1> <form METHOD=POST ACTION="subject.pl"> <P>Название предмета:<input TYPE=TEXT size=40 name="name" ><br> Фамилия учителя:&nbsp;&nbsp;&nbsp;<input TYPE=TEXT size=40 name="teacher" ><br><INPUT TYPE=HIDDEN NAME="action" VALUE="add2"> <INPUT TYPE=SUBMIT VALUE="Следующая страница "><INPUT TYPE=RESET> </form><p><A HREF="..">Перейти</a> к домашней странице Помощи учителю. </body></html> END_OF_HTML } Функция проверяет, не имеют ли какие-либо поля предустановленные значения. Это придает функции дополнительную гибкость, позволяя использовать ее как шаблон для классов со значениями по умолчанию, возможно, генерируемыми какой-либо другой CGI-программой. Значения, полученные в первой части процесса добавления, передаются обратно CGI-программе для использования в функции add2. Функция add2 сначала проверяет, существует ли уже предмет. Если существует, то пользователю посылается сообщение об ошибке, и он может ввести другой предмет. Листинг 5.22. Продолжение скрипта students.pl sub add2 { my $name = param('name'); my $query_name = "'".$name."'"; # Строим запрос для проверки существования предмета, # Если введена фамилию учителя, отдельно проверяем фамилию, # поскольку могут быть два курса с одинаковым названием, но # разными учителями, my ($teacher, $query_teacher, $query); $query ="select id, name ";# from subject where name=$query_name"; if (param('teacher')) { $teacher = param('teacher'); $query.=", teacher"; $query_teacher = "'".$teacher."'"; } $query .= " from subject where name=$query_name"; if (param('teacher')) {$query .= " and teacher=$query_teacher";} # Теперь посылаем запрос серверу MySQL. my $out = $dbh->query($query); # Проверяем значение $out->numrows, чтобы узнать, были ли # возвращены какие-либо строки. Если были, то мы выходим с # сообщением, что предмет уже существует if ($out->numrows) { # Печать страницы 'Предмет уже существует'. print header, start_html('title' =>'Предмет уже существует', 'BGCOLOR'=>'white'); print <<END_OF_HTML; <h1>Предмет уже существует</H1><A HREF='..'>Перейти</a> на домашнюю страницу 'В помощь учителю'.<br> <A HREF= 'subject.pl'?action=add'>Добавить</a> следующий предмет </body></html> END_OF_HTML } else { $out = $dbh->query("select * from subject"); my ($id) = $out->fetchrow+1; # Теперь вводим информацию в базу данных, используя # полученное число в качестве ID $query = "INSERT INTO subject (id, name, teacher) VALUES ($id, $query_name, $query_teacher)"; $dbh->query($query); print header, start_html('title' =>'Предмет создан', 'BGCOLOR'=>'white'); print <<END_OF_HTML; <h1>Предмет создан</H1><A HREF='..'>Перейти</a> на домашнюю страницу 'В помощь учителю'.<br> <A HREF= 'subject.pl'?action=add'>Добавить</a> следующий предмет </body></html> END_OF_HTML }



Логические операторы && (AND) и || (OR).

Операторы работы с битами.

'&' - побитное AND
'|' - побитное OR
'^' - побитное XOR
'&&' - если левое выражение возвращает false, правое не выполняется.
'||' - если левое выражение возвращает true, правое не выполняется.

Отличие от подобных операторов в С заключается в том, что в С возвращаемое значение либо 0, либо 1, тогда как в Perl возвращается результат выражения.

Оператор диапазона '..' Результат его работы зависит от контекста. В списковом контексте результат есть список с элементами, первый элемент которого это левое выражение и последнее - правое. Значение каждого элемента внутри списка увеличивается на 1. Данный оператор удобен для небольших циклов, т.к. память отводится для всего списка целиком. Поэтому будьте внимательны и не задавайте слишком большой диапазон.

for $i (1..4)

{ print "$i "; # Результат: 1 2 3 4

}

В скалярном контексте результат - логическое значение. Каждая '..' операция устанавливает свое собственное состояние. Это false до тех пор, пока левый операнд false. Как только он стал true, результат - true до тех пока правый true, после чего опять - false. Если вы не хотите проверять правый операнд, то используйте оператор '...'.

Правый операнд не вычисляется, пока результат false и левый операнд не вычисляется, пока результат true. Приоритетность оператора '..' немного ниже чем '&&' и '||'. Возвращаемое значение если flase - нулевая строка, если true - порядковый номер, начиная с 1. Порядковый номер обнуляется для каждого нового диапазона.

@abc = ('a'..'z'); # Массив малых букв латинского алфавита

@digits = (0..9); # Массив цифр

Условный оператор '?:' Этот оператор работает так же как и в С. Если выражение перед '?' истинно, то выполняется аргумент перед ':' - иначе после ':'.

$i = 1;

$i > 1 ? print "больше" : print "меньше"; #Результат: меньше

Операторы присваивания. '=' - обычный оператор "присвоить" правое значение переменной слева. Вся эта группа операторов подобна операторам С, т.е.

$i += 2; #эквивалентно $i = $i + 2;

Остальные операторы этой группы работают аналогично. Допустимы следующие операторы:

**=, +=, -=, .=, *=, /=, %=, x=, &=, |=, ^=, <<=, >>=, &&=, ||=

Приоритет всей этой группы операторов равен приоритету '='.

Оператор ',' (запятая) В скалярном контексте выполняется левый аргумент, результат игнорируется, затем правый, и его результат есть результат действия оператора. В списковом контексте это разделитель элементов списка, включает указанные элементы в список.

Операторы not, and, or, xor Оператор логическое not (отрицание). - унарный not возвращает противоположное значение, полученное выражением справа. Он эквивалентен '!'.

Оператор логическое and (И). Выполняет логическую конъюнкцию двух выражений. Эквивалентен '&&', но имеет очень низкий приоритет и "краткость" действия, т. е. если левое выражение равно false - правое не выполняется.

Логическое or (ИЛИ). Выполняет логическую дизъюнкцию двух выражений. Эквивалентен '||', но имеет очень низкий приоритет и "краткость" действия, т. е. если левое выражение равно true - левое не выполняется.

Логическое xor (исключающее ИЛИ). Выполняет логическое исключающие или. Всегда выполняются оба правое и левое выражение.

В Perl отсутствуют операторы языка С, такие как:

унарное & - получить адрес. Для этого применяется '\'.
унарный * - переадресация.
(TYPE) - совмещение типов.

Операторы ограничители строк. Обычно ограничителями строк мы считаем литералы, но в Perl это операторы, выполняющие разного рода интерполяцию и поиск по шаблону. Вы можете сами задавать удобные для вас ограничители. В следующей таблице приведен полный перечень вариантов. Фигурные скобки '{}' обозначают любой символ, используемый для ограничителя. В случае использования скобок (круглых '( )', квадратных '[ ]', фигурных '{ }', угловых '< >') в начале ставится открывающаяся скобка, а в конце закрывающая.

По умолчанию Полное Функция Интерполяция
'' q{} Literal нет
"" qq{} Литерал да
`` qx{} Команда да
  qw{} Список слов нет
// m{} Шаблон да
  s{}{} Подстановка да
  tr{}{} Трансляция нет

В строках, допускающих интерполяцию, имена переменных, начинающиеся с символов '$' или '@' - интерполируются, т.е. в строку вставляется значение строки или массива. Данные последовательности символов имеют специальное значение:

\t символ табуляции
\n символ новой строки
\r возврат
\f перевод формата
\v вертикальная табуляция
\b backspace (забой)
\a звонок
\e escape
\034 восьмеричный символ
\x1a шестнадцатеричный символ
\c[ символ управления
\l нижний регистр следующего символа
\u верхний регистр следующего символа
\L нижний регистр для всех символов до \E
\U верхний регистр для всех символов до \E
\E ограничитель смены регистра
\Q отмена действия метасимволов до \E

Шаблоны интерполируются как регулярные выражения. Это выполняется вторым проходом после интерполяции переменных, поэтому в шаблоны можно вставлять переменные. Для отмены интерполяции используйте '\Q'. Если вы применяете вложенные ограничители, то внутренние ограничители работать не будут.

?PATERN? Действие этого оператора аналогично /шаблон/, но выполняется до первого совпадения. Это удобно для поиска наличия какой-нибудь строки в одном или множестве файлов. Это не очень удачный оператор.

m/PATERN/gimosx, /PATERN/gimosx Поиск в строке по патерну (шаблону). В скалярном контексте возвращает логическое значение true (1) или false (''). Если строка не указана с помощью операторов '=~' или '!~', поиск ведется в строке $_. Опции:

g - Глобальный поиск. Поиск всех вхождений.
i - Сравнение не зависит от регистра (верхний или нижний)
m - Строка многострочная.
o - однопроходная компиляция
s - однострочная строка
x - используются расширенные регулярные выражения.

Если '/' - ограничитель, то начальное 'm' можно опустить. С помощью него в качестве ограничителя может быть любой символ кроме пробела.

PATTERN может содержать переменные, которые будут интерполироваться (перекомпилироваться) каждый раз в момент вычисления. Переменные $) и $| не интерполируются. Если вы хотите, что бы такой шаблон интерполировался один раз - добавьте /o. Это необходимо делать в циклах поиска для увеличения быстродействия. Если PATERN - нулевая строка, то используется последнее регулярное выражение.

В скалярном контексте возвращается список, элементы которого - результаты выполнения выражений в скобках патерна ($1, $2, $3...). Обратите внимание, что первый элемент $1.

$a = "/usr/local/perl/perl.bin"; # Анализируемая строка

Цель: Создать массив @dirs с именами директорий.

Решение: Самый простой способ - воспользоваться split('\/'), но мы используем скобки.

@dirs =($a=~ m[/(\w*)/(\w*)/(\w*)/(\w*)]);

Здесь 'm[' - использовать квадратные скобки как ограничители, (\w*)- шаблон алфавитно-цифровой последовательности.

В результате @dirs равен ('usr', 'local', 'perl')

q/строка/, 'строка' Строка литералов. Не интерполируется. Внутри строки разрешается использовать \' или \\ для обозначения символов ' и \ :

print q#Привет.#; # Результат Привет.

print 'O\'K'; # O'K

qq/строка/, "строка" Интерполируемая строка:

$var = 13;

print "\$var = $var"; # Результат: $var = 13

qx/строка/, `строка` Строка интерполируется, а потом выполняется как системная команда:

print `date`; #Результат: Thu Nov 14 13:36:49 MSK 1996

qw/строка/ Возвращает список, элементы которого - слова строки, разделенные пробелами:

print qw/Построимся и спасемся!/; # ('Построимся','и','спасемся!')

s/шаблон/подстрока/egimosx Поиск по шаблону и в случае успеха замена подстрокой. Возвращает количество произведенных подстановок, иначе false (0). Если строка в которой ведется поиск не указана (операторы =~ или != ), то используется переменная $_ . Если в качестве разделителя '/' использовать одинарную кавычку ('), то интерполяции не будет, иначе можно применять переменные в шаблоне или подстроке. Опции:

e - Рассматривать правую часть как выражение.
g - Глобальный поиск.
i - Без различия регистра букв
m - многострочная переменная
o - компилировать шаблон один раз
s - однострочная переменная
x - расширенное регулярное выражение

Разделитель '/' можно заменить на любой алфавитно-цифровой символ кроме пробела:

Листинг 6-3.Регулярные выражения.

$var = "12345"; # исходная строка

$var =~ s/1/0/; print $var; # Заменить '1' на '0'. Результат 02345

$var =~ s(5)(.); print $var; # Заменить '5' на '.' Результат 0234.

Здесь в качестве разделителя применены скобки, поэтому подстрока взята в две скобки.

$var =~ s/\d*/каламбур/; Заменить все цифры. Результат 'каламбур.'

$var =~ s/а/о/g; print $var; # Заменить все 'а' на 'о'.

$var = "12 34"; # Новое значение

$var =~s/(\d\d)\s(\d\d)/$2 $1/; print $var;#Поменять местами числа

tr/таблица1/таблица2/cds, y/таблица1/таблица2/cds Замена всех символов из "таблица1" на соответствующий символ из "таблица2". Результат - количество замен или стираний. Без оператора =~ или != операция выполняется со строкой $_. Для совместимости с программой sed вместо tr можно писать 'y'. Опции:

c - дополнение "таблица1"
d - стереть найденные, но не замененные символы.
s - "сжать" повторяющиеся замененные символы.

Если указана опция /d, таблица2 всегда интерпретируется как положено: если таблица2 короче, чем таблица1, то символ из таблицы1 интерпретируется всегда. Если таблица2 - null, то все символы строки остаются неизменными. Это удобно для подсчета количества символов в строке определенного класса или сжатия повторяющихся символов:

Листинг 5.4.Регулярные выражения.

$s = "hello"; # Исходная строка

$s =~ tr/a-z/A-Z/; # Заменить малые буквы на большие.

print $s; # Результат 'HELLO'

$s = 'Hel....lo';

$s =~ tr/a-zA-z/_/c; # Заменить все не буквы на '_'

print $s; # Результат 'Hel____lo'

$s =~ tr/_/ /s; # Заменить '_' на ' ' и сжать.

print $s; # Результат 'Hel lo'

$s =~ tr/a-zA-Z /a-zA-Z/d; # Удалить все не буквы.

print $s; # Результат 'Hello'

Если один символ несколько раз указан в таблице1, то применяется только первая замена.

Операторы ввода-вывода. В Perl существует несколько операторов ввода-вывода. Первый это скобки из символа '`' - акцента. Строка в этих скобках воспринимается, как системная команда и результат ее действия возвращается как "псевдо" литерал. В скалярном контексте это строка, содержащая весь результат, а в списковом - список, элементы которого - строки результата. Статус выполненной команды хранится в переменной $?.

Следующая команда ввода вывода выглядит как '<файл>'. Вычисление <файл> приводит к чтению строки из файла. Обратите внимание, что 'файл' здесь не имя файла, а указатель файла, который создается функцией open(). В скалярном контексте читается одна строка вместе с символом '\n' - перевода строки, а в списковом - весь файл читается в список, элементы которого суть строки файла. В случае обнаружения конца файла результат оператора не определен и воспринимается как false. Если не указана переменная результата, то по умолчанию это $_. Указатель файла по умолчанию STDIN - стандартный ввод:

while(<>) { print; }; # Прочитать и вывести весь файл STDIN

У оператора '<>' есть одна отличительная особенность. Если в командной строке нет никаких аргументов, то читается стандартный ввод, если есть аргументы, то они считаются именами файлов, которые последовательно читаются.

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

while(<*.pl>) { print;}; # То же что и ls *.pl

@files = <*>; # Массив @files содержит имена файлов в директории

но лучше сделать: @files = glob("*"); т.к. внутри скобок можно использовать переменные.

Слияние констант. Как и С Perl выполняет возможные вычисления в период компиляции. Так подстановка символов после '\', операция конкатенации строк, арифметические выражения, содержащие только одни константы, все это делается в момент компиляции, что существенно увеличивает скорость выполнения программы.

Целочисленная арифметика. По умолчанию Perl выполняет арифметику с плавающей запятой, но если вы укажете:

use integer;

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

no integer;

Встроенные функции.

Встроенные функции используются как термы выражений и подразделяются на две категории: списковые операторы и унарные операторы. Это влияет на их приоритет по отношению к оператору ',' - запятая. Списковые операторы могут иметь множество (список) аргументов, а унарные только один. Таким образом, запятая завершает аргументы унарного оператора и разделяет аргументы спискового. Аргумент унарного оператора воспринимается обычно в скалярном контексте, а спискового - как в скалярном, так и списковом, причем скалярные аргументы идут первыми. Аргументы функций можно заключать в круглые скобки и таким образом обозначать, что "это функция" и приоритет не имеет значения, иначе это списковый или унарный оператор с определенным фиксированным приоритетом. Пробел после имени функции и скобкой значения не имеет:

print 1 + 2 + 3; # результат 6

print(1+2)+3; # результат 3

print (1+2)+3; # опять 3

print (1+2+3); # 6

Если функция возвращает результат, как в скалярном, так и в списковом контексте, то код выхода по ошибке - скаляр с неопределенным значением или пустой список.

Запомните правило: Не существует общего правила преобразования списка в скаляр!

Перечень встроенных функций (без описания системных вызовов) приведен в приложении.

Подпрограммы.

Для применения подпрограммы ее необходимо определить либо в текущем модуле (файле), либо во внешнем модуле (файле). Подпрограммы определяются и декларируются следующим образом:

· sub имя; - Только декларация. Определение ниже.

· sub имя (прототипы); - То же но с декларацией параметров.

· sub имя блок; - Декларация и определение.

· sub имя (прототипы) блок; - То же, но с параметрами.

Для определения динамической анонимной подпрограммы можно указать:

· $переменная = sub блок;

Для импортирования подпрограмм из других модулей используйте:

· use модуль qw(подпрограмма1 подпрограмма2 );

Вызов подпрограммы:

имя(список параметров); # символ '&' можно не указывать.

имя список; # Если подпрограмма уже декларирована.

&имя; # Параметры в @_

Все параметры передаются подпрограмме как массив @_. Соответственно $_[0] - первый параметр, $_[1] - второй и т.д. Массив @_ - локальный, но он содержит адреса параметров, поэтому можно изменять значение параметров. Возвращаемое значение подпрограммы - результат последнего оператора. Это может быть как скаляр, так и массив. Можно принудительно возвращать результат, используя функцию return().

Подпрограмму можно вызвать, используя префикс '&' перед именем подпрограммы. Если подпрограмма предварительно продекларирована, то префикс и скобки можно опустить.

Private переменные. Для применения переменных доступных только внутри блока или подпрограммы необходимо определить их с помощью функции my(список). Если переменная одна, то скобки можно опустить. my() декларирует private переменные в пределах текущей подпрограммы, блока, функции eval() или do/require/use файлов. Private переменные аналогичны auto переменным в С:

Листинг 5.5.Подпрограммы.

# Программа вычисления факториала.

print fact(3); # вычислить факториал 3*2*1

sub fact # Определяем подпрограмму.

{ my $m; # private переменная но не local !

$m = $_[0];

return 1 if $m <= 1;

return($m * fact($m -1));

}

Можно указывать начальные значения private переменных как:

· my(список) = выражение;

Так для вышеприведенного примера лучше было написать:

· my($m) = $_[0];

Переменные типа local. В общем лучше использовать private переменные, т. к. это надежней и быстрее. private переменные обеспечивают лексическую область применения (видимости), а local - динамическую. Обычно это переменные форматов, значение которых должно быть видимо из вызываемых подпрограмм. Применение функции local() нецелесообразно в циклах, так как она вызывается каждый раз и таким образом заметно увеличивает время выполнения цикла.

Прототипы (prototypes). Для краткого описания типа передаваемых подпрограмме параметров можно применять прототипы. В Perl существуют следующие прототипы:

Декларация Пример вызова
sub mylink($$) mylink $old, $new
sub myvec($$$) myvec $var, $offset, 1
sub myindex($$;$) myindex &getstring, "substr"
sub myreverse(@) myreverse $a, $b, $c
sub myjoin($@) myjoin ":",$a,$b,$c
sub mypop(\@) mypop @array
sub mysplice(\@$$@) mysplice @array, @array, 0, @pushme
sub mykeys(\%) mykeys %{$hashref}
sub myopen(*;$) myopen HANDLE, $name
sub mypipe(**) mypipe READHANDLE, WRITEHANDLE
sub mygrep(&@) mygrep { /foo/ } $a, $b, $c
sub myrand($) myrand 42
sub mytime() mytime

Здесь:

· \'символ' - параметр с типом 'символ'

· '@' или '%' - все оставшиеся параметры как список

· '$' - скаляр

· '&' - безымянная подпрограмма

· '*' - ссылка на таблицу имен

· ';' - разграничитель обязательных и не обязательных параметров.

Ссылка как параметр. Иногда нужно в качестве параметра передать подпрограмме не значение элемента массива, а ссылку на него, чтобы подпрограмма могла изменить значение элемента. Для этого в Perl к имени переменной добавляется символ '*' Подобное выражение называют 'type glob' так же как в Unix символом '*' обозначают "все возможные значения". Поэтому '*' для массива означает "все элементы массива". Для скаляров употреблять '*' не имеет смысла, т.к. они и так передаются ссылкой и вы можете изменять значение параметра, изменяя, например, переменную $_[0].

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

· use subs 'функция1', 'функция2' ....;

и далее в модуле определить сами функции.

Автозагрузка. Если вы попытаетесь вызвать несуществующую функцию, то Perl выдаст сообщение об ошибке. Но если вы определите подпрограмму с именем 'AUTOLOAD', то она будет вызвана с теми же параметрами, а переменная $AUTOLOAD будет содержать имя несуществующей подпрограммы. Данный механизм очень удобен для средств отладки.

Модули (packages).

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

· packages имя_модуля;

Конец модуля это конец блока или файла. Головной модуль имеет по умолчанию имя main. На имя внутри модуля можно ссылаться, добавляя '::' после имени модуля:

$main::var1 - переменная в головном модуле.

::var1 - то же самое. Имя main можно опускать.

$модуль1::var1 - переменная в модуле 'модуль1'

$модуль1::модуль2::var1 - Модуль2 содержится в модуле 1.

Только идентификаторы, начинающиеся с буквы или символа '_', хранятся в пространстве имен текущего модуля. Остальные хранятся в пространстве головного модуля main. Кроме этого имена STDIN, STDOUT, STDERR, ARGV, ARGVOUT, ENV, INC и SIG так же хранятся в головном модуле.

Таблицы имен. Все имена модуля хранятся в ассоциативном массиве (хеше) с именем модуля, к которому добавлены символы "::". Таким образом, имена головного модуля хранятся в %main:: , модуля 'mod1' в %mod1:: и т.д. Выражение вида *имя указывает значение элемента хеша 'имя', это удобно для определения констант.

*pi = \3.14159;

Здесь переменная $pi - это константа пи, которую уже нельзя изменить.

Конструкторы и деструкторы. Конструктор - это подпрограмма, которая выполняется в момент создания объекта, а деструктор - удаления объекта. Для модуля это подпрограммы с именами BEGIN и END. При определении этих подпрограмм слово sub можно опускать.

Конструктор BEGIN выполняется сразу, как только возможно, т.е. как только он определен, даже не завершая дальнейший разбор программы. Можно указать несколько блоков BEGIN. Они будут выполняться один за другим в порядке определения.

Деструктор END выполняется последним как только возможно, т.е. при завершении работы интерпретатора. Можно указать несколько блоков END, при этом они будут выполняться в обратном определению порядке.

Классы. В Perl нет специального синтаксиса для классов. Но функционально полноценными классами могут быть модули. При этом подпрограммы модуля становятся методами, а с помощью массива @ISA можно реализовать механизм наследования в классах. Более подробно классы рассматривать не будем.

Создание библиотеки. Если вы хотите создать модуль отдельным файлом и использовать как библиотеку подпрограмм, при этом вызывать подпрограммы библиотеки, не указывая имени модуля, вам необходимо оформить модуль следующим образом:

package имя_модуля; #Такое же, как имя файла без расширения '.pm'

require Exporter; # Обязательная строка для экспорта имен

@ISA = qw(Exporter); # -//-

@EXPORT = qw(func1 func2) #Перечисляем имена функций. Нет запятой!

@EXPORT_OK = qw($переменная @массив); #Указать публичные #переменные, массивы и т.д. если необходимо

{ # Начало блока модуля

.....

sub func1

........

sub func2

........

1;

}

Данный файл с расширением ".pm" должен храниться в одной из библиотечных директорий Perl. Они перечислены в массиве @INC, одна из них обычно "/usr/local/lib/perl/".

В головной программе вы указываете:

· use имя_модуля;

и вам становятся доступны имена подпрограмм данного модуля.

Perl библиотеки. Стандартный набор библиотек обычно поставляется с дистрибутивом Perl, они разделяются на pragma библиотеки (работают как директивы компилятору) и стандартные библиотеки.

Pragma библиотеки. Данные библиотеки используют как:

· use имя;

когда хотят включить действие и

· no имя;

когда хотят выключить.

В стандартный набор входят следующие pragma:

diagnostics- Включить режим расширенной диагностики.

integer- Использовать целочисленную арифметику.

less- Режим минимальной загрузки компилятора.

overload- Режим переопределения операторов.

sigtrap- Режим слежения за прерываниями.

strict- Режим ограниченного использования "опасных" операторов.

subs- Режим обязательного декларирования подпрограмм.

Стандартные библиотеки. С точки зрения web-программирования наибольший интерес представляют библиотеки для работы с тегами HTML и для доступа к базам данных. Их мы рассмотрим чуть позднее и более подробно. Подробное описание каждой библиотеки записано в самом файле.

CPAN. Программисты всего мира, работающие с Perl, создали общедоступную библиотеку модулей CPAN . Она доступна через Интернет и содержит огромное количество различных по назначению модулей. К ним относятся документаторы, системные интерфейсы, интерфейсы работы с базами данных, работа в сети, с файлами, Интернет-броузеры, системы поиска, огромное количество CGI скриптов для Web серверов и многое-многое другое.

Форматы.В Perl реализован удобный метод создания форматированных отчетов. С помощью оператора format вы описываете заголовки, размеры полей, указываете положение данных на листе в удобной текстовой форме. Затем выполняете команду write(файл), которая выводит отформатированные данные в указанный файл.

Оператор format имеет следующий синтаксис:

format имя =

FORMLIST

.

Обратите внимание на то, что описание формата идет после строки format и заканчивается символом '.' в начале строки. Здесь 'имя' - это имя формата, такое же как и имя указателя выходного файла. Если 'имя' отсутствует то значение по умолчанию - STDOUT.

FORMLIST - это строки формата. Они бывают трех типов:

1. Комментарий. Строка начинается символом '#'.

2. Описатель полей данных (picture).

3. Строка аргументов используемых описателем.

Описатель - это строка, которая выводится в виде "как есть" за исключением специально обозначенных форматов полей данных. Каждое поле начинается либо символом '@', либо '^'. В описательной строке указывается только положение и вид выводимых данных, но не имена полей и переменных. Для этого предназначена следующая строка аргументов которая следует всегда после описателя и содержит имена переменных или целые выражения в порядке указанном описателем. Размер и вид поля в описателе обозначается символами:

"<<<<" - выравнить значение по правому краю.
">>>>" - -//- по левому.
"

Что такое РНР?

РНР — это серверный язык создания сценариев (или стороны сервера), разработанный специально для Web. В HTML-страницу можно внедрить код РНР, который будет выполняться при каждом ее посещении. Код РНР интерпретируется Web-сервером и генерирует HTML или иной вывод, наблюдаемый посетителем страницы.

Разработка РНР была начата в 1994 г. и вначале выполнялась одним человеком, Расмусом Лердорфом (Rasmus Lerdorf). Этот язык был принят рядом талантливых людей и претерпел три основных редакции, пока не стал широко используемым и зрелым продуктом, с которым мы имеем дело сегодня. К январю 2001 г. он использовался почти в пяти миллионах доменов во всем мире и их число продолжает быстро расти. Количество доменов, в которых в настоящее время используется РНР, можно выяснить на странице http://www.php.net/ usage.php. РНР — это продукт с открытым исходным кодом (Open Source). У пользователя имеется доступ к исходному коду. Его можно использовать, изменять и свободно распространять другим пользователям или организациям.

Первоначально РНР являлось сокращением от Personal Home Page (Персональная начальная страница), но затем это название было изменено в соответствии с рекурсивным соглашением по наименованию GNU (GNU = Gnu's Not Unix) и теперь означает РНР Hypertext Preprocessor (Препроцессор гипертекста РНР).

В настоящее время основной версией РНР является четвертая. Адрес начальной страницы для РНР — http://www.php.net

Что нового в РНР 4?Имеется ряд важных усовершенствований 4 версии:

· РНР 4 работает значительно быстрее предшествующих версий, поскольку в нем используется новый механизм Zend Engine. Если требуется еще более высокая производительность, по адресу http://www.zend.com можно получить модули Zend Optimizer, Zend Cache или Zend Compiler.

· РНР всегда можно было использовать как эффективный модуль сервера Apache. С появлением новой версии РНР можно устанавливать и в виде модуля ISAPI для Internet Information Server компании Microsoft.

· Теперь поддержка сеансов является встроенной. В предшествующих версиях для управления сеансом или создания собственного сеанса требовалось устанавливать дополнительный модуль PHPLib.

Некоторые преимущества РНР.К числу конкурентов РНР относятся Perl, Active Server Pages (ASP) от Microsoft, Java Server Pages (JSP) и Allaire Cold Fusion.

РНР обладает множеством преимуществ по сравнению с этими продуктами:

• Высокая производительность

• Наличие интерфейсов ко многим различным системам баз данных

• Встроенные библиотеки для выполнения многих общих задач, связанных с Web

• Низкая стоимость

• Простота изучения и использования

• Переместимость

• Доступность исходного кода

Производительность.РНР исключительно эффективен. Используя единственный недорогой сервер, можно обслуживать миллионы обращений в день. Результаты тестирования, опубликованные компанией Zend Technologies (http://www.zend.com), подтверждают более высокую производительность РНР по сравнению с конкурирующими продуктами.

Интеграция с базами данных.РНР обладает встроенной связностью со многими системами баз данных. В дополнение к MySQL, в числе прочих можно непосредственно подключаться к базам данных PostgreSQL, mSQL, Oracle, dbm, Hyperware, Informix, InterBase и Sybase.

Используя Open Database Connectivity Standard (Стандарт открытого интерфейса связи с базами данных, ODBC), можно подключаться к любой базе данных, для которых существует ODBC-драйвер. Это распространяется на продукты Microsoft и многих других компаний.

Встроенные библиотеки.Поскольку РНР был разработан для использования в Web, он имеет множество строенных функций для выполнения широкого разнообразия полезных, связанных с Web, задач. С его помощью можно "на лету" генерировать GIF-изображения, подключаться к другим сетевым службам, отправлять сообщения электронной почты, рабо­тать с cookie-наборам и генерировать PDF-документы посредством нескольких строк кода.

Стоимость.Пакет РНР является бесплатным. Наиболее новую версию можно в любой момент совершенно бесплатно выгрузить из http://www.php.net.

Изучение РНР.Синтаксис РНР основывается на других языках программирования, в первую очередь на С и Perl, Если вы уже знакомы с С, Perl или С-подобным языком, таким как C++ или Java, то почти сразу сможете эффективно использовать РНР.

Переносимость.Пакет РНР можно использовать под управлением многих различных операционных систем. Код РНР можно создавать в среде таких бесплатных Unix-подобных операционных систем, как Linux и FreeBSD, коммерческих версий Unix типа Solaris и IRIX или различных версий Microsoft Windows. Как правило, программы будут работать без каких-либо изменений в различных средах с установленным РНР.

Исходный код.Пользователь имеет доступ к исходному коду РНР. В отличие от коммерческих закрытых программных продуктов, если нужно что-либо изменить или добавить в этом языке, то это всегда можно сделать. Не следует дожидаться, пока фирма-изготовитель выпустит правки (патчи). Нет необходимости беспокоиться о том, что изготовитель собирается покинуть рынок или перестанет поддерживать продукт.

Синтаксис и грамматика. Синтаксис PHP заимствован непосредственно из C. Java и Perl также повлияли на синтаксис данного языка.

Переход из HTML.Есть три способа выхода из HTML и перехода в "режим PHP кода":

1. <? echo("простейший способ, инструкция обработки SGML\n"); ?>

2. <?php echo("при работе с XML документами делайте так\n"); ?>

3. <script language="php">

echo ("некоторые редакторы (подобные FrontPage) не любят обрабатывающие инструкции");

</script>;

4. <% echo("От PHP 3.0.4 можно факультативно применять ASP-тэги"); %>

Разделение инструкций.Инструкции (утверждения) разделяются также как в C или Perl - точкой с запятой. Закрывающий тэг (?>) тоже подразумевает конец утверждения, поэтому следующие записи эквивалентны:

<php

echo "Это тест";

?>

<php echo "Это тест" ?>

Типы переменных.PHP поддерживает переменные следующих типов:

· integer - целое

· double - число с дробной частью

· string - строковая переменная

· array - массив

· object - объектная переменная

· pdfdoc - PDF-документ (только при наличии поддержки PDF)

· pdfinfo - PDF-инфо (только при наличии поддержки PDF)

Тип переменной обычно не устанавливается программистом; вместо этого, он определяется PHP во время выполнения программы, в зависимости от контекста, в котором она используется. Если вам нравится указывать тип переменной непосредственно, используйте для этого инструкцию cast либо функцию settype(), но учтите, что переменная может вести себя по-разному, в зависимости от того, какой тип определен для нее в данное время.

Инициализация переменной.Для инициализации переменной в PHP вы просто присваиваете ей значение. Для большинства переменных это именно так; для массивов и объектных переменных, однако, может использоваться несколько иной механизм.

Инициализация массивов.Массив может инициализироваться одним из двух способов: последовательным присвоением значений, или посредством конструкции array().

При последовательном добавлении значений в массив вы просто записываете значения элементов массива, используя пустой индекс. Каждое последующее значение будет добавляться в качестве последнего элемента массива.

$names[] = "Jill"; // $names[0] = "Jill"

$names[] = "Jack"; // $names[1] = "Jack"

Как в C и Perl, элементы массива нумеруются, начиная с 0, а не с 1.

Инициализация объектов.Для инициализации объектной переменной используйте новое предписание для сопоставления данного объекта объектной переменной.

class foo {

function do_foo () { echo "Doing foo."; }

}

$bar = new foo;

$bar -> do_foo ();

Область переменной.Областью переменной является контекст, внутри которого она определена. Обычно все переменные PHP имеют одну область. Однако, внутри функций определенных пользователем, представлена локальная область функции. Любая переменная, определенная внутри функции, по умолчанию ограничена локальной областью функции. Например:

$a = 1; /* глобальная область */

Function Test () {

echo $a; /* ссылка на переменную локальной области */

}

Test ();

Этот скрипт не выдаст что-либо на выходе, поскольку инструкция echo относится к локальной версии переменной $a, значение которой присваивается не внутри этой области. Вы можете заметить, что здесь имеется некоторое отличие от языка C, в том, что глобальные переменные в C автоматически действуют и внутри функций, если только они не переписываются локальными определениями. Это может вызвать некоторые проблемы, т.к. по неосторожности можно изменить глобальную переменную. В PHP глобальные переменные должны быть продекларированы глобально внутри функции, если предполагается их использование в данной функции. Например:

$a = 1;

$b = 2;

Function Sum () {

global $a, $b;

$b = $a + $b;

}

Sum ();

echo $b;

Этот скрипт выдаст значение "3". Поскольку $a и $b декларируются глобально внутри функции, ссылки на данные переменные трактуются как ссылки на их глобальные версии.

Вторым способом доступа к переменным из глобальной области является использование специального определяемого PHP массива $GLOBALS. При этом предыдущий пример может быть записан как:

$a = 1; $b = 2;

Function Sum () { $GLOBALS["b"] = $GLOBALS["a"] + $GLOBALS["b"]; }

Sum ();

echo $b;

Массив $GLOBALS является ассоциативным, в котором имя глобальной переменной является ключом, а значение этой переменной является значением элемента массива.

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

Function Test () {

$a = 0;

echo $a;

$a++;

}

Эта функция совершенно бесполезна практически, поскольку каждый раз при ее вызове она устанавливает $a в 0 и выводит "0". Выражение $a++ так же бесполезно, поскольку при выходе из функции переменная $a исчезает. Для придания дееспособности функции подсчета переменная $a декларируется как статическая:

Function Test () {

static $a = 0;

echo $a;

$a++;

}

Теперь при вызове функции Test() она будет выводить значение $a и увеличивать его.

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

Function Test () {

static $count = 0;

$count++;

echo $count;

if ($count < 10) {

Test ();

}

$count--;

}

Изменяемые переменные.Иногда бывает удобно давать переменным изменяемые имена. Такие имена могут изменяться динамически. Обычная переменная устанавливается так:

$a = "hello";

Изменяемая переменная берет некое значение и обрабатывает его как имя переменной. В приведенном выше примере значение hello может быть использовано как имя переменной, посредством применения двух записанных подряд знаков доллара, т.е.:

$$a = "world";

С этой точки зрения, две переменных определены и сохранены в символьном дереве PHP: $a с содержимым "hello" и $hello с содержимым "world". Так, инструкция:

echo "$a ${$a}";

осуществляет то же самое, что и инструкция:

echo "$a $hello";

а именно, обе они выводят: hello world.

Чтобы использовать изменяемые переменные с массивами, решите проблему неоднозначности. Это означает, что если вы пишете $$a[1], то синтаксическому анализатору необходимо знать, имеете ли вы в виду использовать $a[1] как переменную, или вы предполагаете $$a как переменную, а [1] как индекс этой переменной. Синтаксис для разрешения неоднозначности такой: ${$a[1]} для первого случая и ${$a}[1] для второго.

Переменные вне PHP. HTML Формы (GET и POST)

Когда программой-обработчиком формы является PHP-скрипт, переменные этой формы автоматически доступны для данного скрипта PHP. Например, рассмотрим следующую форму:

<form action="foo.php" method="post">

Name: <input type="text" name="name"><br>

<input type="submit">

</form>

При активизации формы PHP создаст переменную $name, значением которой будет то содержимое, которое было введено в поле Name: данной формы.

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

<form action="array.php" method="post">

Name: <input type="text" name="personal[name]"><br>

Email: <input type="text" name="personal[email]"><br>

Beer: <br>

<select multiple name="beer[]">

<option value="warthog">Warthog

<option value="guinness">Guinness

</select>

<input type="submit">

</form>

Если PHP-атрибут track_vars включен, через установку конфигурации track_vars или директивой <?php_track_vars?>, тогда переменные, активизированные посредством методов POST или GET, будут также находиться в глобальных ассоциативных массивах $HTTP_POST_VARS и $HTTP_GET_VARS соответственно.

Имена переменных РИСУНКА АКТИВИЗАЦИИ.При активизации (запуске) формы можно использовать рисунок (изображение) вместо стандартной кнопки запуска:

<input type=image src="image.gif" name="sub">

Когда пользователь нажимает кнопку мыши где-либо над таким рисунком, сопровождающая форма передается на сервер с двумя дополнительными переменными, sub_x и sub_y. Они содержат координаты места нажатия кнопки мыши пользователем внутри данного рисунка. Можно отметить, что практически, реальные имена переменных, передаваемые браузером, содержат точку вместо символа подчеркивания, но PHP конвертирует точку в элемент подчеркивания (underscore) автоматически.

Переменные окружения.PHP автоматически создает переменные окружения, как и обычные переменные.

echo $HOME; /* Показывает переменную HOME, если она установлена.*/

Хотя при поступлении информации механизмы GET, POST и Cookie также автоматически создают переменные PHP, иногда лучше явным образом прочитать переменную окружения, для того чтобы быть уверенным в получении ее правильной версии. Для этого может использоваться функция getenv(). Для установки значения переменной окружения пользуйтесь функцией putenv().

Изменение типа.PHP не требует явного определения типа при объявлении переменной, тип переменной определяется по контексту в котором она используется. То есть, если вы присваиваете строковое значение переменной var, var становится строкой. Если затем присвоить переменной var значение целого (числа), то она станет целым.

Примером автоматического преобразования типа в PHP может служить оператор сложения '+'. Если какой-либо из операндов является числом с дробной частью (тип double), то затем все операнды оцениваются как double и результат будет иметь тип double. Иначе, эти опе­ранды будут интерпретированы как целые (integers) и результат будет так же иметь тип integer. Отметим, что при этом НЕ меняются типы операндов, меняется только их оценка.

$foo = "0"; // $foo является строкой (ASCII 48)

$foo++; // $foo является строкой "1" (ASCII 49)

$foo += 1; // $foo сейчас является целым (2)

$foo = $foo + 1.3; // $foo сейчас имеет тип double (3.3)

$foo = 5 + "10 Little Piggies"; // $foo является целым (15)

$foo = 5 + "10 Small Pigs"; // $foo является целым (15)

Если вы желаете изменить тип переменной, используйте settype().

Определение типов переменных.Поскольку PHP определяет типы переменных и преобразует их (в общем) по мере необходимости, не всегда очевидно какой тип данная переменная имеет в какой-то отдельный момент. Поэтому PHP включает несколько функций, которые позволяют определить текущий тип переменной. Это функции gettype(), is_long(), is_double(), is_string(), is_array(), и is_object().

Приведение типа.Приведение типа работает в PHP во многом так же как в C: название требуемого типа записывается в круглых скобках перед переменной, которая должна быть приведена к данному типу.

$foo = 10; // $foo is an integer

$bar = (double) $foo; // $bar is a double

Допускается следующее приведение типов:

· (int), (integer) - приведение к целому

· (real), (double), (float) - приведение к типу double

· (string) - приведение к строке

· (array) - приведение к массиву

· (object) - приведение к объектной переменной

Заметим, что табуляция и пробелы допускаются внутри круглых скобок, поэтому следующее функционально эквивалентно:

$foo = (int) $bar;

$foo = ( int ) $bar;

Преобразование строк.Когда строковая переменная оценивается как числовая, результирующее значение и тип переменной определяются следующим образом.

Переменная string будет оценена как double, если она содержит любой из символов '.', 'e', или 'E'. Иначе она будет оценена как integer.

Данное значение задается начальной частью строковой переменной. Если строка начинается с допустимых цифровых данных, то это значение и будет использоваться. Иначе, будет значение 0 (ноль). Допустимые цифровые данные - это конструкция из факультативного символа, следующего за одной или несколькими цифрами (содержащими факультативно десятичную точку), обозначающего экспоненту. Экспонента может обозначаться символом 'e' или 'E', который может следовать за одной или несколькими цифрами.

$foo = 1 + "10.5"; // $foo тип double (11.5)

$foo = 1 + "-1.3e3"; // $foo тип double (-1299)

$foo = 1 + "bob-1.3e3"; // $foo тип integer (1)

$foo = 1 + "bob3"; // $foo тип integer (1)

$foo = 1 + "10 Small Pigs"; // $foo тип integer (11)

$foo = 1 + "10 Little Piggies"; // $foo тип integer (11);

Манипуляции с массивом.PHP поддерживает как скалярные, так и ассоциативные массивы. Фактически, между ними нет разницы. Вы можете создать массив, используя функции list() или array(), или можно явно задать значение каждого элемента массива.

$a[0] = "abc";

$a[1] = "def";

$b["foo"] = 13;

Можно также создать массив просто добавляя в него значения.

$a[] = "hello"; // $a[2] == "hello"

$a[] = "world"; // $a[3] == "world"

Массив может сортироваться функциями asort(), arsort(), ksort(), rsort(), sort(), uasort(), usort(), и uksort() в зависимости от типа желаемой сортировки. Подсчет количества элементов массива осуществляется функцией count(). Перемещаться по массиву позволяют функции next() и prev(). Другим типовым способом перемещения по массиву является использование функции each().

Элементы языка.

Любой скрипт PHP состоит из последовательности операторов. Оператор может быть присваиванием, вызовом функции, циклом, условным выражением или пустым выражением (ничего не делающим). Операторы обычно заканчиваются точкой с запятой. Также операторы могут быть объединены в группу заключением группы операторов в фигурные скобки. Группа операторов также является оператором.

Константа.PHP определяет несколько констант и предоставляет механизм для определения Ваших констант. Константы похожи на переменные, но они имеют иной синтаксис.

Предопределенные константы - это __FILE__ and __LINE__, которые соответствуют имени файла и номеру строки, которая выполняется в настоящий момент.

<?php

function report_error($file, $line, $message) {

echo "An error occured in $file on line $line: $message.";}

report_error(__FILE__,__LINE__, "Something went wrong!");

?>

Можно определить дополнительные константы с помощью функций define() и undefine().

<?php

define("CONSTANT", "Hello world.");

echo CONSTANT; // outputs "Hello world."

undefine ("CONSTANT");

?>

Выражения.Выражения - это краеугольный камень PHP. В PHP почти всё является выражениями. Простейший и наиболее точный способ определить выражение - это "что-то, имеющее значение". Простейший пример, приходящий на ум - это константы и переменные. Когда вы печатаете "$a = 5", вы присваиваете значение '5' переменной $a.

После этого присваивания вы считаете значением $a 5, также, если вы напишете $b = $a, вы будете ожидать того же как, если бы вы написали $b = 5. Другими словами, $a это также выражение со значением 5. Запись типа '$b = ($a = 5)' похожа на запись'$a = 5; $b = 5;' (точка с запятой отмечает конец выражения). Так как присваивания рассматриваются справа налево, вы также можете написать '$b = $a = 5'.

Более сложные примеры выражений - это функции:

function foo () {

return 5;

}

Функции - это выражения с тем значением, которое они возвращают. Так как foo() возвращает 5, значение выражение 'foo()' - 5.

PHP поддерживает 3 скалярных типа значений: целое, число с плавающей точкой и строки (скалярные выражения вы не можете "разбить" на более маленькие части, как, к примеру, массивы). PHP поддерживает 2 составных (нескалярных) типа: массивы и объекты. Каждое из таких значений может быть присвоено переменной или возвращено функцией.

PHP это язык, ориентированный на выражения, практически всё является выражениями.

Другой хороший пример выражения это префиксное и постфиксное увеличение и уменьшение. Пользователи С и многих других языков могут быть знакомы с записями variable++ and variable--. Это операторы увеличения и уменьшения. В PHP, подобно C, есть 2 типа инкремента - префиксный и постфиксный. Префиксное увеличение, которое записывается как '++$variable', приравнивается увеличенной переменной (PHP увеличивает переменную до того, как прочитать её значение).

Очень распространённый тип выражений - это выражения сравнения. Эти выражения имеют значение 0 или 1 (означает ложь или истину соответственно). PHP поддерживает > (больше, чем), >= ( больше или равно), = (равно), < (меньше, чем) и <= (меньше или равно). Эти выражения в основном используются внутри условий, например оператора IF.

Последний пример выражений, с которыми мы разберёмся, это совмещённые выражения оператор-присваивание. В PHP, также как и в ряде других языков типа C, вы можете писать '$a+=3'. Значение '$a+=3' как и значение обычного присваивания - это присвоенное значение. Любой бинарный оператор может быть записан таким методом, например : '$a–=5' (вычесть 5 из значения $a), '$b*=7' (умножиить значение $a на 7) и так далее.

Есть ещё условный оператор с тремя операндами: $first ? $second : $third. Если значение первого выражения истинно (не равно 0), то исполняется второе выражение и это является результатом данного условного выражения. Иначе исполняется третий оператор.

Этот пример должен помочь Вам лучше понять выражения:

function double($i) /* функция удваивания переменной */

{ return $i*2; }

$b = $a = 5; /* присваиваем значения переменым $a и $b */

$c = $a++; /* постфиксное увеличение, присваиваем $c начальное значение $a (5)*/

$e = $d = ++$b; /* префиксное увеличение, $d и $e равны увеличенному значение $b */

$f = double($d++); /* $f = удвоенное значение $d до его увеличения*/

$g = double(++$e); /* $g = удвоенное значение $e после его увеличения */

$h = $g += 10; /* увеличить значение $g на 10, присвоить это значение переменной $h */

Не каждое выражения является оператором. Оператор имеет форму 'выражение' ';', то есть выражение, за которым следует точка с запятой. В '$b=$a=5;' $a=5 это правильное выражение, но оно не является оператором. А вот '$b=$a=5;' является оператором.

Ещё одна вещь, которую нужно упомянуть - это логические значения выражений. Во многих случаях, в основном в условных операторах и операторах циклов, вы не заинтересованы в конкретных значениях выражений, а только являются ли их значения TRUE или FALSE (в PHP нет специального типа boolean). Логические значения вычисляются примерно так же, как я в языке Perl. Любое не нулевое целое значение - это TRUE, ноль - это FALSE. Обратите внимание на то, что отрицательные значения - это не ноль и поэтому они считаются равными TRUE. Пустая строка и строка '0' это FALSE; все остальные строки - TRUE. И насчёт составных типов (массивы и объекты) - если значение такого типа не содержит элементов, то оно считается равным FALSE; иначе подразумевается TRUE.

Далее мы будем писать 'expr' для обозначения любого правильного выражения PHP.

IF.Возможности PHP по использованию выражения IF похожи на C:

if (expr) statement

Вычисляется логический результат "expr" . Если expr равно TRUE, то PHP выполнит "statement", а если FALSE - проигнорирует.

Следующий пример выведет фразу 'a is bigger than b' если $a больше $b:

if ($a > $b) print "a is bigger than b";

Зачастую Вам требуется исполнить больше чем одно выражение по условию. Конечно, не надо окружать каждое выражение конструкцией IF. Вместо этого вы можете сгруппировать несколько выражений в блок выражений. К примеру, следующий код не только выведет фразу, но и присвоит значение $a переменной $b:

if ($a > $b) { print "a is bigger than b"; $b = $a; }

Выражение IF может иметь неограниченную степень вложенности в другие выражения IF, что позволяет Вам использовать выполнение по условию различных частей программы.

ELSE.Зачастую Вам требуется исполнить одно выражение, если соблюдается какое-либо условие и другое выражение в противном случае. Вот для этого применяется ELSE. ELSE расширяет возможности IF по части обработки вариантов выражения, когда оно равно FALSE. Данный пример выведет фразу 'a is bigger than b' если $a больше $b, и 'a is NOT bigger than b' в противном случае:

if ($a > $b) { print "a is bigger than b"; }

else { print "a is NOT bigger than b"; }

Выражение ELSE выполняется только если выражение IF равно FALSE, а если есть конструкции ELSEIF - то если и они также равны FALSE (см. ниже).

ELSEIF.Является комбинацией IF и ELSE. ELSEIF, как и ELSE позволяет выполнить выражение, если значение IF равно FALSE, но в отличие от ELSE, оно выполнится только если выражение ELSEIF равно TRUE. К примеру, следующий код выведет 'a is bigger than b' если $a>$b, 'a is equal to b' если $a==$b, и 'a is smaller than b' если$a<$b:

if ($a > $b) { print "a is bigger than b";}

elseif ($a == $b) { print "a is equal to b";}

else { print "a is smaller than b"; }

Внутри одного выражения IF может быть несколько ELSEIF. Первое выражение ELSEIF (если таковые есть), которое будет равно TRUE, будет выполнено. В PHP вы можете написать 'else if' (два слова), что будет значить то же самое, что и 'elseif' (одно слово).

Выражение ELSEIF будет выполнено, только если выражение IF и все предыдущие ELSEIF равно FALSE, а данный ELSEIF равен TRUE.

Иной синтаксис для оператора IF: IF(): ... ENDIF;PHP предлагает иной путь для группирования операторов с оператором IF. Наиболее часто это используется, когда вы внедряете блоки HTML внутрь оператора IF, но вообще может использоваться где угодно. Вместо использования фигурных скобок за "IF(выражение)" должно следовать двоеточие, одно или несколько выражений и завершающий ENDIF. Рассмотрите следующий пример:

<?php if ($a==5): ?> A = 5 <?php endif; ?>

В этом примере блок "A = 5" внедрЈн внутрь выражения IF, используемого альтернативным способом. Блок HTML будет виден, только если $a равно 5.

Этот альтернативный синтаксис применим и к ELSE и ELSEIF (expr) .Вот пример подобной структуры :

if ($a == 5): print "a equals 5"; print "...";

elseif ($a == 6): print "a equals 6"; print "!!!";

else: print "a is neither 5 nor 6";

endif;

WHILE.Цикл WHILE - простейший тип цикла в PHP. Он действует, как и его аналог в C. Основная форма оператора WHILE:

WHILE(expr) statement

Он предписывает PHP выполнять вложенный(е) оператор(ы) до тех пор, пока expr равно TRUE. Значение выражения проверяется каждый раз при начале цикла, так что если значение выражения изменится внутри цикла, то он не прервётся до конца текущей итерации. Если значение expr равно FALSE с самого начала, цикл не выполняется ни разу.

Как и в IF, вы можете сгруппировать несколько операторов внутри фигурных скобок или использовать альтернативный синтаксис:

WHILE(expr): выражения ... ENDWHILE;

Следующие примеры идентичны - оба выводят номера с 1 по 10:

/* example 1 */

$i = 1;

while ($i <= 10) { print $i++; }

/* example 2 */

$i = 1;

while ($i <= 10): print $i; $i++;

endwhile;

DO..WHILE.Цикл DO..WHILE очень похож на WHILE за исключением того, что значение логического выражения проверяется не до, а после окончания итерации. DO..WHILE гарантировано выполнится хотя бы один раз, что в случае WHILE не обязательно.

Для циклов DO..WHILE существует только один вид синтаксиса:

$i = 0; do { print $i; } while ($i>0);

Этот цикл выполнится один раз, так как после окончания итерации будет проверено значение логического выражения, а оно равно FALSE ($i не больше 0).

Программисты на C знакомы с иным использованием DO..WHILE, позволяющим прекратить исполнение блока операторов в середине путём внедрения его в цикл DO..WHILE(0) и использования оператора BREAK. Следующий код демонстрирует такую возможность :

do {

if ($i < 5) {

print "i is not big enough";

break;

}

$i *= $factor;

if ($i < $minimum_limit) { break; }

print "i is ok";

} while(0);

FOR.Циклы FOR - наиболее мощные циклы в PHP. Они работают подобно их аналогам в C. Синтаксис цикла FOR :

FOR (expr1; expr2; expr3) statement

Первое выражение (expr1) безусловно вычисляется(выполняется) в начале цикла.

В начале каждой итерации вычисляется expr2. Если оно равно TRUE, то цикл продолжается и выполняются вложенный(е) оператор(ы). Если оно равно FALSE, то цикл заканчивается. В конце каждой итерации вычисляется(исполняется) expr3.

Каждое из этих выражений может быть пустым. Если expr2 пусто, то цикл продолжается бесконечно (PHP по умолчанию считает его равным TRUE, как и С). Это не так бесполезно, как могло бы показаться, так как зачастую вам требуется закончить выполнение цикла, используя оператор BREAK в сочетании с логическим условием вместо использования логического выражения в FOR.

Рассмотрим следующие примеры. Все они выводят номера с 1 по 10 :

/* пример 1 */

for ($i = 1; $i <= 10; $i++)

print $i;

}/* пример 2 */

for ($i = 1;;$i++) {

if ($i > 10) break;

print $i;

}/* пример 3 */

$i = 1;

for (;;) {

if ($i > 10) break;

print $i;

$i++;

}/* пример 4 */

for ($i = 1; $i <= 10; print $i, $i++) ;

PHP также поддерживает альтернативный синтаксис FOR :

FOR (expr1; expr2; expr3): выражение; ...; endfor;

Другие языки используют оператор foreach для того, чтобы обрабатывает массивы или списки. PHP использует для этого оператор while и функции list() и each() . Для примера смотрите документацию по этим функциям.

BREAK. Прерывает выполнение текущего цикла.

$i = 0;

while ($i < 10) {

if ($arr[$i] == "stop") { break; }

$i++;

}

CONTINUE.CONTINUE переходит на начало ближайшего цикла.

while (list($key,$value) = each($arr)) {

if ($key % 2) { // skip even members

continue; }

do_something_odd ($value);

}

SWITCH.Оператор SWITCH похож на группу операторов IF с одинаковым выражением. Во многих случаях вам нужно сравнить переменную (или выражение) со многими различными значениями и выполнить различные фрагменты кода в зависимости от того, чему будет равно значение выражения.

Следующие 2 примера - это 2 различных пути для достижения одной цели, но один использует серию операторов IF, а другой - оператор SWITCH.

/* пример 1 */

if ($i == 0) { print "i equals 0"; }

if ($i == 1) { print "i equals 1"; }

if ($i == 2) { print "i equals 2"; }

/* пример 2 */

switch ($i) {

case 0: print "i equals 0"; break;

case 1: print "i equals 1"; break;

case 2: print "i equals 2"; break;

}

SWITCH выполняет последовательно оператор за оператором. В начале код не исполняется. Только когда встречается оператор CASE с подходящим значением, PHP начинает выполнять программу. PHP продолжает выполнять операторы до конца блока SWITCH или пока не встретит оператор BREAK. Если вы не напишете BREAK в конце цикла операторов, то PHP продолжит выполнять операторы и следующего SWITCH'а. К примеру:

switch ($i) {

case 0: print "i equals 0";

case 1: print "i equals 1";

case 2: print "i equals 2";

}

В этом случае, если $i равно 0, то PHP выполнит все операторы print! Если $i равно 1, то PHP выполнит последние два print. И только если $i равно 2, вы получите ожидаемый результат и выведено будет только 'i equals 2'. Так что важно не забывать ставить BREAK. Специальный случай - это 'default case'. Этот оператор соответствует всем значениям, которые не удовлетворяют другим case'ам. К примеру :

switch ($i) {

case 0: print "i equals 0"; break;

case 1: print "i equals 1"; break;

case 2: print "i equals 2"; break;

default: print "i is not equal to 0, 1 or 2";

}

Выражения в CASE могут быть любого скалярного типа, то есть целые числа или числа с плавающей запятой, а так же строки. Массивы и объекты не будут ошибкой.

REQUIRE.Оператор REQUIRE заменяет себя содержимым указанного файла, похоже на то, как в препроцессоре C работает #include. Это означает, что вы не можете поместить require() внутрь цикла и ожидать, что он включит содержимое другого файла несколько раз в процессе каждой итерации. Для это используйте INCLUDE.

require ('header.inc');

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

$files = array ('first.inc', 'second.inc', 'third.inc');

for ($i = 0; $i < count($files); $i++) { include($files[$i]); }

include() отличается от require() тем, что оператор include выполняется каждый раз при его встрече, а require() заменяется на содержимое указанного файла безотносительно будет ли выполнено его содержимое или нет. Так как include() это специальный оператор, требуется заключать его в фигурные скобки при использовании внутри условного оператора.

/* Это неправильно и не будет работать, как хотелось бы. */

if ($condition) include($file);

else include($other);

/* А вот это - верно. */

if ($condition) { include($file);}

else { include($other); }

Когда файл исполняется, парсер пребывает в "режиме HTML", то есть будет выводить содержимое файла, пока не встретит первый стартовый тег PHP (<?).

FUNCTION.Функция может быть объявлена следующим образом:

function foo ($arg_1, $arg_2, ..., $arg_n) {

echo "Example function.\n";

return $retval; }

Внутри функции может быть любой верный код PHP, даже объявление другой функции или класса. Функции должны быть определены перед тем, как на них ссылаться.

Возвращение результатов.Результаты возвращаются через необязательный оператор return. Возвращаемый результат может быть любого типа, включая списки и объекты.

function my_sqrt ($num) {

return $num * $num; }

echo my_sqrt (4); // outputs '16'.

Множественные результаты не могут быть возвращены в качестве результата, но вы можете реализовать это путём возврата списка :

function foo() {

return array (0, 1, 2); }

list ($zero, $one, $two) = foo();

Аргументы.Информация может быть передана функции через список аргументов, которые являются разделенным запятыми списком переменных и/или констант.

PHP поддерживает передачу аргументов по значению (по умолчанию), по ссылке, и значения по умолчанию. Списки аргументов переменной длины не поддерживаются, но того же можно достичь, передавая массивы.

function takes_array($input) {

echo "$input[0] + $input[1] = ", $input[0]+$input[1];

}

Передача по ссылке.По умолчанию, аргументы функции передаются по значению. Если вы хотите в функции модифицировать аргументы, то можете передать их по ссылке.

Если вы хотите, чтобы аргумент всегда передавался по ссылке, то следует поставить амперсанд (&) перед именем аргумента в объявлении функции:

function foo( &$bar ) {

$bar .= ' and something extra.'; }

$str = 'This is a string, ';

foo ($str);

echo $str; // выведет :'This is a string, and something extra.'

Если вы хотите передать аргумент по ссылке в случае, когда по умолчанию такого не делается, то добавьте амперсанд перед именем аргумента в вызове функции :

function foo ($bar) {

$bar .= ' and something extra.';}

$str = 'This is a string, ';

foo ($str);

echo $str; // выведет 'This is a string, '

foo (&$str);

echo $str; // выведет 'This is a string, and something extra.'

Значения по умолчанию.Функции могут определять значения по умолчанию для скалярных аргументов в стиле C++ как показано :

function makecoffee ($type = "cappucino") {

echo "Making a cup of $type.\n";

}

echo makecoffee ();

echo makecoffee ("espresso");

Этот пример выведет следующее :

Making a cup of cappucino.

Making a cup of espresso.

Значение по умолчанию должно быть константой, а не переменной или, к примеру, членом класса. Учтите, что когда вы объявляете аргументы по умолчанию, они должны быть справа от всех "неумолчиваемых" аргументов, в противном случае это не будет работать, как задумано. К примеру :

function makeyogurt ($type = "acidophilus", $flavour) {

return "Making a bowl of $type $flavour.\n";

}

echo makeyogurt ("raspberry");

Этот пример выведет следующее :

Warning: Missing argument 2 in call to makeyogurt() in

/usr/local/etc/httpd/htdocs/php3test/functest.html on line 41

Making a bowl of raspberry .

А теперь сравните с этим :

function makeyogurt ($flavour, $type = "acidophilus") {

return "Making a bowl of $type $flavour.\n";

}

echo makeyogurt ("raspberry"); // а вот это работает

И выводит следующее :

Making a bowl of acidophilus raspberry.

Класс. Класс - это набор переменных и функций, работающих с этими переменными. Класс определяется следующим образом :

<?php

class Cart {

var $items; // Количество вещей в корзине покупателя

// Добавить $num наименований типа $artnr в корзину

function add_item ($artnr, $num) {

$this->items[$artnr] += $num; }

// Убрать $num наименований $artnr из корзины

function remove_item ($artnr, $num) {

if ($this->items[$artnr] > $num) {

$this->items[$artnr] -= $num;

return true; }

else { return false; }

}

}

?>

Это определения класса Cart, который состоит связного списка наименований товаров в корзине и двух функций для добавления и удаления вещей из корзины.

Классы это типы, то есть, заготовки для реальных переменных. Вы должны создавать переменные желаемого типа, используя оператор new :

$cart = new Cart;

$cart->add_item("10", 1);

Таким образом, мы создали объект $cart класса Cart. Функция add_item() этого объекта вызывается для добавления 1 товара номер 10 к корзине.

Классы могут быть расширениями других классов. Расширенный класс обладает всеми переменными и функциями базового класса и тем, что вы определите при расширении класса. Это делается, используя ключевое слово extends:

class Named_Cart extends Cart {

var $owner;

function set_owner ($name) {

$this->owner = $name; }

}

Это определяет класс Named_Cart, который имеет все переменные и функции класса Cart плюс дополнительную переменную $owner и дополнительную функцию set_owner(). Вы можете создать поименованную корзину обычным образом и установить или получить владельца корзины. Также вы можете использовать и нормальные функции корзины в поименованной корзине :

$ncart = new Named_Cart; // Создать корзину

$ncart->set_owner ("kris"); // Указать владельца

print $ncart->owner; // Распечатать имя владельца корзины

$ncart->add_item ("10", 1); // (унаследовано из обычной корзины)

Внутри функций класса переменная $this означает сам объект. Вы должны использовать $this->нечто для доступа к переменной или функции с именем 'нечто' внутри объекта.

Конструкторы это функции в классе, которые автоматически вызываются, когда вы создаёте новую переменную данного класса. Функция становится классом, когда она имеет такое же имя, как и сам класс.

class Auto_Cart extends Cart {

function Auto_Cart () {

$this->add_item ("10", 1); }

}

Мы определили класс Auto_Cart который является тем же классом Cart плюс имеет конструктор, который инициализирует корзину при создании, наполняя ее одним товаром типа "10". Конструкторы также могут иметь аргументы, и эти аргументы могут быть необязательными, что делает конструктор более полезным:

class Constructor_Cart {

function Constructor_Cart ($item = "10", $num = 1) {

$this->add_item ($item, $num);

}

}// Покупаем все одно и то же:

$default_cart = new Constructor_Cart;

// А тут что-то новое :

$different_cart = new Constructor_Cart ("20", 17);

Операторы

Арифметические операторы.Эти операторы работают подобным образом



<== предыдущая лекция | следующая лекция ==>
Операторы равенства. | Аутентификация с помощью PHP и MySQL.


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.106 сек.