|
||||||||||
PHP - язык программирования для Интернета. Вы вышли за рамки статических www-страниц? Вам
требуется обрабатывать html-формы? Вы хотите сделать интефейс с базой
данных через веб? Электронный магазин? Счетчик с подробной статистикой
или опрос посетителей вашего сайта? Есть множество программ, работающих
через интерфейс CGI, как правило, написанных на языке Perl, но сегодня
существуют и другие возможности. Достаточно полно описать язык программирования и сопутствующие инструментальные библиотеки в одной статье невозможно, однако можно постараться: не описывая синтаксис или библиотечные функции, полезно остановиться на особенностях создания скриптов на PHP. А с подробной документацией по PHP можно ознакомиться на сайте www.php.net/manual. PHP можно установить в двух вариантах: как отдельный интерпретатор, работающий через интерфейс CGI, или как модуль веб-сервера, встроенный в сам сервер. В последнем случае становятся актуальными все преимущества PHP. Из аналогичных встроенных в сервер программных средств хорошо известны SSI, mod_perl, ASP. Но SSI обладает довольно ограниченными возможностями, а mod_perl, на мой взгляд, слишком много умеет. Ближайшим аналогом PHP является ASP, но технология ASP не прижилась в мире Unix/Apache, где простой, удобный и быстрый язык PHP постепенно завоевывает первые ряды. Сейчас распространена версия 3 интерпретатора PHP, версия 4 пока еще находится в стадии бета-тестирования. Принципиальных отличий четвертой версии от третьей нет, есть только несколько изменений синтаксиса (описанных на сайте www.php.net/version4/incompatibilities.php), которые большинство пользователей не заметит: подавляющее большинство скриптов будут работать в обеих версиях языка. Как и все процедурные языки, PHP можно разделить
на собственно язык и библиотеку функций. Существует большое количество
инструментальных средств для PHP, интерфейсы ко всем популярным СУБД,
почтовым протоколам, к разделяемой памяти, графическим файлам, архивам
и множество других инструментов. Посетителю такой страницы будет показан документ с картинками, меню и текстом, красиво упакованным в хитро вложенную таблицу. Отдельные файлы header.html и footer.html будут просто включены в тот документ, что отдается сервером посетителю страницы. Таким образом можно отделить оформление страницы от ее наполнения, сильно облегчая работу по внесению информации на сайт даже неквалифицированным работникам. Текст скрипта выполняется сверху вниз и справа
налево, последовательно. Эта последовательность может быть изменена
операторами цикла и условными операторами. Например: Здесь мы получим текст "Тебя зовут Вася" или "Тебя зовут капитан Немо" в зависимости от значения переменной $name. В примере видно, что мы прервали текст тегами PHP. В языке есть несколько функций вывода - echo, printf и др., но приведенный в примере код работает намного быстрее, чем, например, if ($name=='Вася') echo 'Вася'. Перевод строки, идущий после закрытия тега ?>, интерпретатор пропускает. Сделано это для удобства форматирования исходных текстов скриптов. Переменные в PHP отличаются наличием символа
$ (доллар) перед именем самой переменной. Объявлять их никак не надо,
так как они создаются автоматически при присвоении им значения и удаляются
при выходе из области действия. Переменные бывают типа строка, число,
массив и объект. Некоторые трудности может вызвать нестрогое отличие
строк от чисел. Поясню на примере: Интерпретатор очень вольно приводит типы строка
и число друг к другу. Хотя чаще всего это даже удобно. Просто надо об
этом помнить и не пытаться сравнивать строку с числом: В первом случае сравниваются числа 5 и 0 и результат,
естественно, положительный. А во втором случае что сравнивается? Документация
на этот счет молчит, а эксперимент показывает, что сравниваться будут
тоже числа. Согласен, что это не строго и не очень красиво, и в условных
операторах я рекомендую использовать операторы приведения типа, как
в языке Cи: или Синтаксис языка PHP вообще очень похож на синтаксис Си, если бы не символы $ в начале имени переменных и некоторые вольности с типами и массивами. Как в "Поднятой целине" председатель колхоза английский учил: "... Английские слова такие же, как русские, только в конце шипение какое-то, революшн, например..." Для изменения типа переменной, в принципе, особенного
ничего делать не надо, достаточно просто присвоить ей значение нового
типа: Последняя строка, например, показывает нам очень популярный и удобный тип данных - хэш-массив (hash array). В принципе, это обычный массив, только индексом у него выступает строка, а не целое число, и никакого приведения типов, о котором я говорил ранее, здесь нет. PHP позволяет создавать многомерные сооружения вида массив хэш-массивов, как, например, $name[5]['ой'][6]= 'не может быть'; В принципе, массив - это тоже хэш, только в нем индексами являются строки, соответствующие числам. Почему так хитро? Это еще ничего, а вот, например, фраза $name[5]=0; создает массив $name из 6 элементов (индексы считаются от 0, как в Си), но только 1 элемент реально существует, остальные просто не определены. На практике это не сильно мешает, помните только, что это не Cи и не Паскаль. Конечно, не очень хорошо, но частенько удобно
пользоваться конструкциями вместо правильной просто потому, что первая запись короче. В первом случае, если переменная $test будет не определена, то ее значение будет как бы пустой строкой. Логично считать, что "никакая" строка - это тоже пустая. Подобная фраза может вызвать предупреждение о синтаксической ошибке, если администратор включил параноидальный контроль синтаксиса, но это бывает редко. Если вам не лень, то пользуйтесь правильными конструкциями и проверяйте наличие переменной перед обращением к ней. А если лень, то считайте неопределенную переменную пустой строкой, нулем, логической ложью и т. п. Как-то специально объявлять массив или хэш тоже
не надо. Но в некоторых случаях это бывает полезно, например, если ваша
функция возвращает массив, то она должна вернуть именно массив, а не
неопределенное значение. Это, кстати, относится и к функциям: Эта надуманная функция возвращает массив, если
$num больше нуля, и непределенное значение - в противном случае, что
затрудняет работу с результатом ее выполнения: Здесь вам поможет функция array(), возвращающая массив, в том числе и пустой. Либо стоит сразу инициализировать переменную $a=array() или вернуть пустой массив как return array(). Первый вариант предпочтительнее. В PHP есть даже некоторая объектность, то есть
вы можете создавать классы, методы и т. д. Как правило, классы хороши
в больших приложениях или как средство ограничения области видимости
переменных. Я бы не рекомендовал очень уж активно ими пользоваться:
помните, что объектный подход нынче очень моден, но не стоит из него
делать фетиш. Реализация классов в PHP версии 4 обещает быть намного
эффективнее, чем в третьей. Поживем - увидим. Программа на языке PHP, как правило, не живет сама по себе, а применяется для обработки запросов через интерфейс CGI. Даже если интерпретатор PHP встроен в сервер как модуль, с точки зрения самой пользовательской программы, она, эта программа, работает через CGI. А для чего творцам чудесных веб-сайтов нужен CGI? Конечно же, для обработки форм. Именно на скрипт указывет параметр action-тега <form action="doit.phtml">. В PHP автору не требуется каким-то особым образом
извлекать данные формы. В момент начала выполнения скрипта для вас уже
существуют и определены переменные, соответствующие одноименным полям.
Если форма имеет вид то при старте скрипта doit.phtml в нем уже определены
переменные $f1, $f2 и $do. Можно указать имя поля в форме как тогда на момент выполнения скрипта, обрабатывающего эту форму, будет определен массив $sel, содержащий выбранные пункты списка select. По умолчанию и чаще всего форма передается HTTP-методом POST. А статические страницы посетитель обычно получает методом GET. В последнем случае вы тоже можете передавать "параметры" выполняющемуся скрипту через так называемую строку запроса (query string), то есть через URL. Выглядит такой URL как-то так: www.domain.ru/script.phtml?a=5&b=no&c=%2f. Собственно параметры начинаются после знака "?" и состоят из пар "имя=значение", разделенных знаком "&". Как и в случае с полями формы, программа script.phtml получит переменные $a, $b и $c с соответственным содержимым "5", "no" и "/". Обратите внимание на значение переменной $c. Вообще-то лучше не полениться и, зайдя на сайт www.w3c.org, вдумчиво прочитать документацию о протоколе HTTP/1.0. Это очень поможет вам в профессиональном росте. Кстати, вам ведь ничто не мешает комбинировать
оба эти метода. То есть вы можете создавать формы и указывать обработчику
параметры через URL: Передавать данные скрипту можно не только посредством параметров в URL или в полях формы. Практически все современные броузеры понимают cookies. В PHP вы можете пользоваться ими совершенно свободно. Когда броузер отдает cookie вашему скрипту, вы просто получаете переменную с именем cookie и значением, соответствующим значению cookie. Отдать же cookie броузеру вы можете функцией setcookie('имя','значение' [,необязательные параметры]); Помните, что эта функция должна выполняться до любого вывода текста страницы. PHP позволяет с помощью cookies хранить в броузере
клиента множество информации. Для этого реализован механизм cookies-массива.
Например, после однократного выполнения такого фрагмента кода: все ваши скрипты будут иметь в начале выполнения хэш-массив $myData с точно тем же содержимым. Помните, что количество информации в cookies ограничено, так что старайтесь ими не злоупотреблять. Да, и не храните в cookies текст на русском языке или двоичную информацию, лучше предварительно закодируйте ее с помощью функции rawurlencode(). Если же вам очень хочется завести о пользователе
целую уйму персональных данных, а использовать для этого cookies неудобно,
то вам стоит выбрать одну из схем "ведения пользователя" (user
tracking). Их существует множество - это и модули к www-серверу, и отдельные
библиотеки к PHP, и множество готовых функций или классов, написанных
на самом PHP. Вы легко можете сделать и свою систему ведения. Вот вам
простенький примерчик. Включив этот файл в начало любого скрипта, вы
можете вести пользователей, сохраняя информацию о пользователе в течение
года: В результате мы получим хэш-массив со всеми заданными
нами настройками посетителя. Базы данных dbm* работают очень быстро
и не требуют больших ресурсов, и пользоваться ими можно и нужно. Мы
могли бы использовать для хранения данных СУБД, но пока не будем. В
данном случае применение SQL СУБД оправдано, если большая часть ваших
страниц также формируется из базы данных. Сейчас стало очень модно применять
SQL-серверы где угодно, там где надо и где не надо (чаще всего, где
не надо). Даже www-чаты на SQL-базах делают. При небольших объемах данных
стоит подумать о простых средствах: текстовых файлах, хэш-базах (dbm*)
и т. п. Прочитать файл в 100 К в память и порыться в ней будет намного
быстрее, чем даже 1 запрос к SQL-базе. О пользовании СУБД я расскажу
несколько позже. Владея PHP, вы можете легко уйти от рутины. Любой
табличный процессор позволяет сохранять листы как текст с разделителями-табуляциями.
А вот как такой файл красиво вывести в виде таблицы со строчками разного
цвета: PHP имеет достаточное количество встроенных функций
для работы с файлами, но частенько хочется этот набор несколько расширить.
Например как сделать www-чат? В теории все просто, все посетители пишут
в один файл и читают последние N строк этого файла. Конечно, хотелось
бы читать этот файл не последовательно с начала. Я предлагаю вашему
вниманию функцию tail(), которая работает очень быстро не зависимо от
размеров читаемого файла. Я не буду утверждать, что это лучший на свете алгоритм, и принимаю все предложения по его улучшению. Есть два замечания сразу. *!* Здесь вычисляется средняя длина строки для
следующего цикла. У меня это отлично работало и при $appxlen*=2, но
так, наверно, быстрее будет. Функция чтения строки из файла имеет ограничение
на длину считываемой строки. А думать о длинах строк при написании гениальных
скриптов не хочется. Как быть? Я предлагаю небольшую функцию, аналогичную
fgets(), но без неприятного ограничения: Функцию authFunction() пишет сам пользователь, она получает аргументами, соответственно, логин и пароль, введенные посетителем, и два необязательных параметра по наследству от authCheck(). Автор скрипта должен просто включить файл auth.inc в свою программу, написать функцию authFunction(), которая, например, будет проверять пользователя по базе данных, и вызвать функцию authCheck() перед каким-либо выводом текста страницы, как было замечено про функцию setcookie(). Написание разных authFunction() позволяет контролировать доступ посетителей из множества различных источников, таких как файлы паролей, СУБД, хэш-файлы, запросы к сетевым сервисам авторизации, и из любых на ваше усмотрение. Такой тип авторизации самый, так сказать, железный. При посещении закрытой страницы посетителю выдается диалоговое всплывающее окно с полями имени и пароля. В дальнейшем броузер запоминает $realm и при последующем запросе пароля будет автоматически отправлять серверу пару имя/пароль. Однако это не единственный способ авторизации. Пример писать не буду, а просто потеоретизирую немного. Описанная выше система ведения пользователя вполне подойдет с небольшими модификациями. Для регистрации создадим форму с полями login и password. Обработчик формы генерирует случайный уникальный ключ и записывает с ним дату/время регистрации в хэш-файл. Вместо даты и времени годится значение функции time(), возвращающей количество секунд с 01.01.1970. Броузеру клиента выдается cookie, например, xfile со значением только что сгенерированного ключа. Каждая страница, требующая авторизации, должна проверить наличие ключа $xfile в хэш-файле и, если он есть, записать туда время обращения, не затрагивая времени регистрации. Для отказа от авторизации достаточно удалить ключ из базы. Внешняя программа может раз в полчаса, допустим, удалять ключи, выданные 3 часа назад, и ключи, к которым не было обращения в течение 1 часа. Стойкость такой системы определяется трудностью подбора ключа-cookie за ограниченное время, так как ключи живут относительно недолго и они достаточно длинные. Ключ можно передавать не только через cookie, но и через URL как параметр скрипта. Конечно, гениальный автор сайта сам должен решить, какой алгоритм авторизации он себе выберет, так как у обоих вариантов есть свои плюсы и минусы. Возможно, есть еще какие-либо варианты. Пишите, обсудим. В общем-то ведение пользователя и авторизация
- это ключ к созданию электронного магазина. Может быть, об этом я тоже
когда-нибудь напишу. Самая распространенная ошибка авторов скриптов
- это отношение к СУБД как к чему-то сверхоперативному. А это вовсе
не так. Вот пример, как не надо писать скрипты: 1 строка - надо трижды подумать, прежде чем иcпользовать постоянное соединение с базой. Здесь выбран хост localhost, но работа с локальным сервером через unix socket может быть быстрее. 2 строка - надо проверить, выполнился ли запрос без ошибок. 3 строка - нехорошо вызывать функцию в цикле, лучше завести дополнительную переменную $num=pg_numrows($s1). 5 строка - самая грубая ошибка: запрос в цикле по другому запросу, от такого программирования не спасут ни множество процессоров, ни обилие памяти, ни быстрая дисковая система. Почему бы не решить проблему в один запрос? $s1=pg_exec("select a,c,x,y,z from b,d where e=a order by a"); В цикле можно запомнить предыдущее значение $a и прерывать цикл при смене этого значения. В любом случае, чем меньше запросов будет к базе, тем лучше - имейте это в виду. 7-10 строки - можно не вытаскивать поля по одному, а применить функцию pg_fetch_array() или pg_fetch_object(), которые возвращают хэш и объект соответственно с именами полей, соответствующими именам полей результата запроса. PHP позволяет поддерживать постоянные соединения с СУБД. То есть при завершении скрипта соединение с сервером базы данных разорвано не будет, а будет возобновлено при повторном запросе. Такой метод работы очень экономит время соединения, но съедает системные ресурсы (память, дескрипторы и т. д.). Если у вас один пользователь базы, одна база и один сайт, который непрерывно обращается к базе, то вам стоит попробовать поэкспериментировать. В конфигурации PHP можно глобально отменить постоянные соединения, чем и пользуются провайдеры, чтобы защитить свои хосты от жадных пользователей. Раз уж мы начали говорить об электронной торговле, то можно развеять еще одно заблуждение, - что MySQL для нее годится. Это не совсем так. Он годится для макета, но не для серьезного сайта. В MySQL нет транзакций. Для сложной базы, для денежных расчетов, для оформления заказов и многих других важных операций транзакции необходимы. Так что используйте PostgreSQL, который все это умеет. Допустим, магазин вы организовали, заработали
кучу денег, давайте теперь продолжим ознакомление с программированием
на PHP. Вкратце коснусь других возможностей. Указывайте хотя бы From: и Content-type: - это предохранит вас от раздраженных получателей писем или, если получаете вы, от получения писем в непонятной кодировке неизвестно от кого. Одно время у провайдеров были популярны системы
чтения/отправки электронной почты с www-сайта. На PHP вы можете сделать
то же самое. Достаточно лишь почитать описание протоколов POP и IMAP
и открыть сетевое соединение с почтовым сервером. Функция fsockopen(хост,
порт) открывает сетевое соединение, а пользоваться им можно при помощи
обычных файловых функций. Только не открывайте соединение к своему www-серверу
и не запрашивайте свой же скрипт - веб-мастеру это может сильно не понравиться.
В целом работа с сетью в PHP оставляет желать лучшего - надеюсь, многие
изъяны будут исправлены в четвертой версии. В первую очередь не хватает
функции select() или аналога соответствующему вызову POSIX. Сетевое
соединение - это не совсем файл, оно может прерваться, другая программа
может не закрыть соединение и завершиться/зависнуть и т. п. Функция
select() позволяет сделать работу с сетью более надежной. Подождем. 1 -ABORTED 2 - TIMEOUT Когда PHP работает нормально, статус соединения будет NORMAL. Когда клиент прерывает соединение, устанавливается флаг ABORT. Если для выполнения скрипта не хватило времени, то будет установлен флаг TIMEOUT. Вы можете указать интерпретатору, будет или нет ваш скрипт прерван при разрыве соединения. Этот вариант можно выбрать функцией ignore_user_abort(). Другой вариант - это создание функции аварийного завершения, как было описано выше. При ее выполнении вы можете задать проверку причины завершения при помощи функций connection_aborted(), connection_timeout() и connection_status(). Если вы использовали ignore_user_abort(), то функция аварийного завершения может обнаружить два статуса, ABORT, если пользователь прервал соединение, и TIMEOUT если при этом скрипт выполнялся слишком долго. Как известно, для пользователя самый страшный
враг - это сам пользователь. А если таких много на одном сервере? И
обязательно найдется некто, который назовет себя "куул хацкером"
и начнет либо искать спрятанную информацию, либо просто пакостить. В
PHP предприняты попытки ограничить возможности пользовательского скрипта,
чтобы предотвратить возможность утечки информации и порчи чужих данных.
Провайдеры обычно разрешают пользователям выполнять скрипты в "безопасном
режиме". Сильно это ограничение не сковывает, но помнить об этом
надо. Данная статья взата с сайта http://web-build.info |
||||||||||
© 2004-2005 All rights reserved WebSupport: Бикмуллин Эльдар |
||||||||||