Самоучитель PHP 4 - Котеров Д. В
..pdf108 |
Часть III. Основы языка PHP |
Достоинства и недостатки интерпретатора
Если вы — бывший системщик или прикладной программист и не знакомы с языком Perl, довольно непросто будет привыкнуть к тому, что PHP, как и большинство языков для Web, является интерпретатором (правда, как мы уже говорили, с транслирующим оптимизатором).
Что ж, это так. Да, сценарии, написанные на PHP, работают в тысячи раз медленнее, чем Си-программы (но почти с такой же скоростью, как созданные на Perl — может быть, отстают максимум в несколько раз на особо критических участках), и к этому придется привыкнуть. Например, если мы напишем на Си пустой цикл с миллионом итераций примерно такого вида:
for(long i=0; i<1000000; i++);
то он будет работать всего долю секунды, в то время как аналогичный цикл на PHP:
for($i=0; $i<1000000; $i++);
проработает на процессоре Pentium 100 несколько секунд.
Приведенные оценки, особенно сравнения с Perl, касаются только PHP версии 4, но не версии 3. Последний отстает даже от Perl по быстродействию почти в 100 раз. Так что стоит задуматься, допустимо ли вообще применять PHP вер- сии 3 при написании нетривиальных программ.
Однако для сценариев, не содержащих в себе таких громадных циклов (а таких программ, как мы вскоре увидим, большинство), время работы будет отличаться очень несущественно. Ну, в самом деле, какая разница, работает ли сценарий 0,01 секунды или 0,1 секунды, если передача данных по каналам Интернета через модем будет длиться, например, 5 секунд?
Впрочем, тут все-таки есть стимул стараться по возможности ускорить сцена- рий: если на вашей машине размещены сотни виртуальных хостов, способных работать с PHP, и каждый из них весьма популярен у пользователей Интерне- та, то суммарный проигрыш в быстродействии может быть вполне ощутим. В этом случае придется просто отказаться от PHP и перейти на более быстрый (но и более сложный) язык — например, Си или Java.
"А как же быть, — спросят некоторые, — если нам нужно написать сценарий для работы, скажем, с тысячами и десятками тысяч пользователей, адреса и телефоны которых хранятся в файле? Ведь, чтобы найти какого-то пользователя (особенно, если его имя задано не точно), придется просматривать их всех, а это как раз и будет цикл с огромным количеством итераций?" Да, это действительно так. Если нужно обраба-
Глава 6. Характеристика языка PHP |
109 |
тывать очень большие массивы данных, лучше использовать Си или... базу данных. База данных — это набор очень большого числа записей с одинаковой структурой плюс программное обеспечение для быстрого поиска, добавления и удаления записей (чаще всего написанного как раз на Си). PHP поддерживает работу с очень большим числом разнообразных баз данных, поэтому написание сценариев с применением баз данных не должно вызвать особых проблем. Кстати, и выполняться такие скрипты будут быстрее, чем аналогичные им "самодельные", написанные на Си — ведь разработкой баз данных и эффективных алгоритмов работы с ними занималось множество людей. А в PHP останется лишь вызвать нужную функцию (например, поиск в базе данных) и сразу получить результат — многие базы данных даже умеют нужным образом его отсортировать и вообще выполнить всю "грязную работу"...
У интерпретатора есть и другие преимущества перед классическим компилятором, например, перед Си. Вот некоторые из них.
r Упрощается обнаружение ошибок во время выполнения программы. В случае сбоя интерпретатор сразу же выведет сообщение, что что-то не так.
r Можно не заботиться об освобождении выделенной памяти. Интерпретатор сам определит, когда та или иная переменная в программе уже не используется, и освободит память, выделенную для нее.
rСуществует возможность написать программу, которая, грубо говоря, будет формировать и тут же исполнять другую программу, что очень часто практикуется при шаблонной системе организации скриптов. В частности, мы можем формировать идентификаторы во время исполнения программы, создавать массивы анонимных функций и т. д.
rНе нужно думать о типах переменных (как это, кстати, было сделано в приведенном цикле for). Мы еще вернемся к данному вопросу в дальнейшем.
Есть и другие достоинства. Вообще, использование интерпретатора способно дать сценариям ту мощь, которую пользователи Web от них и ожидают.
Но за все нужно платить: эта пресловутая медлительность интерпретаторов, даже с блоком трансляции, способна вывести из себя самого закаленного программиста. Проигрыш особенно заметен в случае больших и сложных циклов, при обработке большого количества строк и т. д. Однако, заметьте, это единственный недостаток PHP, который будет все меньше и меньше проявляться по мере выхода более мощных процессоров, чтобы в конце концов вообще сойти на нет.
Пример PHP-программы
Традиционно, любая книга начинается с программы "Hello world!". Что ж, не буду отходить от этих канонов и приведу сразу два примера такой программы. Вот первый из них:
<?
110 |
Часть III. Основы языка PHP |
echo "Hello world!"; ?>
Запустим сценарий в браузере. Легко убедиться, что он действительно работает, да к тому же еще и безотказно.
Это замечание предназначено для тех, кто еще совершенно не знаком с син- таксисом языка PHP. Итак, возможно, вы немного смущены словами "запустим сценарий в браузере". Дело в том, что PHP-сценарий по своей природе не- сколько отличается от обычных CGI-сценариев, которые мы рассматривали в первой части этой книги. Но не торопитесь. Следующий пример поставит все точки над "i".
Для тех, кто еще не сталкивался с синтаксисом PHP, более интересен пример второй программы. Вот как он выглядит:
<body> Hello world! </body>
Что — думаете, произошла ошибка и редактор вместо примера кода на PHP случайно вставил в текст пример HTML-страницы? А вот и нет. Да-да, вы не ошиблись — тут действительно нет вообще никаких операторов PHP, и содержимое файла с "программой" состоит целиком из статического текста.
Что же происходит? Выходит, обычный HTML-текст также правильно обрабатывается PHP? Да, это так. Но рассмотрим чуть более сложный пример (листинг 6.1).
Листинг 6.1. Простой сценарий на PHP
<html><body> <h1>Здравствуйте!</h1> <?
//Вычисляем текущую дату в формате "день.месяц год" $dat=date("d.m y");
//Вычисляем текущее время
$tm=date("h:i:s");
# Выводим их
echo "Текущая дата: $dat года<br>\n"; echo "Текущее время: $tm<br>\n";
# Выводим цифры
echo "А вот квадраты и кубы первых 5 натуральных чисел:<br>\n"; for($i=1; $i<=5; $i++)
{echo "<li>$i в квадрате = ".($i*$i); echo ", $i в кубе = ".($i*$i*$i)."\n";
Глава 6. Характеристика языка PHP |
111 |
}
?>
</body></html>
Я убежден, что синтаксис любого языка программирования гораздо легче "почувствовать" на примерах, нежели используя какие-то диаграммы и схемы. Я буду придерживаться этого принципа на протяжении всей книги. Что ж, приступим к разбору программы.
Начало сценария, если бы не был уже затронут второй пример, может озадачить: разве это сценарий? Откуда HTML-тэги <html> и <body>? Вот тут-то и кроется главная особенность (кстати, чрезвычайно удобная) языка PHP: PHP-скрипт может вообще не отличаться от обычного HTML-документа, как мы это уже заметили ранее.
А помните, как мы раньше в примерах на Си писали кучу одинаковых printf'ов для того, чтобы выводить HTML-код страницы? На PHP это можно делать естественным образом, без всяких операторов. Иными словами, все, что расположено в нашем примере до начала PHP-кода, отображается непосредственно, как будто при помощи нескольких вызовов printf() в Си.
Идем дальше. Вы, наверное, догадались, что сам код сценария начинается после открывающего тэга <? и заканчивается закрывающим ?>. Итак, между этими двумя тэгами текст интерпретируется как программа, и в HTML-документ не попадает. Если же программе нужно что-то вывести, она должна воспользоваться оператором echo (это не функция, а конструкция языка: ведь, в конце концов, если это функция, то где же скобки?). Мы подробно рассмотрим ее работу в дальнейшем. Итак, PHP устроен так, что любой текст, который расположен вне программных блоков, ограниченных <? и ?>, выводится в браузер непосредственно, т. е. воспринимается, как вызов оператора echo (последняя аналогия очень точна, и мы остановимся на ней чуть позже).
Нетрудно догадаться, что часть строки после // является комментарием и на программу никак не влияет. Однострочные комментарии также можно предварять и символом # вместо //, как мы можем это увидеть в примере. Комментарии еще бывают и такие:
/*
это комментарий
...и еще одна строка
*/
То есть, комментарии могут, как и в Си, быть однострочными и многострочными. Однако в некоторых реализациях PHP многострочные комментарии почему-то вступают в конфликт с "русскими" буквами, которые могут находиться между ними. А именно, появляются бессмысленные сообщения о синтаксических ошибках, причем совершенно не в том месте. Почему так происходит, неясно: видимо, ошибка в PHP. Насчет комментариев и контроля ошибок мы еще поговорим, а пока вот вам совет: никогда не пользуйтесь многострочными комментариями в PHP, если хотите жить
112 |
Часть III. Основы языка PHP |
долго и счастливо (тем более, что не допускаются вложенные многострочные комментарии).
А пока давайте лучше посмотрим, что происходит дальше. Вот строка:
$dat=date("d.m y");
Делает она следующее: переменной с именем $dat (заметьте, что абсолютно все переменные в PHP должны начинаться со знака $, потому что "так проще для интерпретации") присваивается значение, которое вернула функция date(). Итак, мы видим, что в PHP, во-первых, нет необходимости явно описывать переменные (как это делается, например, в Паскале или Си), а во-вторых, нигде не указывается их тип (про типы мы еще поговорим чуть позже). Интерпретатор сам решает, что, где и какого типа. А насчет функции date()... Можно заметить, что у нее задается один параметр, который определяет формат результата. Например, в нашем случае это будет строка вида "11.12 01".
В конце каждого оператора должна стоять точка с запятой, как в Си. Заметьте — именно как в Си, а не как в Паскале. Иными словами, вы обязаны ставить точку с запятой перед else в конструкции if-else, но не должны после заголовка функции.
На следующей строке мы опять видим комментарии, а дальше — еще один оператор, похожий на ранее описанный. Он присваивает переменной $tm текущее время в формате "часы:минуты:секунды", опять же при помощи вызова date(). Все возможности этой полезной функции будут подробно описаны в четвертой части книги.
Далее следуют операторы echo, выводящие текстовые строки и нашу дату и время. Рассмотрим один из них:
echo "Текущая дата: $dat года<br>\n";
Заметьте: то, что любая переменная должна начинаться с символа $, позволяет интерпретатору вставить ее прямо в строку символов на место $dat (конечно, в любую строку, а не только в параметры echo). Разумеется, можно было бы написать и так (поскольку конструкция echo не ограничена по числу параметров):
echo "Текущая дата: ",$dat," года<br>\n";
или даже так:
echo "Текущая дата: ".$dat." года<br>\n";
так как для слияния строк используется операция "." (к этому придется пока привыкнуть).
Кстати говоря, на вопрос, почему для конкатенации строк применяется точка а не, скажем, плюс "+", довольно легко ответить примером:
$a="100"; $b="200";
echo $a+$b; // выведет "300" echo $a.$b; // выведет "100200"
Глава 6. Характеристика языка PHP |
113 |
Итак, мы видим, что плюс используется именно как числовой оператор, а точка — как строковой. Все нюансы применения операторов мы рассмотрим в следующей главе.
Еще один пример "внедрения" переменных непосредственно в строку:
$path="c:/windows"; $name="win"; $ext="com"; FullPath="$path\$name.$ext";
Последнее выглядит явно изящнее, чем:
$path="c:/windows"; $name="win"; $ext="com"; $FullPath=$path."\".$name.".".$ext;
В терминах языка Perl можно сказать, что переменные в строках, заключенных в кавычки, интерполируются, т. е. расширяются. Существует и другой способ представления строк в PHP — это строки в апострофах, и в них переменные не интерполируются.
Ну вот, мы почти подобрались к сердцу нашего сценария — "уникальному" алгоритму поиска квадратов и кубов первых 5 натуральных чисел. Выглядит он так:
for($i=1; $i<=5; $i++)
{echo "<li>$i в квадрате = ".($i*$i); echo ", $i в кубе = ".($i*$i*$i)."\n";
}
В первой строке находится определение цикла for (счетчик $i, которому присваивается начальное значение 1, инкрементируется на единицу на каждом шаге, пока не достигнет пяти). Затем следует блок, выполняющий вывод одной пары "квадрат-куб". Я намеренно сделал вывод в две строки, а не в одну, чтобы показать, что в PHP применяются те же самые правила группировки операторов, что и в Си. А именно: несколько операторов можно сделать одним сложным оператором, заключив их в фигурные скобки, как это сделано выше.
Наконец, после всего этого расположен закрывающий тэг PHP ?>, а дальше — опять обычные HTML-тэги, завершающие нашу страничку.
Уф! Вот какой код получился в результате работы нашего сценария (листинг 6.2):
Листинг 6.2. Результат работы сценария
<html><body> <h1>Здравствуйте!</h1>
Текущая дата: 29.01 01 года<br>
114 |
Часть III. Основы языка PHP |
Текущее время: 04:34:16<br>
А вот квадраты и кубы первых 5 натуральных чисел:<br> <li>1 в квадрате = 1, 1 в кубе = 1
<li>2 в квадрате = 4, 2 в кубе = 8 <li>3 в квадрате = 9, 3 в кубе = 27 <li>4 в квадрате = 16, 4 в кубе = 64 <li>5 в квадрате = 25, 5 в кубе = 125 </body></html>
Как видите, выходные данные сценария скомбинировались с текстом, расположенным вне скобок <? и ?>. В этом-то и заключена основная сила PHP: в легком встраивании кода в тело документа.
Использование PHP в Web
Пока мы с вами касались только теории того, как работает сценарий на PHP. Давайте же теперь наконец займемся практикой. Но сначала поговорим вот о чем.
Итак, PHP — язык, который позволяет встраивать в код программы "куски" HTMLкода. Мы можем использовать его для написания CGI-сценариев и избавиться от множества неудобных операторов вывода текста. Не так ли?
Посмотрим. Вот другое утверждение. PHP — язык (надстройка над HTML), который позволяет встраивать программный код в HTML-документы. Мы можем привлекать его для формирования HTML-документов и избавиться от множества вызовов внешних сценариев.
Вы озадачены — какое же из утверждений (в чем-то противоречивых, кстати) верно? Это хорошо. Я достиг цели. Это означает, что мы с вами только что избежали одной из самых популярных ошибок начинающих программировать на PHP людей — считать единственно верным только первое или только второе утверждение. В действительности PHP представляет собой язык, в котором в одних ситуациях следует придерживаться одного, а в остальных — другого соглашения.
Если вы думаете, что все это лишь игра слов, и "хоть горшком назови, только в печь не ставь", то ошибаетесь. Дело в том, что затронутая тема почти вплот- ную стыкуется с идеологией отделения кода сценария от дизайна страницы — идее очень важной, особенно при работе нескольких человек над одним проек- том, и довольно нетривиальной самой по себе. Мы очень подробно рассмот- рим ее в пятой части книги, которая посвящена методам программирования на
PHP.
Глава 6. Характеристика языка PHP |
115 |
Ну что, стало понятнее? Пожалуй, нет. Ну что ж, давайте пока будем рассматривать все наши примеры так, как будто они подходят под второе утверждение (хотя в последнем примере — положа руку на сердце — больше программного кода, чем HTML-тэгов). Итак, программа, показанная в листинге 6.1, представляет собой HTML-страницу с "вкрапленным" кодом на PHP. А раз так, то назовем ее, например, list1.1.php и расположим в каталоге для документов на Web-сервере. Теперь с точки зрения Web-пользователя она — просто страница.
Для иллюстрации примеров здесь и далее я буду использовать локальный сервер Apache для платформы Win32, установка которого подробно описана в главе 3. Примеры я располагал на хосте localhost в его корневом каталоге. Конечно, это ни в коей мере не означает, что примеры будут работать только под Windows-версией PHP. Язык PHP задумывался как платформенно-неза- висимый, поэтому, если вы не задействуете в сценарии особенностей той или иной операционной системы, он будет одинаково хорошо (или одинаково пло- хо) работать в любой системе — будь то Unix у хостинг-провайдера или
Windows дома.
Рис. 6.1 — это то, что я увидел, когда открыл в браузере рассмотренный выше пример (файл со сценарием я разместил по адресу:
z:/home/localhost/www/list1.1.php).
Обратите внимание на URL в строке браузера (http://localhost/list1.1.php). Все выглядит так, как будто мы просто открыли обычную Web-страничку. Пока что мы присвоили расширение php для этой страницы для того, чтобы сервер смог понять, что ему нужно на самом деле использовать PHP-интерпретатор для обработки документа. В пятой части этой книги мы рассмотрим, как можно связать PHP с любым расширением и любым документом на сервере, а пока давайте договоримся давать PHPсценариям расширение php.
116 |
Часть III. Основы языка PHP |
Рис. 6.1. Результат работы сценария, приведенного в листинге 6.1
Глава 7
Переменные, константы, выражения
Как вы, наверное, уже заметили, структура PHP-программы довольно сильно напоминает смесь Бейсика и Си, да еще со включениями на HTML. Что ж, так оно, в общем, и есть. Однако мы рассмотрели лишь очень простой пример программы на PHP, поэтому вряд ли сможем сейчас увидеть общую картину языка. А теперь настало время заняться конструкциями PHP вплотную.
Начнем мы с основ языка. Итак...
Переменные
Как и в любом другом языке программирования (за исключением, может быть, языка Forth), в PHP существует такое понятие, как переменная. Даже в простом примере, какой был описан выше, мы использовали целых 3 переменных!
При программировании на PHP принято не скупиться на объявление новых переменных, даже если можно обойтись и без них. Например, в том простом сценарии мы вполне могли бы использовать всего одну переменную — счетчик цикла. Однако значительно читабельнее будет определить их несколько штук. Отчасти это связано с тем, что создание нового идентификатора интерпретатору обходится довольно дешево, частично из-за того, что все переменные в функциях по умолчанию локальны (о локальных переменных разговор пойдет чуть позже).
Имена переменных чувствительны к регистру букв: например, $my_variable — не то же самое, что $My_Variable или $MY_VARIABLE. Кроме того, имена всех переменных должны начинаться со знака $ — так интерпретатору значительно легче "понять" и отличить их, например, в строках. Поначалу это довольно сильно раздражает, но потом привыкаешь (и даже автоматически начинаешь писать "доллары" перед именами переменных в программах на Си, Паскале...)
В официальной документации сказано, что имя переменной может состоять не только из "английских" букв и цифр, но также и из любых символов, код кото- рых старше 127, — в частности, и из "русских" букв! Однако я категорически не советую вам применять кириллицу в именах переменных — хотя бы из-за того, что в различных кодировках ее буквы имеют различные коды.