Руководство по PHP

Stig Sжther Bakken
Alexander Aulbach
Egon Schmid
Jim Winstead
Lars Torben Wilson
Rasmus Lerdorf
Andrei Zmievski
Jouni Ahto

Под редакцией

Stig Sжther Bakken
Egon Schmid
Ivan Kovalenko
Dzhigkayev Kazbek
Kirill Barashkin
Alexey Asemov

22-04-2003

Авторские права

Авторские права © Copyright 1997-2003 принадлежат Группе Документирования PHP. Члены этой группы перечислены на первой странице руководства.

Данное руководство может распространяться на условиях лицензии GNU General Public License, опубликованной Free Software Foundation; подразумевается 2 версия лицензии или (на ваше усмотрение) любая более поздняя версия.

Авторские права © 2000 на главу "Расширение возможностей PHP 4.0" принадлежат Zend Technologies, Ltd. Этот материал может распространяться только на условиях лицензии Open Publication License, 1 версии или любой более поздней версии (самая последняя версия доступна по адресу http://www.opencontent.org/openpub/).


Содержание
Предисловие
I. Приступая к работе
1. Введение
2. Краткое руководство
3. Установка
4. Конфигурация
5. Безопасность
II. Справочник по языку
6. Основы синтаксиса
7. Типы
8. Variables
9. Constants
10. Expressions
11. Operators
12. Control Structures
13. Functions
14. Classes and Objects
15. References Explained
III. Отличительные особенности
16. HTTP authentication with PHP
17. Cookies
18. Handling file uploads
19. Using remote files
20. Connection handling
21. Persistent Database Connections
22. Safe Mode
23. Using PHP from the command line
IV. Справочник по функциям
I. Функции для работы с сервером Apache
II. Функции для работы с массивами
III. Aspell functions [deprecated]
IV. BCMath Arbitrary Precision Mathematics Functions
V. Bzip2 Compression Functions
VI. Calendar functions
VII. CCVS API Functions
VIII. COM support functions for Windows
IX. Class/Object Functions
X. ClibPDF functions
XI. Crack functions
XII. CURL, Client URL Library Functions
XIII. Cybercash payment functions
XIV. Crйdit Mutuel CyberMUT functions
XV. Cyrus IMAP administration functions
XVI. Character type functions
XVII. Database (dbm-style) abstraction layer functions
XVIII. Date and Time functions
XIX. dBase functions
XX. DBM Functions [deprecated]
XXI. dbx functions
XXII. DB++ Functions
XXIII. Direct IO functions
XXIV. Directory functions
XXV. DOM XML functions
XXVI. .NET functions
XXVII. Error Handling and Logging Functions
XXVIII. FrontBase Functions
XXIX. filePro functions
XXX. Filesystem functions
XXXI. Forms Data Format functions
XXXII. FriBiDi functions
XXXIII. FTP functions
XXXIV. Function Handling functions
XXXV. Gettext
XXXVI. GMP functions
XXXVII. HTTP functions
XXXVIII. Hyperwave functions
XXXIX. Hyperwave API functions
XL. iconv functions
XLI. Image functions
XLII. IMAP, POP3 and NNTP functions
XLIII. Informix functions
XLIV. InterBase functions
XLV. Ingres II functions
XLVI. IRC Gateway Functions
XLVII. PHP / Java Integration
XLVIII. LDAP functions
XLIX. Mail functions
L. mailparse functions
LI. Mathematical Functions
LII. Multi-Byte String Functions
LIII. MCAL functions
LIV. Mcrypt Encryption Functions
LV. MCVE Payment Functions
LVI. Mhash Functions
LVII. Mimetype Functions
LVIII. Microsoft SQL Server functions
LIX. Ming functions for Flash
LX. Miscellaneous functions
LXI. mnoGoSearch Functions
LXII. mSQL functions
LXIII. MySQL Functions
LXIV. Mohawk Software session handler functions
LXV. muscat functions
LXVI. Network Functions
LXVII. Ncurses terminal screen control functions
LXVIII. Lotus Notes functions
LXIX. Unified ODBC functions
LXX. Object Aggregation/Composition Functions
LXXI. Oracle 8 functions
LXXII. OpenSSL functions
LXXIII. Oracle functions
LXXIV. Ovrimos SQL functions
LXXV. Output Control Functions
LXXVI. Object property and method call overloading
LXXVII. PDF functions
LXXVIII. Verisign Payflow Pro functions
LXXIX. PHP Options&Information
LXXX. POSIX functions
LXXXI. PostgreSQL functions
LXXXII. Process Control Functions
LXXXIII. Program Execution functions
LXXXIV. Printer functions
LXXXV. Pspell Functions
LXXXVI. GNU Readline
LXXXVII. GNU Recode functions
LXXXVIII. Regular Expression Functions (Perl-Compatible)
LXXXIX. qtdom functions
XC. Regular Expression Functions (POSIX Extended)
XCI. Semaphore, Shared Memory and IPC Functions
XCII. SESAM database functions
XCIII. Session handling functions
XCIV. Shared Memory Functions
XCV. Shockwave Flash functions
XCVI. SNMP functions
XCVII. Socket functions
XCVIII. Stream functions
XCIX. String functions
C. Sybase functions
CI. Tokenizer functions
CII. URL Functions
CIII. Variable Functions
CIV. vpopmail functions
CV. W32api functions
CVI. WDDX Functions
CVII. XML parser functions
CVIII. XML-RPC functions
CIX. XSLT functions
CX. YAZ functions
CXI. YP/NIS Functions
CXII. Zip File Functions (Read Only Access)
CXIII. Zlib Compression Functions
V. Zend API
24. Overview
25. Extension Possibilities
26. Source Layout
27. PHP's Automatic Build System
28. Creating Extensions
29. Using Extensions
30. Troubleshooting
31. Source Discussion
32. Accepting Arguments
33. Creating Variables
34. Duplicating Variable Contents: The Copy Constructor
35. Returning Values
36. Printing Information
37. Startup and Shutdown Functions
38. Calling User Functions
39. Initialization File Support
40. Where to Go from Here
41. Reference: Some Configuration Macros
42. API Macros
VI. PHP API: Интерфейс для разработчиков расширений
43. Streams API for PHP Extension Authors
VII. FAQ: Часто задаваемые вопросы
44. General Information
45. Mailing lists
46. Obtaining PHP
47. Database issues
48. Installation
49. Build Problems
50. Using PHP
51. PHP and HTML
52. PHP and COM
53. PHP and other languages
54. Migrating from PHP 2 to PHP 3
55. Migrating from PHP 3 to PHP 4
56. Miscellaneous Questions
VIII. Приложения
A. History of PHP and related projects
B. Migrating from PHP 3 to PHP 4
C. Migrating from PHP/FI 2 to PHP 3
D. Отладка PHP
E. Extending PHP
F. Список псевдонимов функций
G. List of Reserved Words
H. List of Resource Types
I. List of Supported Protocols/Wrappers
J. List of Parser Tokens
K. Об этом руководстве
L. Что отсутствует в этом руководстве

Предисловие

PHP, что означает "PHP: Hypertext Preprocessor" ("PHP: Препроцессор гипертекста"), является широко используемым языком программирования общего назначения с открытым исходным кодом, внедряемым в HTML. Его синтаксис основан на синтаксисе языков C, Java и Perl и является легким для изучения. Главная цель языка состоит в предоставлении веб-разработчикам возможности быстро создавать динамически генерируемые веб-страницы. Кроме того, возможности PHP не ограничиваются только этим применением.

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

Вы можете загрузить это руководство в нескольких форматах по адресу http://www.php.net/docs.php. Файлы, доступные для загрузки по этому адресу, обновляются по мере внесения изменений в руководство. За более подробной информацией о том, каким образом ведется документирование, обратитесь к приложению 'Об этом руководстве'.

Обратитесь также к главе История PHP.


Глава 1. Введение

Что такое PHP?

PHP (рекурсивный акроним словосочетания "PHP: Hypertext Preprocessor") - это широко используемый язык программирования общего назначения с открытым исходным кодом. PHP сконструирован специально для ведения Web-разработок и может внедряться в HTML-код.

Простой ответ, но что он может означать? Вот пример:

Пример 1-1. Пример программирования на PHP

<html>
    <head>
        <title>Пример</title>
    </head>
    <body>

        <?php 
        echo "Привет, я - скрипт PHP!"; 
        ?>

    </body>
</html>

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

Значительным отличием PHP от какого-либо кода, выполняющегося на стороне клиента, например, JavaScript, является то, что PHP-скрипты выполняются на сервере. Если бы у вас на сервере был размещен скрипт, подобный вышеприведенному, клиент получил бы только результат выполнения скрипта, причем он не смог бы выяснить, какой именно код выполняется. Вы даже можете сконфигурировать свой сервер таким образом, чтобы HTML-файлы обрабатывались процессором PHP, так что клиенты даже не смогут узнать, получают ли они обычный HTML-файл или результат выполнения скрипта.

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

Хотя PHP, главным образом, предназначен для работы в среде web-серверов, область его применения не ограничивается только этим. Читайте дальше и не пропустите главу Возможности PHP.


Возможности PHP

PHP может все. Главным образом, область применения PHP сфокусирована на написание скриптов, работающих на стороне сервера; таким образом, PHP способен выполнять всё то, что выполняет любая другая программа CGI, например, обрабатывать данных форм, генерировать динамические страницы или отсылать и принимать cookies. Но PHP способен выполнять и множество других задач.

Существуют три основных области, где используется PHP.

  • Создание скриптов для выполнения на стороне сервера. PHP наиболее широко используется именно таким образом. Все, что вам понадобится, это парсер PHP (в виде программы CGI или серверного модуля), вебсервер и броузер. Чтобы вы могли просматривать результаты выполнения PHP-скриптов в броузере, вам нужен работающий вебсервер и установленный PHP. За более подробными сведениями обратитесь к главе Советы по установке.

  • Создание скриптов для выполнения в командной строке. Вы можете создать PHP-скрипт, способный запускаться вне зависимости от вебсервера и броузера. Все, что вам потребуется - парсер PHP. Такой способ использования PHP идеально подходит для скриптов, которые должны выполняться регулярно, например, с помощью cron (на платформах *nix или Linux) или с помощью планировщика задач (Task Scheduler) на платформах Windows. Эти скрипты также могут быть использованы в задачах простой обработки текстов. За дополнительной информацией обращайтесь к главе Использование PHP в среде командной строки.

  • Создание приложений GUI, выполняющихся на стороне клиента. Возможно, PHP является не самым лучшим языком для создания подобных приложений, но, если вы очень хорошо знаете PHP и хотели бы использовать некоторые его возможности в своих клиент-приложениях, вы можете использовать PHP-GTK для создания таких приложений. Подобным образом вы можете создавать и кросс-платформенные приложения. PHP-GTK является расширением PHP и не поставляется вместе с дистрибутивом PHP. Если вы заинтересованы, посетите сайт PHP-GTK.

PHP доступен для большинства операционных систем, включая Linux, многие модификации Unix (такие, как HP-UX, Solaris и OpenBSD), Microsoft Windows, Mac OS X, RISC OS, и многих других. (Совершенно точно, что существует версия PHP для OS/2. Неизвестно, правда, насколько соответствующая нынешним реалиям - Прим.перев.) Также в PHP включена поддержка большинства современных вебсерверов, таких, как Apache, Microsoft Internet Information Server, Personal Web Server, серверов Netscape и iPlanet, сервера Oreilly Website Pro, Caudium, Xitami, OmniHTTPd и многих других. Для большинства серверов PHP поставляется в качестве модуля, для других, поддерживающих стандарт CGI, PHP может функционировать в качестве процессора CGI.

Таким образом, выбирая PHP, вы получаете свободу выбора операционной системы и вебсервера. Кроме того, у вас появляется выбор между использованием процедурного или объектно-ориентированного программирования или же их сочетания. Несмотря на то, что текущая версия PHP поддерживает не все особенности ООП, многие библиотеки кода и большие приложения (включая библиотеку PEAR) написаны только с использованием ООП.

PHP способен не только выдавать HTML. Возможности PHP включают формирование изображений, файлов PDF и даже роликов Flash (с использованием libswf и Ming), создаваемых "на лету". PHP также способен выдавать любые текстовые данные, такие, как XHTML и другие XML-файлы. PHP способен осуществлять автоматическую генерацию таких файлов и сохранять их в файловой системе вашего сервера вместо того, чтобы отдавать клиенту, организуя, таким образом, кеш динамического содержания, расположенный на стороне сервера.

Одним из значительных преимуществ PHP является поддержка широкого круга баз данных. Создание скрипта, использующего базы данных, - невероятно просто. В настоящее время PHP поддерживает следующие базы данных:

Adabas DIngresOracle (OCI7 и OCI8)
dBaseInterBaseOvrimos
EmpressFrontBasePostgreSQL
FilePro (только чтение)mSQLSolid
HyperwaveDirect MS-SQLSybase
IBM DB2MySQLVelocis
InformixODBCUnix dbm

Также в PHP включена поддержка DBX для работы на абстрактном уровне, так что вы можете работать с любой базой данных, использующих DBX. Кроме того, PHP поддерживает ODBC (Open Database Connection standard), таким образом, вы можете работать с любой базой данных, поддерживающей этот всемирно признанный стандарт.

PHP также поддерживает "общение" с другими сервисами с использованием таких протоколов, как LDAP, IMAP, SNMP, NNTP, POP3, HTTP, COM (на платформах Windows) и многих других. Кроме того, вы получаете возможность работать с сетевыми сокетами "напрямую". PHP поддерживает стандарт обмена сложными структурами данных WDDX. Обращая внимание на взаимодействие между различными языками, следует упомянуть о поддержке объектов Java и возможности их использования в качестве объектов PHP. Для доступа к удаленным объектам вы можете использовать расширение CORBA.

PHP включает средства обработки текстовой информации, начиная с регулярных выражений Perl или POSIX Extended и заканчивая парсером документов XML. Для парсинга XML используются стандарты SAX и DOM. Для преобразования документов XML вы можете использовать расширение XSLT.

Используя PHP в области электронной коммерции, вы обратите внимание на функции осуществления платежей Cybercash, CyberMUT, VeriSign Payflow Pro и CCVS.

Последним по порядку, но не по значению, является поддержка многих других расширений, таких, как функции поисковой машины mnoGoSearch, функции IRC Gateway, функции для работы со сжатыми файлами (gzip, bz2), функции календарных вычислений, функции перевода...

Как вы видите, этой страницы не хватит для того, чтобы перечислить все, что может предложить вам PHP. Читайте следующую главу, Установка PHP и обратитесь к главе Справочник по функциям за более подробными сведениями о перечисленных выше расширениях.


Глава 2. Краткое руководство

В данном кратком руководстве на примерах объясняются основы PHP. Это руководство включает в себя только создание динамических Web-страниц с помощью PHP, однако реальная область применения PHP гораздо шире. В разделе "Что может PHP" приведена дополнительная информация.

Созданные с использованием PHP Web-страницы обрабатываются, как обычные HTML-страницы. Их можно создавать и изменять точно таким же образом, как и обычные страницы на HTML.


Что потребуется?

В данном руководстве мы предполагаем, что ваш сервер имеет поддержку PHP и что все файлы, заканчивающиеся на .php, обрабатываются PHP. В большинстве серверов это расширение используется для PHP по умолчанию, но все-таки не лишним будет уточнить это у вашего администратора сервера. Если ваш сервер поддерживает PHP, то у вас есть все, что требуется. Просто создавайте ваши файлы .php и размещайте их в вашем каталоге Web-сервера - они будут обрабатываться автоматически. Не нужно ничего компилировать, не нужно никаких дополнительных программ. Считайте файлы PHP обычными файлами HTML с набором новых "волшебных" тегов, которые позволяют вам делать все, что угодно.


Первая страница на PHP

Создайте файл с именем hello.php в корневом каталоге ваших документов Web-сервера и запишите в него следующее:

Пример 2-1. Первый скрипт на PHP: hello.php

<html>
 <head>
  <title>Тестируем PHP</title>
 </head>
 <body>
 <?php echo "Привет!<p>"; ?>
 </body>
</html>

Эта программа выведет следующее:
<html>
 <head>
  <title>Тестируем PHP</title>
 </head>
 <body>
 Привет!<p>
 </body>
</html>

Заметим, что сходства со скриптами на CGI нет. Файл не обязан быть выполнимым или отмеченным любым другим образом. Это просто обычный файл HTML, в котором есть набор специальных тегов, делающих много интересного.

Эта программа чрезвычайно проста, и для создания настолько простой странички даже необязательно использовать PHP. Все что она делает - это выводит "Привет! с использованием функции PHP echo().

Если у вас этот пример не отображает ничего или выводит окно загрузки, или если вы видите весь этот файл в текстовом виде, то весьма вероятно, что ваш Web-сервер не имеет поддержки PHP. Попросите вашего администратора сервера включить такую поддержку. Предложите ему инструкцию по установке - раздел "Установка" данной документации. Если же вы хотите разрабатывать скрипты на PHP дома, то вам в раздел необходимые файлы. Дома можно разрабатывать скрипты с использованием любой операционной системы, но вам понадобится установить соответствующий Web-сервер.

Цель примера - показать формат специальных тегов PHP. В этом примере мы использовали <?php в качестве открывающего тега, затем шли команды PHP, завершающиеся закрывающим тегом ?>. Таким образом можно сколько угодно раз переходить к коду PHP в файле HTML.

Пара слов о текстовых редакторах: Существует множество текстовых редакторов и интегрированных сред разработки (IDE), в которых вы можете создавать и редактировать файлы PHP. Список некоторых редакторов содержится в разделе "Список редакторов PHP". Если вы хотите порекомендовать какой-либо редактор, посетите данную страницу и попросите добавить данный редактор в список.

Пара слов о текстовых процессорах: Текстовые процессоры (StarOffice Writer, Microsoft Word, Abiword и др.) в большинстве случаев не подходят для редактирования файлов PHP.

Если вы используете текстовый процессор для создания скриптов на PHP, вы должны быть уверены, что сохраняете файл, как ЧИСТО ТЕКСТОВЫЙ. В противном случае PHP не сможет обработать и выполнить вашу программу.

Пара слов о "Блокноте" Windows: При написании скриптов PHP с использованием встроенного "Блокнота" Windows необходимо сохранять файлы с расширением .php. "Блокнот" автоматически добавляет расширение .txt. Для обхода этой проблемы существует несколько методов.

Можно поместить название файла в кавычки (пример: "hello.php").

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


Делаем что-нибудь полезное

Давайте сделаем что-нибудь полезное. К примеру, определим, какой браузер использует тот, кто смотрит в данный момент нашу страницу. Для этого мы проверим строку с именем браузера, посылаемую нам в HTTP-запросе. Эта информация хранится в переменной. Переменные в PHP всегда предваряются знаком доллара. Интересующая нас в данный момент переменная называется $_SERVER["HTTP_USER_AGENT"].

Пару слов об автоматической глобализации переменных в PHP: $_SERVER - специальная зарезервированная переменная PHP, которая содержит всю информацию, полученную от Web-сервера. Она является автоглобализованной (или суперглобальной). Для более подробной информации смотрите раздел "Суперглобальные переменные". Эти специальные переменные появились в PHP, начиная с версии 4.1.0. До этого использовались массивы $HTTP_*_VARS, такие, как $HTTP_SERVER_VARS. Эти массивы, несмотря на то, что они уже устарели, до сих пор существуют (см. замечания по старым программам).

Для вывода данной переменной мы сделаем так:

Пример 2-2. Вывод значения переменной (элемента массива)

<?php echo $_SERVER["HTTP_USER_AGENT"]; ?>

Пример вывода данной программы:
Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)

В PHP есть огромное количество типов переменных. В предыдущем примере мы печатали элемент массива. Массивы в PHP являются очень мощным средством.

$_SERVER - просто переменная, которая предоставлена вам языком PHP. Список таких переменных можно посмотреть в разделе "Зарезервированные переменные". А можно получить их полный список с помощью такой программы:

Пример 2-3. Показываем все стандартные переменные с помощью функции phpinfo()

<?php phpinfo(); ?>

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

Внутрь тегов PHP можно помещать множество команд и создавать кусочки кода, делающие гораздо большее, чем просто вывод на экран. К примеру, если мы хотим сделать проверку на Internet Explorer, мы можем поступить так:

Пример 2-4. Пример использования управляющих структур и функций

<?php
if (strstr($_SERVER["HTTP_USER_AGENT"], "MSIE")) {
	echo "Вы используете Internet Explorer<br />";
}
?>

Пример вывода данной программы:
You are using Internet Explorer<br />

Здесь мы показали несколько новых элементов. Во-первых, здесь есть команда if. Если вам знаком основной синтаксис языка C, то вы уже заметили что-то схожее. Если же вы не знаете C или подобного по синтаксису языка, то лучший вариант - взять какую-либо книжку по PHP и прочитать ее. Другой вариант - почитать раздел "Описание языка" данного руководства. Список книг по PHP можно найти здесь: http://www.php.net/books.php.

Во-вторых, здесь есть вызов функции strstr(). strstr() - встроенная в PHP функция, которая ищет одну строку в другой. В данном случае мы ищем строку "MSIE" в $_SERVER["HTTP_USER_AGENT"]. Если строка не найдена, эта функция возвращает FALSE, если найдена - TRUE. Если она вернет TRUE, то условие в if окажется истинным, и код в командных скобках ({ }) выполнится. В противном случае данный код не выполняется. Попробуйте создать аналогичные примеры с использованием команд if, else, и других функций, таких, как strtoupper() и strlen(). Также примеры содержатся во многих описаниях функций в данном руководстве.

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

Пример 2-5. Смешение режимов HTML и PHP

<?php
if (strstr($_SERVER["HTTP_USER_AGENT"], "MSIE")) {
?>
<h3>strstr вернул true</h3>
<center><b>Вы используете Internet Explorer</b></center>
<?php
} else {
?>
<h3>strstr вернул false</h3>
<center><b>Вы не используете Internet Explorer</b></center>
<?php
}
?>

Пример вывода данной программы:
<h3>strstr вернул true</h3>
<center><b>Вы используете Internet Explorer</b></center>

Вместо использования команды PHP echo для вывода, мы вышли из режима кода и послали содержимое HTML. Важный момент здесь - то, что логическая структура кода PHP при этом не теряется. Только одна HTML-часть будет послана клиенту в зависимости от результата функции strstr() (другими словами, в зависимости от того, найдена строка "MSIE" или нет).


Работа с формами

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

Пример 2-6. Простейшая форма HTML

<form action="action.php" method="POST">
 Ваше имя: <input type="text" name="name" />
 Ваш возраст: <input type="text" name="age" />
 <input type="submit">
</form>

В этой форме нет ничего особенного. Это обычная форма HTML без каких-либо специальных тегов. Когда пользователь заполнит форму и нажмет кнопку отправки, будет вызвана страница action.php. В этом файле может быть что-то вроде:

Пример 2-7. Выводим данные нашей формы

Здравствуйте, <?php echo $_POST["name"]; ?>.
Вам <?php echo $_POST["age"]; ?> лет.

Пример вывода данной программы:
Здравствуйте, Сергей.
Вам 30 лет.

Принцип работы данного кода прост и понятен. Переменные The $_POST["name"] и $_POST["age"] автоматически установлены для вас средствами PHP. Ранее мы использовали переменную $_SERVER, здесь же мы точно также используем суперглобальную переменную $_POST, которая содержит все POST-данные. Заметим, что метод отправки нашей формы - POST. Если бы мы использовали метод GET, то информация нашей формы была бы в суперглобальной переменной $_GET. Также можно использовать переменную $_REQUEST, если источник данных не имеет значения. Эта переменная содержит смесь данных GET, POST, COOKIE и FILE. Также советуем взглянуть на описание функции import_request_variables().


Использование старых программ с новыми версиями PHP

Сейчас PHP является популярным языком сценариев (скриптов). Становится все больше и больше распространяемых кусочков кода, которые вы можете использовать в своих скриптах. В большинстве случаев разработчики PHP старались сохранить совместимость с предыдущими версиями так, что код, написанный для более старой версии будет идеально работать и с новыми версиями языка без каких-либо изменений. Однако случается так, что изменения все-таки необходимы.

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

  • Объявление массивов $HTTP_*_VARS устаревшими. Эти массивы требовали глобализации в функциях и процедурах. Новые суперглобальные массивы были введены, начиная с PHP 4.1.0. Это: $_GET, $_POST, $_COOKIE, $_SERVER, $_ENV, $_REQUEST, и $_SESSION. Более старые массивы $HTTP_*_VARS, такие, как $HTTP_POST_VARS, существуют со времен PHP 3 и, вероятно, будут еще долго существовать для сохранения совместимости.

  • Внешние переменные больше не глобализуются по умолчанию. Другими словами, директива register_globals в php.ini по умолчанию отключена ("off"), начиная с PHP 4.2.0. Рекомендуемый метод доступа к таким переменным - суперглобальные массивы, описанные выше. Более старые программы, книги и руководства могут считать, что данная директива включена ("on"). К примеру, переменная $id может поступать из строки URL http://www.example.com/foo.php?id=42. Когда указанная директива выключена, $id доступна лишь как $_GET['id'].

Для дополнительной информации касательно изменений, связанных с переменными, смотрите раздел "Предопределенные переменные" и ссылки этого раздела.


Что дальше?

То, что вы узнали, поможет вам понять большую часть руководства и разобраться в большинстве приведенных примеров программ. Другие примеры находятся на различных сайтах, ссылки на которые можно найти на php.net: http://www.php.net/links.php.


Глава 3. Установка


General Installation Considerations

Before installing first, you need to know what do you want to use PHP for. There are three main fields you can use PHP, as described in the What can PHP do? section:

  • Server-side scripting

  • Command line scripting

  • Client-side GUI applications

For the first and most common form, you need three things: PHP itself, a web server and a web browser. You probably already have a web browser, and depending on your operating system setup, you may also have a web server (eg. Apache on Linux or IIS on Windows). You may also rent webspace at a company. This way, you don't need to set up anything on your own, only write your PHP scripts, upload it to the server you rent, and see the results in your browser.

While setting up the server and PHP on your own, you have two choices for the method of connecting PHP to the server. For many servers PHP has a direct module interface (also called SAPI). These servers include Apache, Microsoft Internet Information Server, Netscape and iPlanet servers. Many other servers have support for ISAPI, the Microsoft module interface (OmniHTTPd for example). If PHP has no module support for your web server, you can always use it as a CGI processor. This means you set up your server to use the command line executable of PHP (php.exe on Windows) to process all PHP file requests on the server.

If you are also interested to use PHP for command line scripting (eg. write scripts autogenerating some images for you offline, or processing text files depending on some arguments you pass to them), you always need the command line executable. For more information, read the section about writing command line PHP applications. In this case, you need no server and no browser.

With PHP you can also write client side GUI applications using the PHP-GTK extension. This is a completely different approach than writing web pages, as you do not output any HTML, but manage windows and objects within them. For more information about PHP-GTK, please visit the site dedicated to this extension. PHP-GTK is not included in the official PHP distribution.

From now on, this section deals with setting up PHP for web servers on Unix and Windows with server module interfaces and CGI executables.

Downloading PHP, the source code, and binary distributions for Windows can be found at http://www.php.net/. We recommend you to choose a mirror nearest to you for downloading the distributions.


Unix/HP-UX installs

This section contains notes and hints specific to installing PHP on HP-UX systems.

Пример 3-1. Installation Instructions for HP-UX 10

From: paul_mckay@clearwater-it.co.uk
04-Jan-2001 09:49
(These tips are for PHP 4.0.4 and Apache v1.3.9) 

So you want to install PHP and Apache on a HP-UX 10.20 box? 

1. You need gzip, download a binary distribution from
http://hpux.connect.org.uk/ftp/hpux/Gnu/gzip-1.2.4a/gzip-1.2.4a-sd-10.20.depot.Z
uncompress the file and install using swinstall 

2. You need gcc, download a binary distribution from 
http://gatekeep.cs.utah.edu/ftp/hpux/Gnu/gcc-2.95.2/gcc-2.95.2-sd-10.20.depot.gz 
gunzip this file and install gcc using swinstall. 

3. You need the GNU binutils, you can download a binary distribution from 
http://hpux.connect.org.uk/ftp/hpux/Gnu/binutils-2.9.1/binutils-2.9.1-sd-10.20.depot.gz 
gunzip and install using swinstall. 

4. You now need bison, you can download a binary distribution from 
http://hpux.connect.org.uk/ftp/hpux/Gnu/bison-1.28/bison-1.28-sd-10.20.depot.gz 
install as above. 

5. You now need flex, you need to download the source from one of the
http://www.gnu.org mirrors. It is in the non-gnu directory of the ftp site. 
Download the file, gunzip, then tar -xvf it. Go into the newly created flex
directory and do a ./configure, then a make, and then a make install 

If you have errors here, it's probably because gcc etc. are not in your
PATH so add them to your PATH. 

Right, now into the hard stuff. 

6. Download the PHP and apache sources. 

7. gunzip and tar -xvf them. 

We need to hack a couple of files so that they can compile ok. 

8. Firstly the configure file needs to be hacked because it seems to lose
track of the fact that you are a hpux machine, there will be a
better way of doing this but a cheap and cheerful hack is to put 
    lt_target=hpux10.20 
on line 47286 of the configure script. 

9. Next, the Apache GuessOS file needs to be hacked. Under
apache_1.3.9/src/helpers change line 89 from 
    "echo "hp${HPUXMACH}-hpux${HPUXVER}"; exit 0" 
to: 
    "echo "hp${HPUXMACH}-hp-hpux${HPUXVER}"; exit 0" 
    
10. You cannot install PHP as a shared object under HP-UX so you must compile
it as a static, just follow the instructions at the Apache page. 

11. PHP and apache should have compiled OK, but Apache won't start. you need
to create a new user for Apache, eg www, or apache. You then change lines 252
and 253 of the conf/httpd.conf in Apache so that instead of 
    User nobody 
    Group nogroup 
you have something like 
    User www 
    Group sys 

This is because you can't run Apache as nobody under hp-ux. 
Apache and PHP should then work. 

Hope this helps somebody,
Paul Mckay.

Unix/Linux installs

This section contains notes and hints specific to installing PHP on Linux distributions.


Using Packages

Many Linux distributions have some sort of package installation system, such as RPM. This can assist in setting up a standard configuration, but if you need to have a different set of features (such as a secure server, or a different database driver), you may need to build PHP and/or your webserver. If you are unfamiliar with building and compiling your own software, it is worth checking to see whether somebody has already built a packaged version of PHP with the features you need.


Unix/Mac OS X installs

This section contains notes and hints specific to installing PHP on Mac OS X Server.


Using Packages

There are a few pre-packaged and pre-compiled versions of PHP for Mac OS X. This can help in setting up a standard configuration, but if you need to have a different set of features (such as a secure server, or a different database driver), you may need to build PHP and/or your web server yourself. If you are unfamiliar with building and compiling your own software, it's worth checking whether somebody has already built a packaged version of PHP with the features you need.


Compiling for OS X server

There are two slightly different versions of Mac OS X, client and server. The following is for OS X Server.

Пример 3-2. Mac OS X server install

1. Get the latest distributions of Apache and PHP
2. Untar them, and run the configure program on Apache like so.
    ./configure --exec-prefix=/usr \ 
    --localstatedir=/var \ 
    --mandir=/usr/share/man \ 
    --libexecdir=/System/Library/Apache/Modules \ 
    --iconsdir=/System/Library/Apache/Icons \ 
    --includedir=/System/Library/Frameworks/Apache.framework/Versions/1.3/Headers \ 
    --enable-shared=max \ 
    --enable-module=most \ 
    --target=apache 

4. You may also want to add this line: 
    setenv OPTIM=-O2 
    If you want the compiler to do some optimization. 
    
5. Next, go to the PHP 4 source directory and configure it. 
    ./configure --prefix=/usr \ 
    --sysconfdir=/etc \ 
    --localstatedir=/var \ 
    --mandir=/usr/share/man \ 
    --with-xml \ 
    --with-apache=/src/apache_1.3.12 

    If you have any other additions (MySQL, GD, etc.), be sure to add
    them here. For the --with-apache string, put in the path to your 
    apache source directory, for example "/src/apache_1.3.12". 
6. make
7. make install    
    This will add a directory to your Apache source directory under
    src/modules/php4.
    
8. Now, reconfigure Apache to build in PHP 4.
    ./configure --exec-prefix=/usr \ 
    --localstatedir=/var \ 
    --mandir=/usr/share/man \ 
    --libexecdir=/System/Library/Apache/Modules \ 
    --iconsdir=/System/Library/Apache/Icons \ 
    --includedir=/System/Library/Frameworks/Apache.framework/Versions/1.3/Headers \ 
    --enable-shared=max \ 
    --enable-module=most \ 
    --target=apache \ 
    --activate-module=src/modules/php4/libphp4.a 

    You may get a message telling you that libmodphp4.a is out of date.
    If so, go to the src/modules/php4 directory inside your apache
    source directory and run this command: 

    ranlib libmodphp4.a 

    Then go back to the root of the apache source directory and run the
    above configure command again. That'll bring the link table up to
    date. 

9. make

10. make install

11. copy and rename the php.ini-dist file to your "bin" directory from your
    PHP 4 source directory:
    cp php.ini-dist /usr/local/bin/php.ini 

    or (if your don't have a local directory) 

    cp php.ini-dist /usr/bin/php.ini

Compiling for MacOS X client

Those tips are graciously provided by Marc Liyanage.

The PHP module for the Apache web server included in Mac OS X. This version includes support for the MySQL and PostgreSQL databases.

NOTE: Be careful when you do this, you could screw up your Apache web server!

Do this to install:

  • 1. Open a terminal window

  • 2. Type "wget http://www.diax.ch/users/liyanage/software/macosx/libphp4.so.gz", wait for download to finish

  • 3. Type "gunzip libphp4.so.gz"

  • 4. Type "sudo apxs -i -a -n php4 libphp4.so"

Now type "sudo open -a TextEdit /etc/httpd/httpd.conf" TextEdit will open with the web server configuration file. Locate these two lines towards the end of the file: (Use the Find command)
#AddType application/x-httpd-php .php 
   #AddType application/x-httpd-php-source .phps
Remove the two hash marks (#), then save the file and quit TextEdit.

Finally, type "sudo apachectl graceful" to restart the web server.

PHP should now be up and running. You can test it by dropping a file into your "Sites" folder which is called "test.php". Into that file, write this line: "<?php phpinfo() ?>".

Now open up 127.0.0.1/~your_username/test.php in your web browser. You should see a status table with information about the PHP module.


Unix/OpenBSD installs

This section contains notes and hints specific to installing PHP on OpenBSD 3.2.


Using Binary Packages

Using binary packages to install PHP on OpenBSD is the recommended and simplest method. The core package has been separated from the various modules, and each can be installed and removed independently from the others. The files you need can be found on your OpenBSD CD or on the FTP site.

The main package you need to install is php4-core-4.2.3.tgz, which contains the basic engine (plus gettext and iconv). Next, take a look at the module packages, such as php4-mysql-4.2.3.tgz or php4-imap-4.2.3.tgz. You need to use the phpxs command to activate and deactivate these modules in your php.ini.

Пример 3-3. OpenBSD Package Install Example

# pkg_add php4-core-4.2.3.tgz
# /usr/local/sbin/phpxs -s
# cp /usr/local/share/doc/php4/php.ini-recommended /var/www/conf/php.ini
  (add in mysql)
# pkg_add php4-mysql-4.2.3.tgz
# /usr/local/sbin/phpxs -a mysql
  (add in imap)
# pkg_add php4-imap-4.2.3.tgz
# /usr/local/sbin/phpxs -a imap
  (remove mysql as a test)
# pkg_delete php4-mysql-4.2.3
# /usr/local/sbin/phpxs -r mysql
  (install the PEAR libraries)
# pkg_add php4-pear-4.2.3.tgz

Read the packages(7) manual page for more information about binary packages on OpenBSD.


Using Ports

You can also compile up PHP from source using the ports tree. However, this is only recommended for users familiar with OpenBSD. The PHP4 port is split into three sub-directories: core, extensions and pear. The extensions directory generates sub-packages for all of the supported PHP modules. If you find you do not want to create some of these modules, use the no_* FLAVOR. For example, to skip building the imap module, set the FLAVOR to no_imap.


Older Releases

Older releases of OpenBSD used the FLAVORS system to compile up a statically linked PHP. Since it is hard to generate binary packages using this method, it is now deprecated. You can still use the old stable ports trees if you wish, but they are unsupported by the OpenBSD team. If you have any comments about this, the current maintainer for the port is Anil Madhavapeddy.


Unix/Solaris installs

This section contains notes and hints specific to installing PHP on Solaris systems.


Required software

Solaris installs often lack C compilers and their related tools. The required software is as follows:

  • gcc (recommended, other C compilers may work)

  • make

  • flex

  • bison

  • m4

  • autoconf

  • automake

  • perl

  • gzip

  • tar

  • GNU sed

In addition, you will need to install (and possibly compile) any additional software specific to your configuration, such as Oracle or MySQL.


Using Packages

You can simplify the Solaris install process by using pkgadd to install most of your needed components.


Installation on UNIX systems

This section will guide you through the general configuration and installation of PHP on Unix systems. Be sure to investigate any sections specific to your platform or web server before you begin the process.

Prerequisite knowledge and software:

  • Basic UNIX skills (being able to operate "make" and a C compiler, if compiling)

  • An ANSI C compiler (if compiling)

  • flex (for compiling)

  • bison (for compiling)

  • A web server

  • Any module specific components (such as gd, pdf libs, etc.)

There are several ways to install PHP for the Unix platform, either with a compile and configure process, or through various pre-packaged methods. This documentation is mainly focused around the process of compiling and configuring PHP.

The initial PHP setup and configuration process is controlled by the use of the commandline options of the configure script. This page outlines the usage of the most common options, but there are many others to play with. Check out the Complete list of configure options for an exhaustive rundown. There are several ways to install PHP:


Apache Module Quick Reference

PHP can be compiled in a number of different ways, but one of the most popular is as an Apache module. The following is a quick installation overview.

Пример 3-4. Quick Installation Instructions for PHP 4 (Apache Module Version)

1.  gunzip apache_1.3.x.tar.gz
2.  tar xvf apache_1.3.x.tar
3.  gunzip php-x.x.x.tar.gz
4.  tar xvf php-x.x.x.tar
5.  cd apache_1.3.x
6.  ./configure --prefix=/www
7.  cd ../php-x.x.x
8.  ./configure --with-mysql --with-apache=../apache_1.3.x --enable-track-vars
9.  make
10. make install
11. cd ../apache_1.3.x
12. ./configure --activate-module=src/modules/php4/libphp4.a
13. make
14. make install
15. cd ../php-x.x.x
16. cp php.ini-dist /usr/local/lib/php.ini
17. Edit your httpd.conf or srm.conf file and add: 
      AddType application/x-httpd-php .php

18. Use your normal procedure for restarting the Apache server. (You must
    stop and restart the server, not just cause the server to reload by
    use a HUP or USR1 signal.)

Building

When PHP is configured, you are ready to build the CGI executable. The command make should take care of this. If it fails and you can't figure out why, see the Problems section.


Installation on Windows systems

This section applies to Windows 98/Me and Windows NT/2000/XP. PHP will not work on 16 bit platforms such as Windows 3.1 and sometimes we refer to the supported Windows platforms as Win32. Windows 95 is no longer supported as of PHP 4.3.0.

There are two main ways to install PHP for Windows: either manually or by using the InstallShield installer.

If you have Microsoft Visual Studio, you can also build PHP from the original source code.

Once you have PHP installed on your Windows system, you may also want to load various extensions for added functionality.


Windows InstallShield

The Windows PHP installer is available from the downloads page at http://www.php.net/downloads.php. This installs the CGI version of PHP and, for IIS, PWS, and Xitami, configures the web server as well.

Замечание: While the InstallShield installer is an easy way to make PHP work, it is restricted in many aspects, as automatic setup of extensions for example is not supported. The whole set of supported extensions is only available by downloading the zip binary distribution.

Install your selected HTTP server on your system and make sure that it works.

Run the executable installer and follow the instructions provided by the installation wizard. Two types of installation are supported - standard, which provides sensible defaults for all the settings it can, and advanced, which asks questions as it goes along.

The installation wizard gathers enough information to set up the php.ini file and configure the web server to use PHP. For IIS and also PWS on NT Workstation, a list of all the nodes on the server with script map settings is displayed, and you can choose those nodes to which you wish to add the PHP script mappings.

Once the installation has completed the installer will inform you if you need to restart your system, restart the server, or just start using PHP.

Внимание

Be aware, that this setup of PHP is not secure. If you would like to have a secure PHP setup, you'd better go on the manual way, and set every option carefully. This automatically working setup gives you an instantly working PHP installation, but it is not meant to be used on online servers.


Manual Installation Steps

This install guide will help you manually install and configure PHP on your Windows webserver. The original version of this guide was compiled by Bob Silva, and can be found at http://www.umesd.k12.or.us/php/win32install.html. You need to download the zip binary distribution from the downloads page at http://www.php.net/downloads.php.

PHP 4 for Windows comes in three flavours - a CGI executable (php.exe), a CLI executable (sapi/php.exe) and some other SAPI modules:

php4apache.dll - Apache 1.3.x module
php4apache2.dll - Apache 2.0.x module
php4isapi.dll - ISAPI Module for ISAPI compliant webservers like IIS 4.0/PWS 4.0 or newer.
php4nsapi.dll - Netscape/iPlanet module

The latter form is new to PHP 4, and provides significantly improved performance and some new functionality. The CLI version is designed to use PHP for command line scripting. More information about CLI is available in the chapter about using PHP from the command line

Внимание

The SAPI modules have been significantly improved in the 4.1 release, however, you may find that you encounter possible server errors or other server modules such as ASP failing, in older systems.

DCOM and MDAC requirements: If you choose one of the SAPI modules and use Windows 95, be sure to download and install the DCOM update from the Microsoft DCOM pages. If you use Microsoft Windows 9x/NT4 download the latest version of the Microsoft Data Access Components (MDAC) for your platform. MDAC is available at http://www.microsoft.com/data/.

The following steps should be performed on all installations before any server specific instructions.

  • Extract the distribution file to a directory of your choice, c:\ is a good start. The zip package expands to a foldername like php-4.3.1-Win32 which is assumed to be renamed to php. For the sake of convinience and to be version independant the following steps assume your extracted version of PHP lives in c:\php. You might choose any other location but you probably do not want to use a path in which spaces are included (for example: c:\program files\php is not a good idea). Some web servers will crash if you do. The struture of your directory you extracted the zip file will look like:

c:\php
   |
   +--cli
   |  |
   |  |-php.exe           -- CLI executable - ONLY for commandline scripting
   |
   |
   +--dlls                -- support dlls for extensions --> windows system directory
   |  |
   |  |-expat.dll
   |  |
   |  |-fdftk.dll
   |  |
   |  |-...
   |
   +--extensions          -- extension dlls for PHP
   |  |
   |  |-php_bz2.dll
   |  |
   |  |-php_cpdf.dll
   |  |
   |  |-..
   |
   +--mibs                -- support files for SNMP
   |
   |
   +--openssl             -- support files for Openssl
   |
   |
   +--pdf-related         -- support files for PDF
   |
   |
   +--sapi                -- SAPI dlls
   |  |
   |  |-php4apache.dll
   |  |
   |  |-php4apache2.dll
   |  |
   |  |-php4isapi.dll
   |  |
   |  |-..
   |
   |-install.txt
   |
   |-..
   |
   |-php.exe              -- CGI executable
   |
   |-..
   |
   |-php.ini-dist
   |
   |-php.ini-recommended
   | 
   |-php4ts.dll           -- main dll --> windows system directory
   | 
   |-...

The CGI binary - C:/php/php.exe -, the CLI binary - c:\php\cli\php.exe -, and the SAPI modules - c:\php\sapi\*.dll - rely on the main dll c:\php\php4ts.dll. You have to make sure, that this dll can be found by your PHP installation. The search order for this dll is as follows:

The same directory from where php.exe is called. In case you use a SAPI module the same directory from where your webserver loads the dll (e.g. php4apache.dll).
Any directory in your Windows PATH environment variable.

  • The best bet is to make php4ts.dll available, regardless which interface (CGI or SAPI module) you plan to use. To do so, you have to copy this dll to a directory on your Windows path. The best place is your windows system directory:

    c:\windows\system for Windows 9x/ME
    c:\winnt\system32 for Windows NT/2000 or c:\winnt40\system32 for NT/2000 server
    c:\windows\system32 for Windows XP

    If you plan to use a SAPI module from c:\php\sapi and do not like to copy dlls to your Windows system directory, you have the alternative choice to simply copy php4ts.dll to the sapi folder of your extracted zip package, c:\php\sapi.

  • The next step is to set up a valid configuration file for PHP, php.ini. There are two ini files distributed in the zip file, php.ini-dist and php.ini-recommended. We advise you to use php.ini-recommended, because we optimized the default settings in this file for performance, and security. Read this well documented file carefully and in addition study the ini settings and set every element manually yourself. If you would like to achieve the best security, then this is the way for you, although PHP works fine with these default ini files. Copy your choosen ini-file to a directory where PHP is able to find and rename it to php.ini. By default PHP searchs php.ini in your Windows directory:

    On Windows 9x/ME/XP copy your choosen ini file to your %WINDIR%, which is typically c:\windows.
    On Windows NT/2000 copy your choosen ini file to your %WINDIR% or %SYSTEMROOT%, which is typically c:\winnt or c:\winnt40 for NT/2000 servers.

  • If you're using NTFS on Windows NT, 2000 or XP, make sure that the user running the webserver has read permissions to your php.ini (e.g. make it readable by Everyone).

The following steps are optional.

  • Edit your new php.ini file. If you plan to use OmniHTTPd, do not follow the next step. Set the doc_root to point to your webservers document_root. For example:

    doc_root = c:\inetpub        // for IIS/PWS
    
    doc_root = c:\apache\htdocs // for Apache

  • Choose which extensions you would like to load when PHP starts. See the section about Windows extensions, about how to set up one, and what is already built in. Note that on a new installation it is advisable to first get PHP working and tested without any extensions before enabling them in php.ini.

  • On PWS and IIS, you can set the browscap configuration setting to point to: c:\windows\system\inetsrv\browscap.ini on Windows 9x/Me, c:\winnt\system32\inetsrv\browscap.ini on NT/2000, and c:\windows\system32\inetsrv\browscap.ini on XP.

Following this instructions you are done with the basic steps to setup PHP on Windows. The next step is to choose a webserver and enable it to run PHP. Installation instructions for the following webservers are available:


Building from source

Before getting started, it is worthwhile answering the question: "Why is building on Windows so hard?" Two reasons come to mind:

  1. Windows does not (yet) enjoy a large community of developers who are willing to freely share their source. As a direct result, the necessary investment in infrastructure required to support such development hasn't been made. By and large, what is available has been made possible by the porting of necessary utilities from Unix. Don't be surprised if some of this heritage shows through from time to time.

  2. Pretty much all of the instructions that follow are of the "set and forget" variety. So sit back and try follow the instructions below as faithfully as you can.


Требования

To compile and build PHP you need a Microsoft Development Environment. Microsoft Visuaul C++ 6.0 is recommended. To extract the downloaded files you need a extraction utilitiy (e.g.: Winzip). If you don't already have an unzip utility, you can get a free version from InfoZip.

Before you get started, you have to download...

Finally, you are going to need the source to PHP 4 itself. You can get the latest development version using anonymous CVS, a snapshot or the most recent released source tarball.


Putting it all together

After downloading the required packages you have to extract them in a proper place.

  • Create a working directory where all files end up after extracting, e.g: c:\work.

  • Create the directory win32build under your working directory (c:\work) and unzip win32build.zip into it.

  • Create the directory bindlib_w32 under your working directory (c:\work) and unzip bindlib_w32.zip into it.

  • Extract the downloaded PHP source code into your working directory (c:\work).

Following this steps your directory structure looks like this:

+--c:\work
|  |
|  +--bindlib_w32
|  |  |
|  |  +--arpa
|  |  |
|  |  +--conf
|  |  |
|  |  +--...
|  |
|  +--php-4.x.x
|  |  |
|  |  +--build
|  |  |
|  |  +--...
|  |  |
|  |  +--win32
|  |  |
|  |  +--...
|  |
|  +--win32build
|  |  |
|  |  +--bin
|  |  |
|  |  +--include
|  |  |
|  |  +--lib

Create the directories c:\usr\local\lib. Copy bison.simple from c:\work\win32build\bin to c:\usr\local\lib.

Замечание: Cygwin users may omit the last step. A properly installed Cygwin environment provides the mandatory files bison.simple and bison.exe.


Configure MVC ++

The next step is to configure MVC ++ to prepare for compiling. Launch Microsoft Visual C++, and from the menu select Tools => Options. In the dialog, select the directories tab. Sequentially change the dropdown to Executables, Includes, and Library files. Your entries should look like this:

  • Executable files: c:\work\win32build\bin, Cygwin users: cygwin\bin

  • Include files: c:\work\win32build\include

  • Library files: c:\work\win32build\lib


Build resolv.lib

You must build the resolv.lib library. Decide whether you want to have debug symbols available (bindlib - Win32 Debug) or not (bindlib - Win32 Release). Build the appropriate configuration:

  • For GUI users, launch VC++, and then select File => Open Workspace, navigate to c:\work\bindlib_w32 and select bindlib.dsw. Then select Build=>Set Active Configuration and select the desired configuration. Finally select Build=>Rebuild All.

  • For command line users, make sure that you either have the C++ environment variables registered, or have run vcvars.bat, and then execute one of the following commands:

    • msdev bindlib.dsp /MAKE "bindlib - Win32 Debug"

    • msdev bindlib.dsp /MAKE "bindlib - Win32 Release"

At this point, you should have a usable resolv.lib in either your c:\work\bindlib_w32\Debug or Release subdirectories. Copy this file into your c:\work\win32build\lib directory over the file by the same name found in there.


Compiling

The best way to get started is to build the CGI version.

  • For GUI users, launch VC++, and then select File => Open Workspace and select c:\work\php-4.x.x\win32\php4ts.dsw . Then select Build=>Set Active Configuration and select the desired configuration, either php4ts - Win32 Debug_TS or php4ts - Win32 Release_TS. Finally select Build=>Rebuild All.

  • For command line users, make sure that you either have the C++ environment variables registered, or have run vcvars.bat, and then execute one of the following commands from the c:\work\php-4.x.x\win32 directory:

    • msdev php4ts.dsp /MAKE "php4ts - Win32 Debug_TS"

    • msdev php4ts.dsp /MAKE "php4ts - Win32 Release_TS"

    • At this point, you should have a usable php.exe in either your c:\work\php-4.x.x.\Debug_TS or Release_TS subdirectories.

It is possible to do minor customization to the build process by editing the main/config.win32.h file. For example you can change the builtin extensions, the location of php.ini and

Next you may want to build the CLI version which is designed to use PHP from the command line. The steps are the same as for building the CGI version, except you have to select the php4ts_cli - Win32 Debug_TS or php4ts_cli - Win32 Release_TS project file. After a succcessfull compiling run you will find the php.exe in either the directory Release_TS\cli\ or Debug_TS\cli\.

Замечание: If you want to use PEAR and the comfortable command line installer, the CLI-SAPI is mandatory. For more information about PEAR and the installer read the documantation at the PEAR website.

In order to build the SAPI module (php4isapi.dll) for integrating PHP with Microsoft IIS, set your active configuration to php4isapi-whatever-config and build the desired dll.


Installation of Windows extensions

After installing PHP and a webserver on Windows, you will probably want to install some extensions for added functionality. You can choose which extensions you would like to load when PHP starts by modifying your php.ini. You can also load a module dynamically in your script using dl().

The DLLs for PHP extensions are prefixed with 'php_' in PHP 4 (and 'php3_' in PHP 3). This prevents confusion between PHP extensions and their supporting libraries.

Замечание: In PHP 4.3.1 BCMath, Calendar, COM, Ctype, FTP, MySQL, ODBC, Overload, PCRE, Session, Tokenizer, WDDX, XML and Zlib support is built in. You don't need to load any additional extensions in order to use these functions. See your distributions README.txt or install.txt or this table for a list of built in modules.

Edit your php.ini file:

  • You will need to change the extension_dir setting to point to the directory where your extensions lives, or where you have placed your php_*.dll files. Please do not forget the last backslash. For example:

    extension_dir = c:/php/extensions/

  • Enable the extension(s) in php.ini you want to use by uncommenting the 'extension=php_*.dll' lines in php.ini. This is done by deleting the leading ; form the extension you want to load.

    Пример 3-5. enable Bzip2 extension

    // change the following line from ...
    ;extension=php_bz2.dll
    
    // ... too
    extension=php_bz2.dll

  • Some of the extensions need extra DLLs to work. Couple of them can be found in the distribution package, in the c:\php\dlls\ folder but some, for example Oracle (php_oci8.dll) require DLLs which are not bundled with the distribution package. Copy the bundled DLLs from c:\php\dlls folder to your Windows PATH, safe places are:

    c:\windows\system for Windows 9x/Me
    c:\winnt\system32 for Windows NT/2000
    c:\windows\system32 for Windows XP

    If you have them already installed on your system, overwrite them only if something doesn't work correctly (Before overwriting them, it is a good idea to make a backup of them, or move them to another folder - just in case something goes wrong).

The following table describes some of the extensions available and required additional dlls.

Таблица 3-1. PHP Extensions

ExtensionDescriptionNotes
php_bz2.dllbzip2 compression functionsNone
php_calendar.dllCalendar conversion functionsBuilt in since PHP 4.0.3
php_cpdf.dllClibPDF functionsNone
php_crack.dllCrack functionsNone
php3_crypt.dllCrypt functionsunknown
php_ctype.dllctype family functionsBuilt in since PHP 4.3.0
php_curl.dllCURL, Client URL library functionsRequires: libeay32.dll, ssleay32.dll (bundled)
php_cybercash.dllCybercash payment functionsPHP <= 4.2.0
php_db.dllDBM functionsDeprecated. Use DBA instead (php_dba.dll)
php_dba.dllDBA: DataBase (dbm-style) Abstraction layer functionsNone
php_dbase.dlldBase functionsNone
php3_dbm.dllBerkeley DB2 libraryunknown
php_dbx.dlldbx functions 
php_domxml.dllDOM XML functionsPHP <= 4.2.0 requires: libxml2.dll (bundled)
php_dotnet.dll.NET functionsPHP <= 4.1.1
php_exif.dllRead EXIF headers from JPEGNone
php_fbsql.dllFrontBase functionsPHP <= 4.2.0
php_fdf.dllFDF: Forms Data Format functions.Requires: fdftk.dll (bundled)
php_filepro.dllfilePro functionsRead-only access
php_ftp.dllFTP functionsBuilt-in since PHP 4.0.3
php_gd.dllGD library image functionsNone
php_gd2.dllGD2 library image functionsNone
php_gettext.dllGettext functions PHP <= 4.2.0 requires: gnu_gettext.dll (bundled), PHP >= 4.2.3 requires libintl-1.dll (bundled).
php_hyperwave.dllHyperWave functionsNone
php_iconv.dllICONV characterset conversionRequires: iconv-1.3.dll (bundled), PHP >=4.2.1 iconv.dll
php_ifx.dllInformix functionsRequires: Informix libraries
php_iisfunc.dllIIS management functionsNone
php_imap.dllIMAP POP3 and NNTP functionsPHP 3: php3_imap4r1.dll
php_ingres.dllIngres II functionsRequires: Ingres II libraries
php_interbase.dllInterBase functionsRequires: gds32.dll (bundled)
php_java.dllJava functionsPHP <= 4.0.6 requires: jvm.dll (bundled)
php_ldap.dllLDAP functions PHP <= 4.2.0 requires: libsasl.dll (bundled), PHP >= 4.3.0 requires: libeay32.dll, ssleay32.dll (bundled)
php_mbstring.dllMulti-Byte String functionsNone
php_mcrypt.dllMcrypt Encryption functionsRequires: libmcrypt.dll
php_mhash.dllMhash functionsPHP >= 4.3.0 requires: libmhash.dll (bundled)
php_mime_magic.dllMimetype functionsRequires: magic.mime (bundled)
php_ming.dllMing functions for FlashNone
php_msql.dllmSQL functionsRequires: msql.dll (bundled)
php3_msql1.dllmSQL 1 clientunknown
php3_msql2.dllmSQL 2 clientunknown
php_mssql.dllMSSQL functionsRequires: ntwdblib.dll (bundled)
php3_mysql.dllMySQL functionsBuilt-in in PHP 4
php3_nsmail.dllNetscape mail functionsunknown
php3_oci73.dllOracle functionsunknown
php_oci8.dllOracle 8 functionsRequires: Oracle 8 client libraries
php_openssl.dllOpenSSL functionsRequires: libeay32.dll (bundled)
php_oracle.dllOracle functionsRequires: Oracle 7 client libraries
php_overload.dllObject overloading functionsBuilt in since PHP 4.3.0
php_pdf.dllPDF functionsNone
php_pgsql.dllPostgreSQL functionsNone
php_printer.dllPrinter functionsNone
php_shmop.dllShared Memory functionsNone
php_snmp.dllSNMP get and walk functionsNT only!
php_sockets.dllSocket functionsNone
php_sybase_ct.dllSybase functionsRequires: Sybase client libraries
php_tokenizer.dllTokenizer functionsBuilt in since PHP 4.3.0
php_w32api.dllW32api functionsnone
php_xmlrpc.dllXML-RPC functionsPHP >= 4.2.1 requires: iconv.dll (bundled)
php_xslt.dllXSLT functionsRequires: sablot.dll, expat.dll (bundled)
php_yaz.dllYAZ functionsRequires: yaz.dll (bundled)
php_zib.dllZip File functionsRead only access
php_zlib.dllZLib compression functionsBuilt in since PHP 4.3.0


Servers-CGI/Commandline

The default is to build PHP as a CGI program. This creates a commandline interpreter, which can be used for CGI processing, or for non-web-related PHP scripting. If you are running a web server PHP has module support for, you should generally go for that solution for performance reasons. However, the CGI version enables Apache users to run different PHP-enabled pages under different user-ids. Please make sure you read through the Security chapter if you are going to run PHP as a CGI.

As of PHP 4.3.0, some important additions have happened to PHP. A new SAPI named CLI also exists and it has the same name as the CGI binary. What is installed at {PREFIX}/bin/php depends on your configure line and this is described in detail in the manual section named Using PHP from the command line. For further details please read that section of the manual.


Testing

If you have built PHP as a CGI program, you may test your build by typing make test. It is always a good idea to test your build. This way you may catch a problem with PHP on your platform early instead of having to struggle with it later.


Benchmarking

If you have built PHP 3 as a CGI program, you may benchmark your build by typing make bench. Note that if safe mode is on by default, the benchmark may not be able to finish if it takes longer then the 30 seconds allowed. This is because the set_time_limit() can not be used in safe mode. Use the max_execution_time configuration setting to control this time for your own scripts. make bench ignores the configuration file.

Замечание: make bench is only available for PHP 3.


Using Variables

Some server supplied enviroment variables are not defined in the current CGI/1.1 specification. Only the following variables are defined there; everything else should be treated as 'vendor extensions': AUTH_TYPE, CONTENT_LENGTH, CONTENT_TYPE, GATEWAY_INTERFACE, PATH_INFO, PATH_TRANSLATED, QUERY_STRING, REMOTE_ADDR, REMOTE_HOST, REMOTE_IDENT, REMOTE_USER, REQUEST_METHOD, SCRIPT_NAME, SERVER_NAME, SERVER_PORT, SERVER_PROTOCOL and SERVER_SOFTWARE


Servers-Apache

This section contains notes and hints specific to Apache installs of PHP, both for Unix and Windows versions. We also have instructions and notes for Apache 2 on a separate page.


Details of installing PHP with Apache on Unix

You can select arguments to add to the configure on line 10 below from the Complete list of configure options. The version numbers have been omitted here, to ensure the instructions are not incorrect. You will need to replace the 'xxx' here with the correct values from your files.

Пример 3-6. Installation Instructions (Apache Shared Module Version) for PHP 4

1.  gunzip apache_xxx.tar.gz
2.  tar -xvf apache_xxx.tar
3.  gunzip php-xxx.tar.gz
4.  tar -xvf php-xxx.tar
5.  cd apache_xxx
6.  ./configure --prefix=/www --enable-module=so
7.  make
8.  make install
9.  cd ../php-xxx
10. ./configure --with-mysql --with-apxs=/www/bin/apxs
11. make
12. make install

  If you decide to change your configure options after installation
  you only need to repeat the last three steps. You only need to 
  restart apache for the new module to take effect. A recompile of
  Apache is not needed.

13. cp php.ini-dist /usr/local/lib/php.ini

  You can edit your .ini file to set PHP options.  If
  you prefer this file in another location, use
  --with-config-file-path=/path in step 10.

14. Edit your httpd.conf or srm.conf file and check that these lines are
    present and not commented out:
  
   AddType application/x-httpd-php .php

   LoadModule php4_module        libexec/libphp4.so
 
  You can choose any extension you wish here.  .php is simply the one
  we suggest. You can even include .html, and .php3 can be added for 
  backwards compatibility.
 
  The path on the right hand side of the LoadModule statement must point
  to the path of the PHP module on your system. The above statement is 
  correct for the steps shown above.


15. Use your normal procedure for starting the Apache server. (You must
    stop and restart the server, not just cause the server to reload by
    use a HUP or USR1 signal.)

Depending on your Apache install and Unix variant, there are many possible ways to stop and restart the server. Below are some typical lines used in restarting the server, for different apache/unix installations. You should replace /path/to/ with the path to these applications on your systems.

1. Several Linux and SysV variants:
/etc/rc.d/init.d/httpd restart

2. Using apachectl scripts:
/path/to/apachectl stop
/path/to/apachectl start

3. httpdctl and httpsdctl (Using OpenSSL), similar to apachectl:
/path/to/httpsdctl stop
/path/to/httpsdctl start

4. Using mod_ssl, or another SSL server, you may want to manually
stop and start:
/path/to/apachectl stop
/path/to/apachectl startssl

The locations of the apachectl and http(s)dctl binaries often vary. If your system has locate or whereis or which commands, these can assist you in finding your server control programs.

Different examples of compiling PHP for apache are as follows:

./configure --with-apxs --with-pgsql

This will create a libphp4.so shared library that is loaded into Apache using a LoadModule line in Apache's httpd.conf file. The PostgreSQL support is embedded into this libphp4.so library.

./configure --with-apxs --with-pgsql=shared

This will create a libphp4.so shared library for Apache, but it will also create a pgsql.so shared library that is loaded into PHP either by using the extension directive in php.ini file or by loading it explicitly in a script using the dl() function.

./configure --with-apache=/path/to/apache_source --with-pgsql

This will create a libmodphp4.a library, a mod_php4.c and some accompanying files and copy this into the src/modules/php4 directory in the Apache source tree. Then you compile Apache using --activate-module=src/modules/php4/libphp4.a and the Apache build system will create libphp4.a and link it statically into the httpd binary. The PostgreSQL support is included directly into this httpd binary, so the final result here is a single httpd binary that includes all of Apache and all of PHP.

./configure --with-apache=/path/to/apache_source --with-pgsql=shared

Same as before, except instead of including PostgreSQL support directly into the final httpd you will get a pgsql.so shared library that you can load into PHP from either the php.ini file or directly using dl().

When choosing to build PHP in different ways, you should consider the advantages and drawbacks of each method. Building as a shared object will mean that you can compile apache separately, and don't have to recompile everything as you add to, or change, PHP. Building PHP into apache (static method) means that PHP will load and run faster. For more information, see the Apache webpage on DSO support.

Замечание: Apache's default httpd.conf currently ships with a section that looks like this:

User nobody
Group "#-1"

Unless you change that to "Group nogroup" or something like that ("Group daemon" is also very common) PHP will not be able to open files.

Замечание: Make sure you specify the installed version of apxs when using --with-apxs=/path/to/apxs. You must NOT use the apxs version that is in the apache sources but the one that is actually installed on your system.


Installing PHP on Windows with Apache 1.3.x

There are two ways to set up PHP to work with Apache 1.3.x on Windows. One is to use the CGI binary (php.exe), the other is to use the Apache module DLL. In either case you need to stop the Apache server, and edit your httpd.conf to configure Apache to work with PHP.

It is worth noting here that now the SAPI module has been made more stable under windows, we recommend it's use above the CGI binary, since it is more transparent and secure.

Although there can be a few variations of configuring PHP under Apache, these are simple enough to be used by the newcomer. Please consult the Apache Docs for further configuration directives.

If you unziped the PHP package to c:\php\ as described in the Manual Installation Steps section, you need to insert these lines to your Apache configuration file to set up the CGI binary:

  • ScriptAlias /php/ "c:/php/"

  • AddType application/x-httpd-php .php .phtml

  • Action application/x-httpd-php "/php/php.exe"

Note that the second line in the list above can be found in the actual versions of httpd.conf, but it is commented out. Remember also to substitute the c:/php/ for your actual path to PHP.

Внимание

By using the CGI setup, your server is open to several possible attacks. Please read our CGI security section to learn how to defend yourself from attacks.

If you would like to use PHP as a module in Apache, be sure to copy php4ts.dll to the windows/system (for Windows 9x/Me), winnt/system32 (for Windows NT/2000) or windows/system32 (for Windows XP) directory, overwriting any older file. Then you should add the following lines to your Apache httpd.conf file:

  • Open httpd.conf with your favorite editor and locate the LoadModule directive and add the following line at the end of the list: LoadModule php4_module c:/php/sapi/php4apache.dll

  • You may find after using the windows installer for Apache that you need to define the AddModule directive for mod_php4.c. This is especially important if the ClearModuleList directive is defined, which you will find by scrolling down a few lines. You will see a list of AddModule entries, add the following line at the end of the list: AddModule mod_php4.c

  • Search for a phrase similar to # AddType allows you to tweak mime.types. You will see some AddType entries, add the following line at the end of the list: AddType application/x-httpd-php .php. You can choose any extension you want to parse through PHP here. .php is simply the one we suggest. You can even include .html, and .php3 can be added for backwards compatibility.

After changing the configuration file, remember to restart the server, for example, NET STOP APACHE followed by NET START APACHE, if you run Apache as a Windows Service, or use your regular shortcuts.

There are two ways you can use the source code highlighting feature, however their ability to work depends on your installation. If you have configured Apache to use PHP as an SAPI module, then by adding the following line to your httpd.conf (at the same place you inserted AddType application/x-httpd-php .php, see above) you can use this feature: AddType application/x-httpd-php-source .phps.

If you chose to configure Apache to use PHP as a CGI binary, you will need to use the show_source() function. To do this simply create a PHP script file and add this code: <?php show_source ("original_php_script.php"); ?>. Substitute original_php_script.php with the name of the file you wish to show the source of.

Замечание: On Win-Apache all backslashes in a path statement such as "c:\directory\file.ext", must be converted to forward slashes, as "c:/directory/file.ext".


Servers-Apache 2.0

This section contains notes and hints specific to Apache 2.0 installs of PHP, both for Unix and Windows versions.

Внимание

Do not use Apache 2.0 and PHP in a production environment neither on Unix nor on Windows.

You are highly encouraged to take a look at the Apache Documentation to get a basic understanding of the Apache 2.0 Server.


PHP and Apache 2.0 compatibility notes

The following versions of PHP are known to work with the most recent version of Apache 2.0:

These versions of PHP are compatible to Apache 2.0.40 and later.

Замечание: Apache 2.0 SAPI-support started with PHP 4.2.0. PHP 4.2.3 works with Apache 2.0.39, don't use any other version of Apache with PHP 4.2.3. However, the recommended setup is to use PHP 4.3.0 or later with the most recent version of Apache2.

All mentioned versions of PHP will work still with Apache 1.3.x.


PHP and Apache 2 on Linux

Download the most recent version of Apache 2.0 and a fitting PHP version from the above mentioned places. This quick guide covers only the basics to get started with Apache 2.0 and PHP. For more information read the Apache Documentation. The version numbers have been omitted here, to ensure the instructions are not incorrect. You will need to replace the 'NN' here with the correct values from your files.

Пример 3-7. Installation Instructions (Apache 2 Shared Module Version)

1.  gzip -d httpd-2_0_NN.tar.gz
2.  tar xvf httpd-2_0_NN.tar
3.  gunzip php-NN.tar.gz
4.  tar -xvf php-NN.tar
5.  cd httpd-2_0_NN
6.  ./configure --enable-so
7.  make
8.  make install

    Now you have Apache 2.0.NN available under /usr/local/apache2,
    configured with loadable module support and the standard MPM prefork.
    To test the installation use your normal procedure for starting
    the Apache server, e.g.:
    /usr/local/apache2/bin/apachectl start
    and stop the server to go on with the configuration for PHP:
    /usr/local/apache2/bin/apachectl stop.

9.  cd ../php4-NN
10. ./configure --with-apxs2=/usr/local/apache2/bin/apxs
11. make
12. make install
13. cp php.ini-dist /usr/local/lib/php.ini

    Edit your php.ini file to set PHP options. If
    you prefer this file in another location, use
    --with-config-file-path=/path in step 10.

14. Edit your httpd.conf file and check that these lines are
    present:
  
   LoadModule php4_module modules/libphp4.so
   AddType application/x-httpd-php .php

  You can choose any extension you wish here. .php is simply the one
  we suggest.
 
  The path on the right hand side of the LoadModule statement must point
  to the path of the PHP module on your system. The above statement is
  correct for the steps shown above.

15. Use your normal procedure for starting the Apache server, e.g.:
   /usr/local/apache2/bin/apachectl start

Following the steps above you will have a running Apache 2.0 with support for PHP as SAPI module. Of course there are many more configuration options available for both, Apache and PHP. For more information use ./configure --help in the corresponding source tree. In case you wish to build a multithreaded version of Apache 2.0 you must overwrite the standard MPM-Module prefork either with worker or perchild. To do so append to your configure line in step 6 above either the option --with-mpm=worker or --with-mpm=perchild. Take care about the consequences and understand what you are doing. For more information read the Apache documentation about the MPM-Modules.

Замечание: To build a multithreaded version of Apache your system must support threads. This also implies to build PHP with experimental Zend Thread Safety (ZTS). Therefore not all extensions might be available. The recommended setup is to build Apache with the standard prefork MPM-Module.


PHP and Apache 2.0 on Windows

Consider to read the Windows specific notes for Apache 2.0.

Внимание

Apache 2.0 is designed to run on Windows NT 4.0, Windows 2000 or Windows XP. At this time, support for Windows 9x is incomplete. Apache 2.0 is not expected to work on those platforms at this time.

Download the most recent version of Apache 2.0 and a fitting PHP version from the above mentioned places. Follow the Manual Installation Steps and come back to go on with the integration of PHP and Apache.

There are two ways to set up PHP to work with Apache 2.0 on Windows. One is to use the CGI binary the other is to use the Apache module DLL. In either case you need to stop the Apache server, and edit your httpd.conf to configure Apache to work with PHP.

You need to insert these three lines to your Apache httpd.conf configuration file to set up the CGI binary:

Пример 3-8. PHP and Apache 2.0 as CGI

ScriptAlias /php/ "c:/php/"
AddType application/x-httpd-php .php
Action application/x-httpd-php "/php/php.exe"

If you would like to use PHP as a module in Apache 2.0, be sure to move php4ts.dll to winnt/system32 (for Windows NT/2000) or windows/system32 (for Windows XP), overwriting any older file. You need to insert these two lines to your Apache httpd.conf configuration file to set up the PHP-Module for Apache 2.0:

Пример 3-9. PHP and Apache 2.0 as Module

LoadModule php4_module "c:/php/sapi/php4apache2.dll"
AddType application/x-httpd-php .php

Замечание: Remember to substitute the c:/php/ for your actual path to PHP in the above examples. Take care to use php4apache2.dll in your LoadModule directive and notphp4apche.dll. The latter one is designd to run with Apache 1.3.x.

Внимание

Don't mix up your installation with dll files from different PHP versions . You have the only choice to use the dll's and extensions that ship with your downloaded PHP version.


Servers-Caudium

PHP 4 can be built as a Pike module for the Caudium webserver. Note that this is not supported with PHP 3. Follow the simple instructions below to install PHP 4 for Caudium.

Пример 3-10. Caudium Installation Instructions

1.  Make sure you have Caudium installed prior to attempting to
    install PHP 4. For PHP 4 to work correctly, you will need Pike
    7.0.268 or newer. For the sake of this example we assume that
    Caudium is installed in /opt/caudium/server/.
2.  Change directory to php-x.y.z (where x.y.z is the version number).
3.  ./configure --with-caudium=/opt/caudium/server
4.  make
5.  make install
6.  Restart Caudium if it's currently running.
7.  Log into the graphical configuration interface and go to the
    virtual server where you want to add PHP 4 support.
8.  Click Add Module and locate and then add the PHP 4 Script Support module.
9.  If the documentation says that the 'PHP 4 interpreter isn't
    available', make sure that you restarted the server. If you did
    check /opt/caudium/logs/debug/default.1 for any errors related to
    <filename>PHP4.so</filename>. Also make sure that 
    <filename>caudium/server/lib/[pike-version]/PHP4.so</filename>
    is present.
10. Configure the PHP Script Support module if needed.

You can of course compile your Caudium module with support for the various extensions available in PHP 4. See the complete list of configure options for an exhaustive rundown.

Замечание: When compiling PHP 4 with MySQL support you must make sure that the normal MySQL client code is used. Otherwise there might be conflicts if your Pike already has MySQL support. You do this by specifying a MySQL install directory the --with-mysql option.


Servers-fhttpd

To build PHP as an fhttpd module, answer "yes" to "Build as an fhttpd module?" (the --with-fhttpd=DIR option to configure) and specify the fhttpd source base directory. The default directory is /usr/local/src/fhttpd. If you are running fhttpd, building PHP as a module will give better performance, more control and remote execution capability.


Servers-IIS/PWS

This section contains notes and hints specific to IIS (Microsoft Internet Information Server). Installing PHP for PWS/IIS 3, PWS 4 or newer and IIS 4 or newer versions.

Important for CGI users: Read the faq on cgi.force_redirect for important details. This directive needs to be set to 0.


Windows and PWS/IIS 3

The recommended method for configuring these servers is to use the REG file included with the distribution (pws-php4cgi.reg). You may want to edit this file and make sure the extensions and PHP install directories match your configuration. Or you can follow the steps below to do it manually.

Внимание

These steps involve working directly with the Windows registry. One error here can leave your system in an unstable state. We highly recommend that you back up your registry first. The PHP Development team will not be held responsible if you damage your registry.

  • Run Regedit.

  • Navigate to: HKEY_LOCAL_MACHINE /System /CurrentControlSet /Services /W3Svc /Parameters /ScriptMap.

  • On the edit menu select: New->String Value.

  • Type in the extension you wish to use for your php scripts. For example .php

  • Double click on the new string value and enter the path to php.exe in the value data field. ex: c:\php\php.exe.

  • Repeat these steps for each extension you wish to associate with PHP scripts.

The following steps do not affect the web server installation and only apply if you want your php scripts to be executed when they are run from the command line (ex. run c:\myscripts\test.php) or by double clicking on them in a directory viewer window. You may wish to skip these steps as you might prefer the PHP files to load into a text editor when you double click on them.

  • Navigate to: HKEY_CLASSES_ROOT

  • On the edit menu select: New->Key.

  • Name the key to the extension you setup in the previous section. ex: .php

  • Highlight the new key and in the right side pane, double click the "default value" and enter phpfile.

  • Repeat the last step for each extension you set up in the previous section.

  • Now create another New->Key under HKEY_CLASSES_ROOT and name it phpfile.

  • Highlight the new key phpfile and in the right side pane, double click the "default value" and enter PHP Script.

  • Right click on the phpfile key and select New->Key, name it Shell.

  • Right click on the Shell key and select New->Key, name it open.

  • Right click on the open key and select New->Key, name it command.

  • Highlight the new key command and in the right side pane, double click the "default value" and enter the path to php.exe. ex: c:\php\php.exe -q %1. (don't forget the %1).

  • Exit Regedit.

  • If using PWS on Windows, reboot to reload the registry.

PWS and IIS 3 users now have a fully operational system. IIS 3 users can use a nifty tool from Steven Genusa to configure their script maps.


Windows and PWS 4 or newer

When installing PHP on Windows with PWS 4 or newer version, you have two options. One to set up the PHP CGI binary, the other is to use the ISAPI module DLL.

If you choose the CGI binary, do the following:

  • Edit the enclosed pws-php4cgi.reg file (look into the SAPI dir) to reflect the location of your php.exe. Backslashes should be escaped, for example: [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\w3svc\parameters\Script Map] ".php"="c:\\php\\php.exe" Now merge this registery file into your system; you may do this by double-clicking it.

  • In the PWS Manager, right click on a given directory you want to add PHP support to, and select Properties. Check the 'Execute' checkbox, and confirm.

If you choose the ISAPI module, do the following:

  • Edit the enclosed pws-php4isapi.reg file (look into the SAPI dir) to reflect the location of your php4isapi.dll. Backslashes should be escaped, for example: [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\w3svc\parameters\Script Map] ".php"="c:\\php\\sapi\\php4isapi.dll" Now merge this registery file into your system; you may do this by double-clicking it.

  • In the PWS Manager, right click on a given directory you want to add PHP support to, and select Properties. Check the 'Execute' checkbox, and confirm.


Windows NT/2000/XP and IIS 4 or newer

To install PHP on an NT/2000/XP Server running IIS 4 or newer, follow these instructions. You have two options to set up PHP, using the CGI binary (php.exe) or with the ISAPI module.

In either case, you need to start the Microsoft Management Console (may appear as 'Internet Services Manager', either in your Windows NT 4.0 Option Pack branch or the Control Panel=>Administrative Tools under Windows 2000/XP). Then right click on your Web server node (this will most probably appear as 'Default Web Server'), and select 'Properties'.

If you want to use the CGI binary, do the following:

  • Under 'Home Directory', 'Virtual Directory', or 'Directory', click on the 'Configuration' button, and then enter the App Mappings tab.

  • Click Add, and in the Executable box, type: c:\php\php.exe (assuming that you have unziped PHP in c:\php\).

  • In the Extension box, type the file name extension you want associated with PHP scripts. Leave 'Method exclusions' blank, and check the Script engine checkbox. You may also like to check the 'check that file exists' box - for a small performance penalty, IIS (or PWS) will check that the script file exists and sort out authentication before firing up php. This means that you will get sensible 404 style error messages instead of cgi errors complaining that php did not output any data.

    You must start over from the previous step for each extension you want associated with PHP scripts. .php and .phtml are common, although .php3 may be required for legacy applications.

  • Set up the appropriate security. (This is done in Internet Service Manager), and if your NT Server uses NTFS file system, add execute rights for I_USR_ to the directory that contains php.exe.

To use the ISAPI module, do the following:

  • If you don't want to perform HTTP Authentication using PHP, you can (and should) skip this step. Under ISAPI Filters, add a new ISAPI filter. Use PHP as the filter name, and supply a path to the php4isapi.dll.

  • Under 'Home Directory', click on the 'Configuration' button. Add a new entry to the Application Mappings. Use the path to the php4isapi.dll as the Executable, supply .php as the extension, leave Method exclusions blank, and check the Script engine checkbox.

  • Stop IIS completely (NET STOP iisadmin)

  • Start IIS again (NET START w3svc)


Servers-Netscape and iPlanet

This section contains notes and hints specific to Netscape and iPlanet installs of PHP, both for Sun Solaris and Windows versions.

You can find more information about setting up PHP for the Netscape Enterprise Server here: http://benoit.noss.free.fr/php/install-php4.html


Installing PHP with Netscape on Sun Solaris

To build PHP with NES or iPlanet web servers, enter the proper install directory for the --with-nsapi = DIR option. The default directory is usually /opt/netscape/suitespot/. Please also read /php-xxx-version/sapi/nsapi/nsapi-readme.txt.

Пример 3-11. Installation Example for Netscape Enterprise on Solaris

Instructions for Sun Solaris 2.6 with Netscape Enterprise Server 3.6
From: bhager@invacare.com

1. Install the following packages from www.sunfreeware.com or another
download site: 

    flex-2_5_4a-sol26-sparc-local 
    gcc-2_95_2-sol26-sparc-local 
    gzip-1.2.4-sol26-sparc-local 
    perl-5_005_03-sol26-sparc-local 
    bison-1_25-sol26-sparc-local 
    make-3_76_1-sol26-sparc-local 
    m4-1_4-sol26-sparc-local 
    autoconf-2.13 
    automake-1.4 
    mysql-3.23.24-beta (if you want mysql support) 
    tar-1.13 (GNU tar) 

2. Make sure your path includes the proper directories
    PATH=.:/usr/local/bin:/usr/sbin:/usr/bin:/usr/ccs/bin 
    export PATH 

3. gunzip php-x.x.x.tar.gz (if you have a .gz dist, otherwise go to 4) 
4. tar xvf php-x.x.x.tar 
5. cd ../php-x.x.x 

6. For the following step, make sure /opt/netscape/suitespot/ is where
   your netscape server is installed. Otherwise, change to correct path:
    /configure --with-mysql=/usr/local/mysql --with-nsapi=/opt/netscape/suitespot/ --enable-track-vars --enable-libgcc 
7. make 
8. make install
After performing the base install and reading the appropriate readme file, you may need to performs some additional configuration steps.

Firstly you may need to add some paths to the LD_LIBRARY_PATH environment for Netscape to find all the shared libs. This can best done in the start script for your Netscape server. Windows users can probably skip this step. The start script is often located in: /path/to/server/https-servername/start

You may also need to edit the configuration files that are located in:/path/to/server/https-servername/config/.

Пример 3-12. Configuration Example for Netscape Enterprise

Configuration Instructions for Netscape Enterprise Server
From: bhager@invacare.com

1. Add the following line to mime.types:
    type=magnus-internal/x-httpd-php exts=php

2. Add the following to obj.conf, shlib will vary depending on
    your OS, for unix it will be something like
    /opt/netscape/suitespot/bin/libphp4.so.

    You should place the following lines after mime types init.
    Init fn="load-modules" funcs="php4_init,php4_close,php4_execute,php4_auth_trans" shlib="/php4/nsapiPHP4.dll"
    Init fn=php4_init errorString="Failed to initialize PHP!"

    <object name="default">
    . 
    . 
    . 
    .#NOTE this next line should happen after all 'ObjectType' and before all 'AddLog' lines 
    Service fn="php4_execute" type="magnus-internal/x-httpd-php" 
    . 
    . 
    </Object>


    <Object name="x-httpd-php"> 
    ObjectType fn="force-type" type="magnus-internal/x-httpd-php" 
    Service fn=php4_execute 
    </Object> 


    Authentication configuration 

    PHP authentication cannot be used with any other authentication. ALL AUTHENTICATION IS 
    PASSED TO YOUR PHP SCRIPT. To configure PHP Authentication for the entire server, add 
    the following line: 

    <Object name="default"> 
    AuthTrans fn=php4_auth_trans 
    . 
    . 
    . 
    . 
    </Object> 

    To use PHP Authentication on a single directory, add the following: 

    <Object ppath="d:\path\to\authenticated\dir\*"> 
    AuthTrans fn=php4_auth_trans 
    </Object>

If you are running Netscape Enterprise 4.x, then you should use the following:

Пример 3-13. Configuration Example for Netscape Enterprise 4.x

Place these lines after the mime types init, and everything else is similar
to the example configuration above.
From: Graeme Hoose (GraemeHoose@BrightStation.com)

Init fn="load-modules" shlib="/path/to/server4/bin/libphp4.so" funcs="php4_init,php4_close,php4_execute,php4_auth_trans"
Init fn="php4_init" LateInit="yes"

Installing PHP with Netscape on Windows

To Install PHP as CGI (for Netscape Enterprise Server, iPlanet, perhaps Fastrack), do the following:

  • Copy php4ts.dll to your systemroot (the directory where you installed windows)

  • Make a file association from the command line. Type the following two lines:
    assoc .php=PHPScript
    ftype PHPScript=c:\php\php.exe %1 %*

  • In the Netscape Enterprise Administration Server create a dummy shellcgi directory and remove it just after (this step creates 5 important lines in obj.conf and allow the web server to handle shellcgi scripts).

  • In the Netscape Enterprise Administration Server create a new mime type (Category: type, Content-Type: magnus-internal/shellcgi, File Suffix:php).

  • Do it for each web server instance you want php to run

More details about setting up PHP as a CGI executable can be found here: http://benoit.noss.free.fr/php/install-php.html

To Install PHP as NSAPI (for Netscape Enterprise Server, iPlanet, perhaps Fastrack, do the following:

  • Copy php4ts.dll to your systemroot (the directory where you installed windows)

  • Make a file association from the command line. Type the following two lines:
    assoc .php=PHPScript
    ftype PHPScript=c:\php\php.exe %1 %*

  • In the Netscape Enterprise Administration Server create a new mime type (Category: type, Content-Type: magnus-internal/x-httpd-php, File Suffix:php).

  • Stop your web service and edit obj.conf. At the end of the Init section, place these two lines (necessarily after mime type init!):
    Init fn="load-modules" funcs="php4_init,php4_close,php4_execute,php4_auth_trans" shlib="c:/php/sapi/php4nsapi.dll"
    Init fn="php4_init" errorString="Failed to initialise PHP!"

  • In The < Object name="default" > section, place this line necessarily after all 'ObjectType' and before all 'AddLog' lines:
    Service fn="php4_execute" type="magnus-internal/x-httpd-php"

  • At the end of the file, create a new object called x-httpd-php, by inserting these lines:
    <Object name="x-httpd-php">
    ObjectType fn="force-type" type="magnus-internal/x-httpd-php"
    Service fn=php4_execute
    </Object>

  • Restart your web service and apply changes

  • Do it for each web server instance you want PHP to run

More details about setting up PHP as an NSAPI filter can be found here: http://benoit.noss.free.fr/php/install-php4.html


Servers-OmniHTTPd Server

This section contains notes and hints specific to OmniHTTPd.


OmniHTTPd 2.0b1 and up for Windows

You need to complete the following steps to make PHP work with OmniHTTPd. This is a CGI executable setup. SAPI is supported by OmniHTTPd, but some tests have shown that it is not so stable to use PHP as an ISAPI module.

Important for CGI users: Read the faq on cgi.force_redirect for important details. This directive needs to be set to 0.

  • Step 1: Install OmniHTTPd server.

  • Step 2: Right click on the blue OmniHTTPd icon in the system tray and select Properties

  • Step 3: Click on Web Server Global Settings

  • Step 4: On the 'External' tab, enter: virtual = .php | actual = c:\path-to-php-dir\php.exe, and use the Add button.

  • Step 5: On the Mime tab, enter: virtual = wwwserver/stdcgi | actual = .php, and use the Add button.

  • Step 6: Click OK

Repeat steps 2 - 6 for each extension you want to associate with PHP.

Замечание: Some OmniHTTPd packages come with built in PHP support. You can choose at setup time to do a custom setup, and uncheck the PHP component. We recommend you to use the latest PHP binaries. Some OmniHTTPd servers come with PHP 4 beta distributions, so you should choose not to set up the built in support, but install your own. If the server is already on your machine, use the Replace button in Step 4 and 5 to set the new, correct information.


Servers-Oreilly Website Pro

This section contains notes and hints specific to Oreilly Website Pro.


Oreilly Website Pro 2.5 and up for Windows

This list describes how to set up the PHP CGI binary or the ISAPI module to work with Oreilly Website Pro on Windows.

  • Edit the Server Properties and select the tab "Mapping".

  • From the List select "Associations" and enter the desired extension (.php) and the path to the CGI exe (ex. c:\php\php.exe) or the ISAPI DLL file (ex. c:\php\sapi\php4isapi.dll).

  • Select "Content Types" add the same extension (.php) and enter the content type. If you choose the CGI executable file, enter 'wwwserver/shellcgi', if you choose the ISAPI module, enter 'wwwserver/isapi' (both without quotes).


Servers-Sambar

This section contains notes and hints specific to the Sambar server for Windows.


Sambar Windows

This list describes how to set up the ISAPI module to work with the Sambar server on Windows.

  • Find the file called mappings.ini (in the config directory) in the Sambar isntall directory.

  • Open mappings.ini and add the following line under [ISAPI]:

    *.php = c:\php\php4isapi.dll

    (This line assumes that PHP was installed in c:\php.)

  • Now restart the Sambar server for the changes to take effect.


Servers-Xitami

This section contains notes and hints specific to Xitami.


Xitami for Windows

This list describes how to set up the PHP CGI binary to work with Xitami on Windows.

Important for CGI users: Read the faq on cgi.force_redirect for important details. This directive needs to be set to 0.

  • Make sure the webserver is running, and point your browser to xitamis admin console (usually http://127.0.0.1/admin), and click on Configuration.

  • Navigate to the Filters, and put the extension which PHP should parse (i.e. .php) into the field File extensions (.xxx).

  • In Filter command or script put the path and name of your php executable i.e. c:\php\php.exe.

  • Press the 'Save' icon.

  • Restart the server to reflect changes.


Servers-Other web servers

PHP can be built to support a large number of web servers. Please see Server-related options for a full list of server-related configure options. The PHP CGI binaries are compatible with almost all webservers supporting the CGI standard.


Problems?

Read the FAQ

Some problems are more common than others. The most common ones are listed in the PHP FAQ, part of this manual.


Other problems

If you are still stuck, someone on the PHP installation mailing list may be able to help you. You should check out the archive first, in case someone already answered someone else who had the same problem as you. The archives are available from the support page on http://www.php.net/. To subscribe to the PHP installation mailing list, send an empty mail to php-install-subscribe@lists.php.net. The mailing list address is php-install@lists.php.net.

If you want to get help on the mailing list, please try to be precise and give the necessary details about your environment (which operating system, what PHP version, what web server, if you are running PHP as CGI or a server module, safe mode, etc...), and preferably enough code to make others able to reproduce and test your problem.


Bug reports

If you think you have found a bug in PHP, please report it. The PHP developers probably don't know about it, and unless you report it, chances are it won't be fixed. You can report bugs using the bug-tracking system at http://bugs.php.net/. Please do not send bug reports in mailing list or personal letters. The bug system is also suitable to submit feature requests.

Read the How to report a bug document before submitting any bug reports!


Complete list of configure options

Замечание: These are only used at compile time. If you want to alter PHP's runtime configuration, please see the chapter on Configuration.

The following is a complete list of options supported by PHP 4 configure scripts (as of 4.1.0), used when compiling in Unix-like environments. Some are available in PHP 3, some in PHP 4, and some in both. This is not noted yet.

There are general configuration options for the configure script, consult the appropriate manual pages for GNU autoconf or use the command configure --help for a full, up-to-date list.


Configure Options in PHP 4

Замечание: These options are only used in PHP 4 as of PHP 4.1.0. Some are available in older versions of PHP 4, some even in PHP 3, some only in PHP 4.1.0. If you want to compile an older version, some options will probably not be available.


Database options

--with-dbplus

Include dbplus support.

--with-adabas[=DIR]

Include Adabas D support. DIR is the Adabas base install directory, defaults to /usr/local.

--with-sapdb[=DIR]

Include SAP DB support. DIR is SAP DB base install directory, defaults to /usr/local.

--with-solid[=DIR]

Include Solid support. DIR is the Solid base install directory, defaults to /usr/local/solid.

--with-ibm-db2[=DIR]

Include IBM DB2 support. DIR is the DB2 base install directory, defaults to /home/db2inst1/sqllib.

--with-empress[=DIR]

Include Empress support. DIR is the Empress base install directory, defaults to $EMPRESSPATH. From PHP4, this option only supports Empress Version 8.60 and above.

--with-empress-bcs[=DIR]

Include Empress Local Access support. DIR is the Empress base install directory, defaults to $EMPRESSPATH. From PHP4, this option only supports Empress Version 8.60 and above.

--with-birdstep[=DIR]

Include Birdstep support. DIR is the Birdstep base install directory, defaults to /usr/local/birdstep.

--with-custom-odbc[=DIR]

Include a user defined ODBC support. The DIR is ODBC install base directory, which defaults to /usr/local. Make sure to define CUSTOM_ODBC_LIBS and have some odbc.h in your include dirs. E.g., you should define following for Sybase SQL Anywhere 5.5.00 on QNX, prior to run configure script: CPPFLAGS="-DODBC_QNX -DSQLANY_BUG" LDFLAGS=-lunix CUSTOM_ODBC_LIBS="-ldblib -lodbc".

--with-iodbc[=DIR]

Include iODBC support. DIR is the iODBC base install directory, defaults to /usr/local.

--with-esoob[=DIR]

Include Easysoft OOB support. DIR is the OOB base install directory, defaults to /usr/local/easysoft/oob/client.

--with-unixODBC[=DIR]

Include unixODBC support. DIR is the unixODBC base install directory, defaults to /usr/local.

--with-openlink[=DIR]

Include OpenLink ODBC support. DIR is the OpenLink base install directory, defaults to /usr/local. This is the same as iODBC.

--with-dbmaker[=DIR]

Include DBMaker support. DIR is the DBMaker base install directory, defaults to where the latest version of DBMaker is installed (such as /home/dbmaker/3.6).

--disable-unified-odbc

Disable unified ODBC support. Only applicable if iODBC, Adabas, Solid, Velocis or a custom ODBC interface is enabled. PHP 3 only!


Graphics options

--without-gd

Disable GD support. PHP 3 only!

--with-imagick

The imagick extension has been moved to PECL in PEAR and can be found here. Install instructions for PHP 4 can be found on the PEAR site.

Simply doing --with-imagick is only supported in PHP 3 unless you follow the instructions found on the PEAR site.

--with-ming[=DIR]

Include ming support.


Misc options

--enable-force-cgi-redirect

Enable the security check for internal server redirects. You should use this if you are running the CGI version with Apache.

--enable-discard-path

If this is enabled, the PHP CGI binary can safely be placed outside of the web tree and people will not be able to circumvent .htaccess security.

--with-fastcgi

Build PHP as FastCGI application.

--enable-debug

Compile with debugging symbols.

--with-layout=TYPE

Sets how installed files will be laid out. Type is one of PHP (default) or GNU.

--with-pear=DIR

Install PEAR in DIR (default PREFIX/lib/php).

--without-pear

Do not install PEAR.

--enable-sigchild

Enable PHP's own SIGCHLD handler.

--disable-rpath

Disable passing additional runtime library search paths.

--enable-libgcc

Enable explicitly linking against libgcc.

--enable-php-streams

Include experimental php streams. Do not use unless you are testing the code!

--with-zlib-dir=<DIR>

Define the location of zlib install directory.

--with-aspell[=DIR]

Include ASPELL support.

--with-ccvs[=DIR]

Include CCVS support.

--with-cybercash[=DIR]

Include CyberCash support. DIR is the CyberCash MCK install directory.

--with-icap[=DIR]

Include ICAP support.

--with-ircg-config

Path to the ircg-config script.

--with-ircg

Include ircg support.

--enable-mailparse

Enable mailparse support.

--with-muscat[=DIR]

Include muscat support.

--with-satellite[=DIR]

Enable CORBA support via Satellite (EXPERIMENTAL) DIR is the base directory for ORBit.

--enable-trans-sid

Enable transparent session id propagation.

--with-regex[=TYPE]

Use system regex library (deprecated).

--with-vpopmail[=DIR]

Include vpopmail support.

--with-tsrm-pthreads

Use POSIX threads (default).

--enable-shared[=PKGS]

Build shared libraries [default=yes].

--enable-static[=PKGS]

Build static libraries [default=yes].

--enable-fast-install[=PKGS]

Optimize for fast installation [default=yes].

--with-gnu-ld

Assume the C compiler uses GNU ld [default=no].

--disable-libtool-lock

Avoid locking (might break parallel builds).

--with-pic

Try to use only PIC/non-PIC objects [default=use both].

--enable-memory-limit

Compile with memory limit support.

--disable-url-fopen-wrapper

Disable the URL-aware fopen wrapper that allows accessing files via HTTP or FTP.

--enable-versioning

Export only required symbols. See INSTALL for more information.

--with-imsp[=DIR]

Include IMSp support (DIR is IMSP's include dir and libimsp.a dir). PHP 3 only!

--with-mck[=DIR]

Include Cybercash MCK support. DIR is the cybercash mck build directory, defaults to /usr/src/mck-3.2.0.3-linux for help look in extra/cyberlib. PHP 3 only!

--with-mod-dav=DIR

Include DAV support through Apache's mod_dav, DIR is mod_dav's installation directory (Apache module version only!) PHP 3 only!

--enable-debugger

Compile with remote debugging functions. PHP 3 only!

--enable-versioning

Take advantage of versioning and scoping provided by Solaris 2.x and Linux. PHP 3 only!


PHP options

--enable-maintainer-mode

Enable make rules and dependencies not useful (and sometimes confusing) to the casual installer.

--with-config-file-path=PATH

Sets the path in which to look for php.ini, defaults to PREFIX/lib.

--enable-safe-mode

Enable safe mode by default.

--with-exec-dir[=DIR]

Only allow executables in DIR when in safe mode defaults to /usr/local/php/bin.

--enable-magic-quotes

Enable magic quotes by default.

--disable-short-tags

Disable the short-form <? start tag by default.


Server options

--with-aolserver=DIR

Specify path to the installed AOLserver.

--with-apxs[=FILE]

Build shared Apache module. FILE is the optional pathname to the Apache apxs tool; defaults to apxs. Make sure you specify the version of apxs that is actually installed on your system and NOT the one that is in the apache source tarball.

--with-apache[=DIR]

Build Apache module. DIR is the top-level Apache build directory, defaults to /usr/local/apache.

--with-mod_charset

Enable transfer tables for mod_charset (Rus Apache).

--with-apxs2[=FILE]

Build shared Apache 2.0 module. FILE is the optional pathname to the Apache apxs tool; defaults to apxs.

--with-fhttpd[=DIR]

Build fhttpd module. DIR is the fhttpd sources directory, defaults to /usr/local/src/fhttpd.

--with-isapi=DIR

Build PHP as an ISAPI module for use with Zeus.

--with-nsapi=DIR

Specify path to the installed Netscape Server.

--with-phttpd=DIR

No information yet.

--with-pi3web=DIR

Build PHP as a module for use with Pi3Web.

--with-roxen=DIR

Build PHP as a Pike module. DIR is the base Roxen directory, normally /usr/local/roxen/server.

--enable-roxen-zts

Build the Roxen module using Zend Thread Safety.

--with-servlet[=DIR]

Include servlet support. DIR is the base install directory for the JSDK. This SAPI prereqs the java extension must be built as a shared dl.

--with-thttpd=SRCDIR

Build PHP as thttpd module.

--with-tux=MODULEDIR

Build PHP as a TUX module (Linux only).


Глава 4. Конфигурация

Файл конфигурации

Файл конфигурации (называющийся php3.ini в PHP 3.0, и просто php.ini в PHP 4.0) читается каждый раз при запуске PHP. При использовании PHP в виде модуля для Web-сервера, это происходит лишь один раз при запуске сервера. Для версий CGI и CLI, это происходи при каждом пуске.

Расположение php.ini задается при компиляции (смотрите FAQ), но для версий CGI и CLI может быть изменено из командной строки опцией -c (см. раздел про использование PHP из командной строки. Также можно использовать переменную окружения PHPRC для задания дополнительных путей поиска файла php.ini.

Здесь не описывается каждая директива PHP в отдельности. Для полного списка всех директив смотрите хорошо документированный файл php.ini. Можно посмотреть php.ini последней версии в CVS.

Замечание: Значение по умолчанию для директив register_globals изменилось с on на off в PHP 4.2.0.

Пример 4-1. Пример php.ini

; любой текст после открытой точки с запятой (;) игнорируется
[php] ; также игнорируются маркеры секций (текст в квадратных скобках)
; Логические значения:
;  Включено: true, on, yes
;  Выключено: false, off, no, none
register_globals = off
magic_quotes_gpc = yes

; строки можно заключать в двойные кавычки
include_path = ".:/usr/local/lib/php"

; обратные слэши ничем не отличаются от остальных символов
include_path = ".;c:\php\lib"


Как изменить конфигурацию

При использовании PHP, как модуля Apache

При использовании модуля Apache можно изменить настройки с помощью директив файлов конфигурации Apache httpd.conf) и .htaccess (для этого понадобятся привилегии "AllowOverride Options" или "AllowOverride All").

В PHP 3.0 были директивы Apache, связанные с соответствующими директивами php3.ini, с единственным различием в том, что у них был префикс "php3_".

В PHP 4.0 есть несколько директив Apache, которые позволяют вам менять конфигурацию PHP из файлов конфигурации Apache.

php_value имя значение

Устанавливает значение указанной директивы. Может быть использована только для директив типа PHP_INI_ALL и PHP_INI_PERDIR. Для очистки значения задайте none.

php_value auto_prepend_file none

php_flag имя on|off

Используется для установки значений логических директив. Также может быть использована только с типами PHP_INI_ALL и PHP_INI_PERDIR type directives.

php_admin_value имя значение

Устанавливает значение указанной директивы. Эта директива НЕ МОЖЕТ быть использована в файлах .htaccess. Любая директива, заданная с помощью php_admin_value, не может быть переопределена в файлах .htaccess.

php_admin_flag имя on|off

Устанавливает значение указанной логической директивы. Эта директива НЕ МОЖЕТ быть использована в файлах .htaccess. Любая директива, заданная с помощью php_admin_flag, не может быть переопределена в файлах .htaccess.

Пример 4-2. Пример конфигурации Apache

<IfModule mod_php4.c>
  php_value include_path ".:/usr/local/lib/php"
  php_admin_flag safe_mode on
</IfModule>
<IfModule mod_php3.c>
  php3_include_path ".:/usr/local/lib/php"
  php3_safe_mode on
</IfModule>

Замечание: Константы PHP не определены вне PHP. К примеру, в файле httpd.conf нельзя использовать константы PHP, такие, как E_ALL или E_NOTICE, поскольку они не будут иметь значения и будут восприняты, как 0. Вместо констант придется использовать соответствующие значения.


При использовании других интерфейсов PHP

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

Таблица 4-1. Определение констант PHP_INI_*

КонстантаЗначениеУровень
PHP_INI_USER1Значение может изменяться в программе пользователя
PHP_INI_PERDIR2 Значение может быть задано в php.ini, .htaccess или httpd.conf
PHP_INI_SYSTEM4 Значение может быть задано в php.ini или httpd.conf
PHP_INI_ALL7Значение может задаваться где угодно

Значения конфигурационных директив можно посмотреть в выводе функции phpinfo(). Также можно получит доступ к данным значениям с использованием ini_get() или get_cfg_var().


Configuration directives

Httpd Options

Таблица 4-2. Httpd Options

NameDefaultChangeable
async_send"0"PHP_INI_ALL


Language Options

Таблица 4-3. Language and Misc Configuration Options

NameDefaultChangeable
short_open_tagOnPHP_INI_SYSTEM|PHP_INI_PERDIR
asp_tagsOffPHP_INI_SYSTEM|PHP_INI_PERDIR
precision"14"PHP_INI_ALL
y2k_complianceOffPHP_INI_ALL
allow_call_time_pass_referenceOnPHP_INI_SYSTEM|PHP_INI_PERDIR
expose_phpOnPHP_INI_SYSTEM

Here is a short explanation of the configuration directives.

short_open_tag boolean

Tells whether the short form (<? ?>) of PHP's open tag should be allowed. If you want to use PHP in combination with XML, you can disable this option in order to use <?xml ?> inline. Otherwise, you can print it with PHP, for example: <?php echo '<?xml version="1.0"'; ?>. Also if disabled, you must use the long form of the PHP open tag (<?php ?>).

Замечание: This directive also affects the shorthand <?=, which is identical to <? echo. Use of this shortcut requires short_open_tag to be on.

asp_tags boolean

Enables the use of ASP-like <% %> tags in addition to the usual <?php ?> tags. This includes the variable-value printing shorthand of <%= $value %>. For more information, see Escaping from HTML.

Замечание: Support for ASP-style tags was added in 3.0.4.

precision integer

The number of significant digits displayed in floating point numbers.

y2k_compliance boolean

Enforce year 2000 compliance (will cause problems with non-compliant browsers)

allow_call_time_pass_reference boolean

Whether to enable the ability to force arguments to be passed by reference at function call time. This method is deprecated and is likely to be unsupported in future versions of PHP/Zend. The encouraged method of specifying which arguments should be passed by reference is in the function declaration. You're encouraged to try and turn this option Off and make sure your scripts work properly with it in order to ensure they will work with future versions of the language (you will receive a warning each time you use this feature, and the argument will be passed by value instead of by reference).

See also References Explained.

expose_php boolean

Decides whether PHP may expose the fact that it is installed on the server (e.g. by adding its signature to the Web server header). It is no security threat in any way, but it makes it possible to determine whether you use PHP on your server or not.


Resource Limits

Таблица 4-4. Resource Limits

NameDefaultChangeable
memory_limit"8M"PHP_INI_ALL

Here is a short explanation of the configuration directives.

memory_limit integer

This sets the maximum amount of memory in bytes that a script is allowed to allocate. This helps prevent poorly written scripts for eating up all available memory on a server. In order to use this directive you must have enabled it at compile time. So, your configure line would have included: --enable-memory-limit. Note that you have to set it to -1 if you don't want any limit for your memory.

See also: max_execution_time.


Data Handling

Таблица 4-5. Data Handling Configuration Options

NameDefaultChangeable
track-vars"On"PHP_INI_??
arg_separator.output"&"PHP_INI_ALL
arg_separator.input"&"PHP_INI_SYSTEM|PHP_INI_PERDIR
variables_order"EGPCS"PHP_INI_ALL
register_globals"Off"PHP_INI_PERDIR|PHP_INI_SYSTEM
register_argc_argv"On"PHP_INI_PERDIR|PHP_INI_SYSTEM
post_max_size"8M"PHP_INI_SYSTEM|PHP_INI_PERDIR
gpc_order"GPC"PHP_INI_ALL
auto_prepend_file""PHP_INI_SYSTEM|PHP_INI_PERDIR
auto_append_file""PHP_INI_SYSTEM|PHP_INI_PERDIR
default_mimetype"text/html"PHP_INI_ALL
default_charset"iso-8859-1"PHP_INI_ALL
always_populate_raw_post_data"0"PHP_INI_SYSTEM|PHP_INI_PERDIR
allow_webdav_methods"0"PHP_INI_SYSTEM|PHP_INI_PERDIR

Here is a short explanation of the configuration directives.

track_vars boolean

If enabled, then Environment, GET, POST, Cookie, and Server variables can be found in the global associative arrays $_ENV, $_GET, $_POST, $_COOKIE, and $_SERVER.

Note that as of PHP 4.0.3, track_vars is always turned on.

arg_separator.output string

The separator used in PHP generated URLs to separate arguments.

arg_separator.input string

List of separator(s) used by PHP to parse input URLs into variables.

Замечание: Every character in this directive is considered as separator!

variables_order string

Set the order of the EGPCS (Environment, GET, POST, Cookie, Server) variable parsing. The default setting of this directive is "EGPCS". Setting this to "GP", for example, will cause PHP to completely ignore environment variables, cookies and server variables, and to overwrite any GET method variables with POST-method variables of the same name.

See also register_globals.

register_globals boolean

Tells whether or not to register the EGPCS (Environment, GET, POST, Cookie, Server) variables as global variables. For example; if register_globals = on, the url http://www.example.com/test.php?id=3 will produce $id. Or, $DOCUMENT_ROOT from $_SERVER['DOCUMENT_ROOT']. You may want to turn this off if you don't want to clutter your scripts' global scope with user data. As of PHP 4.2.0, this directive defaults to off. It's preferred to go through PHP Predefined Variables instead, such as the superglobals: $_ENV, $_GET, $_POST, $_COOKIE, and $_SERVER. Please read the security chapter on Using register_globals for related information.

Please note that register_globals cannot be set at runtime (ini_set()). Although, you can use .htaccess if your host allows it as described above. An example .htaccess entry: php_flag register_globals on.

Замечание: register_globals is affected by the variables_order directive.

register_argc_argv boolean

Tells PHP whether to declare the argv & argc variables (that would contain the GET information).

See also command line. Also, this directive became available in PHP 4.0.0 and was always "on" before that.

post_max_size integer

Sets max size of post data allowed. This setting also affects file upload. To upload large files, this value must be larger than upload_max_filesize.

If memory limit is enabled by your configure script, memory_limit also affects file uploading. Generally speaking, memory_limit should be larger than post_max_size.

gpc_order string

Set the order of GET/POST/COOKIE variable parsing. The default setting of this directive is "GPC". Setting this to "GP", for example, will cause PHP to completely ignore cookies and to overwrite any GET method variables with POST-method variables of the same name.

Замечание: This option is not available in PHP 4. Use variables_order instead.

auto_prepend_file string

Specifies the name of a file that is automatically parsed before the main file. The file is included as if it was called with the include() function, so include_path is used.

The special value none disables auto-prepending.

auto_append_file string

Specifies the name of a file that is automatically parsed after the main file. The file is included as if it was called with the include() function, so include_path is used.

The special value none disables auto-appending.

Замечание: If the script is terminated with exit(), auto-append will not occur.

default_mimetype string

default_charset string

As of 4.0b4, PHP always outputs a character encoding by default in the Content-type: header. To disable sending of the charset, simply set it to be empty.

always_populate_raw_post_data boolean

Always populate the $HTTP_RAW_POST_DATA variable.

allow_webdav_methods boolean

Allow handling of WebDAV http requests within PHP scripts (eg. PROPFIND, PROPPATCH, MOVE, COPY, etc..) If you want to get the post data of those requests, you have to set always_populate_raw_post_data as well.

See also: magic_quotes_gpc, magic-quotes-runtime, and magic_quotes_sybase.


Paths and Directories

Таблица 4-6. Paths and Directories Configuration Options

NameDefaultChangeable
include_pathPHP_INCLUDE_PATHPHP_INI_ALL
doc_rootPHP_INCLUDE_PATHPHP_INI_SYSTEM
user_dirNULLPHP_INI_SYSTEM
extension_dirPHP_EXTENSION_DIRPHP_INI_SYSTEM
cgi.force_redirect"1"PHP_INI_SYSTEM
cgi.redirect_status_env""PHP_INI_SYSTEM
fastcgi.impersonate"0"PHP_INI_SYSTEM

Here is a short explanation of the configuration directives.

include_path string

Specifies a list of directories where the require(), include() and fopen_with_path() functions look for files. The format is like the system's PATH environment variable: a list of directories separated with a colon in UNIX or semicolon in Windows.

Пример 4-3. UNIX include_path

include_path=".:/php/includes"

Пример 4-4. Windows include_path

include_path=".;c:\php\includes"

Using a . in the include path allows for relative includes as it means the current directory.

doc_root string

PHP's "root directory" on the server. Only used if non-empty. If PHP is configured with safe mode, no files outside this directory are served. If PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root if you are running php as a CGI under any web server (other than IIS) The alternative is to use the cgi.force_redirect configuration below.

user_dir string

The base name of the directory used on a user's home directory for PHP files, for example public_html.

extension_dir string

In what directory PHP should look for dynamically loadable extensions. See also: enable_dl, and dl().

extension string

Which dynamically loadable extensions to load when PHP starts up.

cgi.force_redirect boolean

cgi.force_redirect is necessary to provide security running PHP as a CGI under most web servers. Left undefined, PHP turns this on by default. You can turn it off AT YOUR OWN RISK.

Замечание: Windows Users: You CAN safely turn this off for IIS, in fact, you MUST. To get OmniHTTPD or Xitami to work you MUST turn it off.

cgi.cgi.redirect_status_env string

If cgi.force_redirect is turned on, and you are not running under Apache or Netscape (iPlanet) web servers, you MAY need to set an environment variable name that PHP will look for to know it is OK to continue execution.

Замечание: Setting this variable MAY cause security issues, KNOW WHAT YOU ARE DOING FIRST.

fastcgi.impersonate string

FastCGI under IIS (on WINNT based OS) supports the ability to impersonate security tokens of the calling client. This allows IIS to define the security context that the request runs under. mod_fastcgi under Apache does not currently support this feature (03/17/2002) Set to 1 if running under IIS. Default is zero.


File Uploads

Таблица 4-7. File Uploads Configuration Options

NameDefaultChangeable
file_uploads"1"PHP_INI_SYSTEM
upload_tmp_dirNULLPHP_INI_SYSTEM
upload_max_filesize"2M"PHP_INI_SYSTEM|PHP_INI_PERDIR

Here is a short explanation of the configuration directives.

file_uploads boolean

Whether or not to allow HTTP file uploads. See also the upload_max_filesize, upload_tmp_dir, and post_max_size directives.

upload_tmp_dir string

The temporary directory used for storing files when doing file upload. Must be writable by whatever user PHP is running as. If not specified PHP will use the system's default.

upload_max_filesize integer

The maximum size of an uploaded file.


General SQL

Таблица 4-8. General SQL Configuration Options

NameDefaultChangeable
sql.safe_mode"0"PHP_INI_SYSTEM

Here is a short explanation of the configuration directives.

sql.safe_mode boolean


Debugger Configuration Directives

debugger.host string

DNS name or IP address of host used by the debugger.

debugger.port string

Port number used by the debugger.

debugger.enabled boolean

Whether the debugger is enabled.


Глава 5. Безопасность

PHP - это мощный язык программирования и интерпретатор. Будучи интегрированным в виде модуля в Web-сервер, или выполняясь как отдельное CGI-приложение, он может обращаться к файлам, исполнять команды и открывать сетевые соединения на сервере. Эти особенности делают все, что выполняется на Web-сервере, небезопасным. PHP специально разрабатывался для того, чтобы быть более безопасным языком для написания CGI-совместимых программ, нежели Perl или С, и, если правильно выставлены настройки компиляции и выполнения, а также при наличии достаточного опыта программирования, PHP даст вам необходимое соотношение гибкости и безопасности.

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

Гибкость настройки PHP конкурирует с гибкостью программирования. PHP может быть использован для создания серверных приложений со всеми возможностями пользователя shell, или для простого включения файлов на стороне сервера, которое не представляет опасности в хорошо контролируемой системе. То, как построена система, и насколько она безопасна, практически полностью зависит от разработчика, использующего PHP.

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


Основные положения

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

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

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

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

Интернет полон людей, которые хотят сделать себе имя путем взлома вашего кода, останова вашего сайта, размещения неподходящих данных, в общем, всего, что не дает вам жить спокойно. Неважно, какого масштаба ваш сайт, вы находитесь под прицелом просто потому, что вы в сети, потому, что у вас есть сервер, к которому можно подключиться. Множество программ для взлома не различают размеров, они просто прокачивают огромное количество IP-траффика в поисках жертвы. Постарайтесь не стать таковой.


При инсталляции в виде приложения CGI

Возможные атаки

Использование PHP в виде приложения CGI - вариант для тех, кто по тем или иным причинам не хочет встраивать PHP в приложение сервера (к примеру, Apache), в виде модуля, или для тех, то хочет использовать PHP совместно с CGI-оболочками, помогающими создать безопасную среду для выполнения программ. Такая настройка обычно включает в себя инсталляцию приложения PHP в директорию cgi-bin на сервере. Рекомендация CERTCA-96.11 выступает против помещения интерпретаторов в cgi-bin. Даже при том, что PHP может быть использован, как независимый интерпретатор, он разрабатавылся для предотвращения атак, связанных с данным вариантом настройки:

  • Получение доступа к системным файлам: http://my.host/cgi-bin/php?/etc/passwd

    Информация запроса в URL после знака вопроса (?) передается с помощью CGI интерпретатору в виде командной строки. Обычно интерпретаторы открывают и выполняют файл, заданный первым аргументом в данной строке.

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

  • Получение доступа к любому документу на сервере: http://my.host/cgi-bin/php/secret/doc.html

    Информационнася часть URL после названия приложения PHP /secret/doc.html обычно используется для задания файла, который будет открыт и интерпретирован приложением CGI. В общем случае для перенаправления запросов вида http://my.host/secret/script.php интерпретатору PHP используются директивы конфигурации Web-сервера (к примеру, Action в Apache). При такой настройке, сервер сначала проверяет разрешения на доступ к данной директории /secret, и только после создает перенаправленный запрос http://my.host/cgi-bin/php/secret/script.php. К сожалению, если запрос уже дан в вышеприведенной форме, сервер не выполняет никаких проверок на право доступа к файлу /secret/script.php, выполняя данную проверку только для файла /cgi-bin/php. Таким образом, любой пользователь c доступом к /cgi-bin/php может получить доступ к любому защищенному документу на сервере.

    В PHP, опция конфигурации компилятора--enable-force-cgi-redirect и опции конфигурации времени выполненияdoc_root и user_dir могут быть использованы для предотвращения подобных атак, если дерево документов сервера имеет каталоги с ограничением доступа. Далее приводятся подробные пояснения к различным комбинациям опций.


Вариант 1: предоставление только общего содержимого

Если ваш сервер не содержит ничего защищенного паролем или списком IP-адресов, то в вышеперечисленных опциях нет необходимости. Если ваш Web-сервер не допускает перенаправлений, или если сервер не имеет возможности безопасно перенаправить запрос приложению PHP, вы можете установить опцию --enable-force-cgi-redirect конфигурирующей программе. Однако, вам все равно придется следить за тем, чтобы ваши программы не зависели от метода их вызова, как прямого http://my.host/cgi-bin/php/dir/script.php так и с использованием перенаправления http://my.host/dir/script.php.

Перенаправление может быть настроено в сервере Apache с использованием директив AddHandler и Action directives (см. ниже).


Вариант 2: использование --enable-force-cgi-redirect

Эта опция компиляции не дает никому использовать PHP напрямую, с применением URL вроде http://my.host/cgi-bin/php/secretdir/script.php. PHP будет транслировать данные только в том случае, если они уже прошли через перенаправление Web-сервера.

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

Action php-script /cgi-bin/php
AddHandler php-script .php

Эта опция была проверена только для Web-сервера Apache и основывается на установке им не-CGI-стандартной переменной окружения REDIRECT_STATUS для перенаправленных запросов. Если ваш Web-сервер не поддерживает никаких путей указания того, осуществлялось ли перенаправление запроса, вы не можете использовать эту опцию и должны использовать другие варианты использования приложения CGI, описанные ниже.


Вариант 3: установка doc_root или user_dir

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

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

Корневой каталог документов для программ PHP можно установить с помощью директивы doc_root в файле конфигурации или с помощью переменной окружения PHP_DOCUMENT_ROOT. Если такая установка сделана, то CGI-версия PHP всегда будет добавлять к информации пути в запросе значение параметра doc_root, так что в этом случае вы можете быть уверены, что ни одна программа не выполнится за пределами этой директории (исключение составляет лишь случай с использованием параметра user_dir, описанный ниже).

Еще одной полезной опцией является user_dir. Если user_dir не задана, то единственным фактором, влияющим на имя открываемого файла является doc_root. Открытие URL вроде http://my.host/~user/doc.php не приведет в этом случае к открытию файла внутри домашнего каталога пользователя. В этом случае будет открыт файл ~user/doc.php в каталоге, заданном в doc_root.

Если user_dir установлена, к примеру, в public_php, то запрос http://my.host/~user/doc.php откроет файл doc.php в каталоге public_php, находящемся в домашнем каталоге пользователя. Если домашний каталог пользователя - /home/user, то в этом случае будет открыт файл /home/user/public_php/doc.php.

user_dir используется независимо от doc_root, что дает возможность задавать корневую директорию документов и пользовательские директории независимо друг от друга.


Вариант 4: интерпретатор PHP вне дерева документов Web

Весьма безопасным является помещение программы-транслятора PHP за пределами дерева документов Web-сервера. К примеру, в /usr/local/bin. У этого варианта есть лишь один недостаток - то, что в начало каждого файла с тэгами PHP придется помещать следующую строку:

#!/usr/local/bin/php

. Также потребуется сделать данные файлы исполняемыми, т.е. придется обращаться с ними так же, как и с любыми другими CGI-программами на Perl, sh или на других известных языках, использующих конструкцию #! для запуска.

Для того, чтобы PHP начал в данном случае корректно обрабатывать PATH_INFO и PATH_TRANSLATED, транслятор PHP должен быть скомпилирован с опцией конфигурации --enable-discard-path.


При инсталляции в виде модуля Apache

При использовании PHP, как модуля Apache, данный модуль получает все права и разрешения Apache (обычно, права пользователя "nobody", т.е. "отсутствующего" пользователя). Это вносит некоторые сложности в систему безопасности и авторизации. К примеру, если PHP используется для обращения к базе данных, то в случае отсутствия встроенного контроля доступа в базе данных ее придется сделать доступной для пользователя "nobody". В этом случае скрипт злоумышленника может получить доступ на чтение и изменение базы данных даже без указания имени пользователя и пароля. Также возможно, что сетевой червь проникнет на страницу администратора и уничтожит все ваши базы данных. Можно защититься от этого путем введения авторизации в Apache, или разработав собственную модель доступа с использованием LDAP, файлов .htaccess (и др.) и использовать этот код, как часть ваших программ на PHP.

Часто случается так, что когда безопасность достигает уровня, где PHP (а в данном случае, Apache) практически не представляет проблемы безопасности, оказывается, что PHP не может записать ни одного файла в пользовательские каталоги. Или, допустим, не имеет доступа к базам данных. PHP оказывается одинакого защищенным от записи дозволенных и недозволенных файлов, или от произведения дозволенных или недозволенных операций с базами данных.

Очень частая ошибка на этом этапе - дать PHP права "root", или администратора или каким-либо образом увеличить разрешения для Apache.

Установка для Apache разрешений администратора (root) очень опасна для системы в целом. Те, кто не является специалистами по безопасности, в данном случае должны избегать любых операций вроде "sudo" или "chroot".

Есть более простые решения. Используя open_basedir, можно контролировать и ограничивать использование PHP директорий. Также можно создать области "только для Apache", ограничив весь доступ не-пользовательскими или не-системными файлами.


Безопасность файловой системы

PHP подчиняется установкам безопасности на уровне файлов и каталогов, которые встроены в большинство серверных систем. Это позволяет контролировать, какие файлы могут быть прочитаны. С особой аккуратностью нужно относиться к файлам с правом чтения "для всех" - нужно помнить о том, они могут быть считаны любым пользователем, имеющим доступ к данной файловой системе.

Поскольку PHP разрабатывался для предоставления пользовательских прав доступа к системе, возможно создать программу на PHP, которая позволит вам читать системные файлы, такие, как /etc/passwd, изменять параметры ваших сетевых соединений, создавать большие задания для печати и т.п. Это создает ряд проблем - нужно быть уверенным в том, что именно необходимые файлы разрешены для чтения и записи.

Приведем следующую программу, где пользователь хочет стереть файл в своем домашнем каталоге. Это типичная ситуация, когда Web-интерфейс PHP используется для управления файлами, т.е. пользователи Apache имеют возможность удалять файлы в своих домашних каталогах.

Пример 5-1. Недостаточная проверка переменных - последствия...

<?php
// удаляем файл из пользовательского домашнего каталога
$username = $_POST['user_submitted_name'];
$homedir = "/home/$username";
$file_to_delete = "$userfile";
unlink ($homedir/$userfile);
echo "$file_to_delete удален!";
?>
Поскольку имя пользователя предоставляется пользовательской формой ввода, можно подставить любые имена пользователя и файла, даже если этот файл принадлежит кому-то другому. В этом случае необходимо использовать схему аутентификации пользователей. Кроме того, представьте, что случится, если переданные переменные будут соответственно "../etc/" и "passwd". Тогда программа будет выглядеть так:

Пример 5-2. ... Атака на файловую систему

<?php
// удаляет любой файл в зоне действия прав пользователя
// Если PHP имеет права администратора:
$username = "../etc/";
$homedir = "/home/../etc/";
$file_to_delete = "passwd";
unlink ("/home/../etc/passwd");
echo "/home/../etc/passwd удален!";
?>
В борьбе с подобными случаями есть два ключевых момента.

  • Назначение интерпретатору PHP ограниченных прав.

  • Проверка всех переданных переменных.

Вот улучшенная программа:

Пример 5-3. Более безопасная проверка имени файла

<?php
// удаляет любой файл в зоне действия прав пользователя
// Если PHP имеет права администратора:
$username = $_SERVER['REMOTE_USER']; // используем механизм аутентификации

$homedir = "/home/$username";

$file_to_delete = basename("$userfile"); // отрезать пути
unlink ("$homedir/$file_to_delete");

$fp = fopen("/home/logging/filedelete.log","+a"); // отчитаться об удалении
$logstring = "$username $homedir $file_to_delete";
fputs ($fp, $logstring);
fclose($fp);

echo "$file_to_delete удален!";
?>
Однако и в этом случае имеются "дырки". Если ваша система аутентификации позволяет пользователям выбирать собственные имена, и пользователь задаст имя "../etc/", система опять попадает под атаку. В этом случае можно сделать более специфическую проверку:

Пример 5-4. Еще более безопасная проверка имени файла

<?php
$username = $_SERVER['REMOTE_USER']; // используем механизм аутентификации
$homedir = "/home/$username";

if (!ereg('^[^./][^/]*$', $userfile))
     die('плохое имя файла'); // выход без обработки

if (!ereg('^[^./][^/]*$', $username))
     die('плохое имя пользователя'); // выход без обработки
//и т.д.
?>

В зависимости от вашей операционной системы, существуют файлы, о безопасности которых надо позаботиться - драйверы устройств (/dev/ или COM1), файлы конфигурации (файлы /etc/ или файлы .ini), известные области хранения данных (/home/, Mои документы), и т.д. В связи с этим, обычно проще создать политику в которой запрещено все, кроме того, что разрешено, как говорится, "вручную".


Безопасность баз данных

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

Для получения или сохранения информации в базе данных, к ней нужно подключиться, послать запрос, обработать ответ и закрыть подключение. Сегодня для всего этого обычно используется структурированный язык запросов (Structured Query Language, SQL). Давайте посмотрим, как злоумышленник может поступить с SQL-запросом.

Как известно, PHP не может сам защитить базу данных. Следующие разделы являются введением в основы доступа и использования баз данных в скриптах на PHP.

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


Планирование баз данных

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

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

Можно создать различных пользователей баз данных для каждого необходимого действия приложений, очень сильно ограничивая доступ последних к объектам базы данных. Требуемые права должны назначаться однократно, их использования в других местах приложения нужно избегать. Это значит, что если злоумышленник получит доступ с использованием той или иной учетной записи, он сможет получить лишь тот доступ, которым обладала использованная часть программы.

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


Подключение к базе данных

Можно устанавливать подключения с помощью SSL для шифрования соединений клиент-сервер, что дает повышенную безопасность. А можно использовать ssh для шифрования сетевых соединений между клиентами и сервером баз данных. Любой из этих способов сильно усложняет отслеживание и получение информации из сетевого траффика.


Хранение зашифрованных данных

SSL/SSH защищает данные только по пути от клиента к серверу, но не данные, хранимые в базе данных. SSL - лишь сетевой протокол.

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

Самый легкий путь в этом случае - создать свою собственную систему шифрования, а затем использовать ее в скриптах на PHP. PHP способствует такому подходу благодаря наличию специфичных раширений, таких, как Mcrypt и Mhash, охватывающих большой ряд алгоритмов шифрования. Программа шифрует сохраняемые данные и расшифровывает получаемые. Для детального описания схем шифрования смотрите ссылки.

В случае скрытых данных, где не требуется их исходный вид (к примеру, для отображения), можно использовать хеширование. Известным примером хеширования является сохранение в базе данных хеша MD5 от пароля вместо самого пароля. Для подробного описания смотрите crypt() и md5().

Пример 5-5. Использование хешированных паролей

// сохраняем хеш от пароля
$query  = sprintf("INSERT INTO users(name,pwd) VALUES('%s','%s');",
            addslashes($username), md5($password));
$result = pg_exec($connection, $query);

// проверяем корректность введенного пользователем пароля
$query = sprintf("SELECT 1 FROM users WHERE name='%s' AND pwd='%s';",
            addslashes($username), md5($password));
$result = pg_exec($connection, $query);

if (pg_numrows($result) > 0) {
    echo "Добро пожаловать, $username!";
}
else {
    echo "Введен неверный пароль для $username.";
}

Внедрение в SQL

Многие разработчики Web-приложений считают запросы SQL не стоящими внимания, не зная о том, что их может использовать злоумышленник. Это означает, что запросы SQL могут быть использованы для обхода систем защиты, аутентификации и авторизации, а также иногда могут быть использованы для получения доступа к командам уровня операционной системы.

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

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

Пример 5-6. Разделение результата запроса по страницам и... создание суперпользователей (PostgreSQL и MySQL)

$offset = argv[0]; // внимание! нет проверки данных!
$query  = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
// в PostgreSQL 
$result = pg_exec($conn, $query);
// в MySQL
$result = mysql_query($query);
Обычно пользователи используют кнопочки "следующая" и "предыдущая", где $offset внедрен в URL. Программа считает, что $offset - число. Однако, кто-нибудь может попытаться внедриться путем добавления urlencode()-кодированных данных в URL

// в случае PostgreSQL
0;
insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
    select 'crack', usesysid, 't','t','crack'
    from pg_shadow where usename='postgres';
--

// в случае MySQL
0;
UPDATE user SET Password=PASSWORD('crack') WHERE user='root';
FLUSH PRIVILEGES;

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

Замечание: Обычная практика - заставить транслятор SQL проигнорировать остаток запроса разработчика с помощью обозначения начала коментария SQL --.

Существует путь получения паролей через ваши страницы поиска. Все, что нужно злоумышленнику - это одна не обработанная должным образом переменная, используемая в SQL-запросе. Использоваться могут команды WHERE, ORDER BY, LIMIT и OFFSET запроса SELECT. Если ваша база данных поддерживает конструкцию UNION, злоумышленник может добавить к исходному запросу еще один - для получения паролей. В этом случае поможет хранение зашифрованных паролей.

Пример 5-7. Вывод статей... и паролей (любой сервер баз данных)

$query  = "SELECT id, name, inserted, size FROM products
                  WHERE size = '$size'
                  ORDER BY $order LIMIT $limit, $offset;";
$result = odbc_exec($conn, $query);
Статическая часть запроса может быть совмещена с другим запросом SELECT, который выведет все пароли:

'
union select '1', concat(uname||'-'||passwd) as name, '1971-01-01', '0' from usertable;
--

Если подобный запрос (использующий ' и --) будет задан в одной из переменных, используемых $query, то атака будет успешной.

Запросы SQL "UPDATE" также могут быть использованы для атаки на базу данных. Эти запросы также подвержены опасности "обрезки" и добавления новых запросов. Но здесь злоумышленник работает с командой SET. В этом случае необходимо знание некоторой информации о структуре базы данных для удачной модификации запроса. Такая информация может быть получена путем изучения названий переменных форм или просто подбором. В конце концов, не так уж и много имен придумано для полей пользователей и паролей.

Пример 5-8. От сброса пароля до получения привилегий... (любой сервер баз данных)

$query = "UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';";
Злоумышленник посылает значение ' or uid like'%admin%'; --, в переменную $uid для изменения пароля администратора или просто устанавливает $pwd в "hehehe', admin='yes', trusted=100 " (с завершающим пробелом) для получения прав. Запрос будет искажен так:

// $uid == ' or uid like'%admin%'; --
$query = "UPDATE usertable SET pwd='...' WHERE uid='' or uid like '%admin%'; --";

// $pwd == "hehehe', admin='yes', trusted=100 "
$query = "UPDATE usertable SET pwd='hehehe', admin='yes', trusted=100 WHERE ...;"

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

Пример 5-9. Атака на операционную систему сервера баз данных (сервер MSSQL)

$query  = "SELECT * FROM products WHERE id LIKE '%$prod%'";
$result = mssql_query($query);
Если злоумышленник пошлет значение a%' exec master..xp_cmdshell 'net user test testpass /ADD' -- в $prod, то $query будет выглядеть так:

$query  = "SELECT * FROM products
                    WHERE id LIKE '%a%'
                    exec master..xp_cmdshell 'net user test testpass /ADD'--";
$result = mssql_query($query);

Сервер MSSQL выполняет все команды SQL, включая команду добавления нового пользователя в локальную базу данных пользователей. Если это приложение было запущено, как sa и служба MSSQLSERVER имеет достаточно прав, злоумышленник будет иметь учетную запись для доступа к этой машине.

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


Техника защиты

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

Большинство атак построены на использовании кода, который писался без учета соображений безопасности. Никогда не доверяйте введенным данным, особенно если они идут с клиентской стороны, пусть даже и из поля отметки, скрытого поля или записи cookie. Первый пример показывает, к чему может привести подмена этих данных.

  • Никогда не соединяйтесь с базой данных в роли суперпользователя или владельца. Всегда используйте специальных пользователей с минимумом прав.

  • Проверяйте ввод на совпадение типа данных с требуемым. PHP включает в себя большое количество проверочных функций, от самых простейших из разделов "Функции для работы с переменными" и "Функции обработки символьного типа", (к примеру is_numeric() и ctype_digit() соответственно) до регулярных выражений Perl ("Регулярные выражения, совместимые с Perl").

  • Если программа ожидает число, проверяйте данные с помощью is_numeric(), или просто изменяйте тип с помощью settype(), или даже используйте численное представление, выданное sprintf().

    Пример 5-10. Более безопасная разбивка на страницы

    settype($offset, 'integer');
    $query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
    
    // отметим %d в строке форматирования, использование %s бесполезно
    $query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;",
                     $offset);

  • Предваряйте любой нечисловой ввод, передаваемый в базу данных, функциями addslashes() или addcslashes(). В первом примере показано, что кавычек в статической части запроса недостаточно.

  • Не выводите никакой информации о структуре базы данных ни коим образом. Для описания подробностей смотрите раздел "Отчеты об ошибках" и "Функции обработки и учета ошибок".

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

Кроме того, ведите журнал операций в программе или собственно в базе данных, если это поддерживается. Ведение журнала не предотвратит внедрения, но оно поможет определить, какая часть программы была поставлена под удар. Сам журнал бесполезен - полезна хранимая в нем информация. Чем ее больше - тем лучше.


Отчеты об ошибках

В случае настройки безопасности PHP у отчета об ошибках есть две стороны. Одна - плюс в сторону безопасности, другая - наоборот.

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

Пример 5-11. Атака на переменные с помощью собственной страницы HTML

<form method="post" action="attacktarget?username=badfoo&password=badfoo">
<input type="hidden" name="username" value="badfoo">
<input type="hidden" name="password" value="badfoo">
</form>

Ошибки, которые обычно возвращаются PHP, очень помогают в отладке программ, указывая на файл или функцию, а также номер строки где произошла ошибка. Однако, вся эта информация может быть использована. Очень часто разработчики используют функции show_source(), highlight_string() или highlight_file(), как отладочные, но в реальном случае они могут показать скрытые переменные, неотлаженные участки кода и другую опасную информацию. Особенно опасен запуск кода с встроенными отладочными частями или с использованием технологий отладки. Если злоумышленник определит вашу схему отладки, он может просто послать вашему коду отладочные команды для произведения своих действий.

Пример 5-12. Использование отладочных переменных

<form method="post" action="attacktarget?errors=Y&amp;showerrors=1"&debug=1">
<input type="hidden" name="errors" value="Y">
<input type="hidden" name="showerrors" value="1">
<input type="hidden" name="debug" value="1">
</form>

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

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

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

Ошибки файловой системы или общие ошибки PHP могут открыть заданные Web-серверу разрешения, а также структуру файлов сервера. Коды ошибок разработчика ухудшают ситуацию, приводя к весьма примитивному использованию "официально скрытой" информации.

Есть три основных пути решения проблемы. Первый - отладить все функции и попытаться компенсировать наличие ошибок. Второй - полностью отключить отчет об ошибках. Третий - использовать собственный обработчик ошибок PHP. Выбор зависит от вашего желания и структуры вашей системы безопасности.

Еще один способ решения проблемы "досрочно" - использование встроенной опции PHP error_reporting(), для того, чтобы обезопасить программу и найти уязвимые переменные. Тестируя программу до развертывания с E_ALL можно быстро найти места, где переменные могут быть открыты для модификации. Как только программа готова к развертыванию, E_NONE предотвращает исследование.

Пример 5-13. Нахождение небезопасных переменных с помощью E_ALL

<?php
if ($username) {  // не инициализирована и не проверяется перед использованием
    $good_login = 1;
}
if ($good_login == 1) { // если предыдущий тест не прошел, значит $username не инициализирована
    fpassthru ("/highly/sensitive/data/index.html");
}
?>


Использование опции register-globals

Еще одно средство PHP для повышения безопасности - конфигурация с использованием register_globals = off. Это отключает внедрение пользовательских переменных в среду переменных программы на PHP, сводя попытки внедрения злоумышленником нужных ему значений на нет. Опция полностью изолирует внутренние переменные от предоставляемых пользователем данных.

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

Пример 5-14. Программа с register_globals=on

<?php
if ($username) {  // может быть подменена пользователем в get/post/cookies
    $good_login = 1;
}

if ($good_login == 1) { // также может быть подменена пользователем в get/post/cookies
    fpassthru ("/highly/sensitive/data/index.html");
}
?>

Пример 5-15. Программа с register_globals = off

<?php
if($_COOKIE['username']){
    // может прийти только из записи cookie, нормальной или поддельной
    $good_login = 1;
    fpassthru ("/highly/sensitive/data/index.html");
}
?>
Разумно используя данный метод, можно даже принять меры предотвращения подмены данных, предупреждая, когда таковая предпринимается. Если известно, где должна быть необходимая переменная, можно проверить, не идет ли она от недопустимого источника. Это не гарантирует отсутствие подмены данных, но злоумышленнику придется искать правильный путь подмены.

Пример 5-16. Простейшая проверка на подмену данных

<?php
if ($_COOKIE['username'] &&
    !$_POST['username'] &&
    !$_GET['username'] ) {
    // произвести проверку имени пользователя
    $good_login = 1;
    fpassthru ("/highly/sensitive/data/index.html");
} else {
   mail("admin@example.com", "Возможна подмена данных ", $_SERVER['REMOTE_ADDR']);
   echo "Ошибка безопасности. Произведено оповещение администратора.";
   exit;
}
?>
Конечно, выключение register_globals не означает, что программа безопасна. Все входные данные все равно требуют дополнительной проверки.


Данные, отправленные пользователем

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

Пример 5-17. Небезопасное использование переменной

<?php
// удаление файла из пользовательского домашнего каталога... или из чьего-то еще?
unlink ($evil_var);

// запись журнала доступа... или запись в /etc/passwd?
fputs ($fp, $evil_var);

// исполнение чего-нибудь простенького.. или rm -rf *?
system ($evil_var);
exec ($evil_var);

?>
Всегда нужно аккуратно исследовать программу, чтобы убедиться, что все переменные, передаваемые пользователем, проверяются. Можно даже задавать себе следующие вопросы:

  • Будет ли эта программа использовать именно необходимые файлы?

  • Могут ли быть обработаны необычные или нежелательные данные?

  • Может ли эта программа использоваться нежелательным образом?

  • Может ли она использоваться в совокупности с другими программами для реализации злого умысла?

  • Будут ли должным образом записаны в журнал операции?

Задавая себе эти вопросы во время написания программы, можно предотвратить переписывание ее "с нуля" в связи с проблемами безопасности. Переняв подобный образ мышления, вы не гарантируете безопасности системы, но увеличите эту безопасность.

Также следует подумать об отключении register_globals, magic_quotes, и других опций, которые ставят под сомнение корректность, источник и значения отдельно взятых переменных. Работа в режиме отображения всех ошибок (error_reporting=E_ALL) также предупредит об использовании переменных без предварительной проверки и инициализации.


Скрытие PHP

В общем случае, скрытие - самая слабая форма системы безопасности. Но в некоторых случаях необходима любая малость.

Есть несколько приемов, позволяющих скрыть PHP, что замедлит действия злоумышленника, пытающегося обнаружить слабости в вашей системе. Установка в файле php.ini опции expose_php = off уменьшит количество доступной информации.

Другая тактика - настройка сервера Web (вроде Apache) для обработки различных типов файлов с помощью PHP. Это делается через директивы .htaccess или через файл конфигурации Apache. Затем можно использовать "отвлекающие" расширения файлов:

Пример 5-18. Скрытие PHP под видом другого языка

# Делаем код PHP похожим на код других языков
AddType application/x-httpd-php .asp .py .pl
Или вносим путаницу:

Пример 5-19. Использование неизвестных расширений для PHP

# Делаем PHP ни на что не похожим
AddType application/x-httpd-php .bop .foo .133t
Или даже можно скрыть PHP под видом html, что приведет к небольшой потере производительности, поскольку все .html-файлы будут обрабатываться интерпретатором PHP.

Пример 5-20. Использование расширений html для PHP

# Делаем PHP похожим на html
AddType application/x-httpd-php .htm .html
Чтобы все это работало, надо переименовать файлы PHP в файлы с вышеперечисленными расширениями. Хотя это и подвид безопасности через скрытие, это одна из мер предотвращения атак с минимумом известных минусов.


В ногу со временем

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

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


Глава 6. Основы синтаксиса

Вставка в HTML

Когда PHP обрабатывает файл, он просто передаёт его текст, пока не встретит один из специальных тегов, который сообщает ему о необходимости начать интерпретацию текста как кода PHP. Затем он выполняет весь найденный код до закрывающего тега, говорящего интерпретатору, что далее снова идет просто текст. Этот механизм позволяет вам внедрять PHP-код в HTML - все за пределами тегов PHP остается неизменным, тогда как внутри - интерпретируется как код.

Существует четыре набора тегов, которые могут быть использованы для обозначения PHP-кода. Из них только два (<?php. . .?> и <script language="php">. . .</script>) всегда доступны; другие могут быть включены или выключены в конфигурационном файле php.ini. Хотя короткие теги и теги в стиле ASP могут быть удобны, они не так переносимы, как длинные версии. Кроме того, если вы намереваетесь вставлять PHP-код в XML или XHTML, чтобы соответствовать XML, вам следует использовать форму <?php. . .?>.

Теги, поддерживаемые PHP:

Пример 6-1. Способы вставки в HTML

1.  <?php echo("если вы хотите работать с документами XHTML или XML, делайте так\n"); ?>

2.  <? echo ("это простейшая инструкция обработки SGML\n"); ?>
    <?= выражение ?> Это синоним для "<? echo выражение ?>"
    
3.  <script language="php">
        echo ("некоторые редакторы (например, FrontPage) не
              любят инструкции обработки");
    </script>

4.  <% echo ("Вы можете по выбору использовать теги в стиле ASP"); %>
    <%= $variable; # Это синоним для "<% echo . . ." %>

Первый способ, <?php. . .?>, наиболее предпочтительный, так как он позволяет использовать PHP в коде, соответствующем правилам XML, таком как XHTML.

Второй способ не всегда доступен. Короткие теги доступны только когда они включены. Это можно сделать, используя функцию short_tags() (только в PHP 3), включив установку short_open_tag в конфигурационном файле PHP, либо скомпилировав PHP с параметром --enable-short-tags для configure. Даже если оно включено по умолчанию в php.ini-dist, использование коротких тегов не рекомендуется.

Четвертый способ доступен только если теги в стиле ASP были включены, используя конфигурационную установку asp_tags.

Замечание: Поддержка тегов в стиле ASP была добавлена в версии 3.0.4.

Замечание: Следует избегать использования коротких тегов при разработке приложений или библиотек, предназначенных для распространения или размещения на PHP-серверах, не находящихся под вашим контролем, так как короткие теги могут не поддерживаться на целевом сервере. Для создания переносимого, совместимого кода, не используйте короткие теги.

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

PHP позволяет использовать такие структуры:

Пример 6-2. Профессиональная вставка

<?php
if ($expression) { 
    ?>
    <strong>Это истина.</strong>
    <?php 
} else { 
    ?>
    <strong>Это ложь.</strong>
    <?php 
}
?>
Этот код работает так, как ожидается, потому что когда PHP встречает закрывающие теги ?>, он просто выводит все, что он находит до следующего открывающего тега. Приведенный здесь пример конечно придуманный, но для вывода больших блоков текста выход из режима интерпретации PHP обычно более эффективен, чем отправка всего текста через echo(), print() или что-либо подобное.


Разделение инструкций

Инструкции разделяются также как и в C или Perl - каждое выражение заканчивается точкой с запятой.

Закрывающий тег (?>) также подразумевает конец инструкции, поэтому два следующих фрагмента кода эквиваленты:

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

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


Комментарии

PHP поддерживает комметарии в стиле 'C', 'C++' и оболочки Unix. Например:

<?php
    echo "Это тест"; // Это однострочный комментарий в стиле c++
    /* Это многострочный комментарий
       еще одна строка комментария */
    echo "Это еще один тест";
    echo "Последний тест"; # Это комментарий в стиле оболочки Unix
?>

Однострочные комментарии идут только до конца строки или текущего блока PHP-кода, в зависимости от того, что идет перед ними.

<h1>Это <?php # echo "простой";?> пример.</h1>
<p>Заголовок вверху выведет 'Это пример'.

Будьте внимательны, следите за отсутствием вложенных 'C'-комментариев, они могут появиться во время комментирования больших блоков.

<?php
 /* 
    echo "Это тест"; /* Этот комментарий вызовет проблему */
 */
?>

Однострочные комментарии идут только до конца строки или текущего блока PHP-кода, в зависимости от того, что идет перед ними. Это означает, что HTML-код после // ?> БУДЕТ напечатан: ?> выводит из режима PHP и возвращает в режим HTML, но // не позволяет этого сделать.


Глава 7. Типы

Введение

PHP поддерживает восемь простых типов.

Четыре скалярных типа:

Два смешанных типа:

И, наконец, два специальных типа:

В этой документации также представлено несколько псевдо-типов для удобства понимания:

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

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

Замечание: Если вы желаете проверить тип и значение определенного выражения, используйте var_dump().

Замечание: Если же вам для отладки необходимо просто удобочитаемое представление типа, используйте gettype(). Чтобы проверить на определенный тип, не используйте gettype(), применяйте для этого is_type функции. Вот несколько примеров:

$bool = TRUE;   // логический
$str  = "foo";  // строковый
$int  = 12;     // целочисленный

echo gettype($bool); // выводит "boolean"
echo gettype($str);  // выводит "string"

// Если это целое, увеличить на четыре
if (is_int($int)) {
    $int += 4;
}

// Если $bool - это строка, вывести ее
// (ничего не выводит)
if (is_string($bool)) {
    echo "Строка: $bool";
}

Если вы хотите принудительно изменить тип переменной, вы можете либо привести переменную, либо использовать функцию settype().

Обратите внимание, что переменная, в зависимости от ее типа в данный момент, в определенных ситуациях может иметь разные значения. Более подробную информацию смотрите в разделе Манипуляции с типами.


Булев

Это простейший тип. Он выражает истинность значения - это может быть либо TRUE, либо FALSE.

Замечание: Булев тип был введен в PHP 4.


Синтаксис

Чтобы определить булев тип, используйте ключевое слово TRUE или FALSE. Оба регистро-независимы.

$foo = True; // определить $foo как TRUE

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

// == это оператор, который проверяет
// эквивалентность и возвращает булево значение
if ($action == "показать_версию") {
    echo "Версия 1.23";
}

// это не обязательно...
if ($show_separators == TRUE) {
    echo "<hr>\n";
}

// ...потому что вы можете просто написать
if ($show_separators) {
    echo "<hr>\n";
}


Конвертация в булев тип

Для несомненной конвертации значения в булев тип используйте привидение типа (bool) или (boolean). Однако в большинстве случаев вам нет необходимости использовать привидение типа, поскольку значение будет автоматически конвертировано, если оператор, функция или управляющая конструкция требует булев аргумент.

Смотрите также Манипуляции с типами.

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

Все остальные значения рассматриваются как TRUE (включая любой источник).

Внимание

-1 считается TRUE, как и любое ненулевое (отрицательное или положительное) число!

echo gettype((bool) "");        // bool(false)
echo gettype((bool) 1);         // bool(true)
echo gettype((bool) -2);        // bool(true)
echo gettype((bool) "foo");     // bool(true)
echo gettype((bool) 2.3e5);     // bool(true)
echo gettype((bool) array(12)); // bool(true)
echo gettype((bool) array());   // bool(false)


Целые

Целое это число из множества Z = {..., -2, -1, 0, 1, 2, ...}.

Смотрите также: Целые произвольной длины и Числа с плавающей точкой


Синтаксис

Целые могут быть указаны в десятичной, шестнадцатеричной или восьмеричной системе счисления, по желанию с предшествующим знаком (- или +).

Если вы используете восьмеричную систему счисления, вы должны предварить число 0 (нулем), для использования шестнадцатеричной системы нужно поставить перед числом 0x.

Пример 7-1. Целые

$a = 1234; # десятичное число
$a = -123; # отрицательное число
$a = 0123; # восьмеричное число (эквивалентно 83 в десятичной системе)
$a = 0x1A; # шестнадцатеричное число (эквивалентно 26 в десятичной системе)
Формально возможная структура целых такова:

десятичные        : [1-9][0-9]*
                  | 0

шестнадцатеричные : 0[xX][0-9a-fA-F]+

восьмеричные      : 0[0-7]+

целые             : [+-]?десятичные
                  | [+-]?шестнадцатеричные
                  | [+-]?восьмеричные

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


Превышение размера целого

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

$large_number =  2147483647;
var_dump($large_number);
// вывод: int(2147483647)

$large_number =  2147483648;
var_dump($large_number);
// вывод: float(2147483648)

// это справедливо и для шестнадцатеричных целых:
var_dump( 0x80000000 );
// вывод: float(2147483648)

$million = 1000000;
$large_number =  50000 * $million;
var_dump($large_number);
// вывод: float(50000000000)

Внимание

К сожалению, в PHP была ошибка, так что это не всегда верно работает, когда используются отрицательные числа. Например: когда вы умножаете -50000 * $million, результатом будет -429496728. Однако, если оба операнда положительны, проблем не возникает.

Эта ошибка устранена в PHP 4.1.0.

в PHP не существует оператора деления целых. Результатом 1/2 будет число с плавающей точкой 0.5. Вы можете привести значение к целому, что всегда округляет его в меньшую сторону, либо использовать функцию round().

var_dump(25/7);         // float(3.5714285714286) 
var_dump((int) (25/7)); // int(3)
var_dump(round(25/7));  // float(4)


Конвертация в целое

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

Смотрите также Манипуляции с типами.


Из булева типа

FALSE конвертируется в 0 (ноль), а TRUE - в 1 (единицу).


Из чисел с плавающей точкой

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

Если число с плавающей точкой превышает пределы целого (как правило, это +/- 2.15e+9 = 2^31), результат будет неопределённым, так как целое не имеет достаточной точности, чтобы вернуть верный результат. В этом случае не будет выведено ни предупреждения, ни даже замечания!

Внимание

Никогда не приводите неизвестную дробь к целому, так как это может иногда дать неожиданные результаты.

echo (int) ( (0.1+0.7) * 10 ); // выводит 7!

Смотрите более подробно: предупреждение о точности числел с плавающей точкой.


Из строк

Смотрите Конвертация строк в числа


Из других типов

Предостережение

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


Числа с плавющей точкой

Числа с плавющей точкой (они же числа двойной точности или действительные числа) могут быть определены при помощи любого из следующих синтаксисов:

$a = 1.234; $a = 1.2e3; $a = 7E-10;

Формально:

LNUM          [0-9]+
DNUM          ([0-9]*[\.]{LNUM}) | ({LNUM}[\.][0-9]*)
EXPONENT_DNUM ( ({LNUM} | {DNUM}) [eE][+-]? {LNUM})

Размер целого зависит от платформы, хотя максимум, как правило, ~1.8e308 с точностью около 14 десятичных цифр (это 64-битный IEEE-формат).

Точность числа с плавающей точкой

Довольно часто простые десятичные дроби вроде 0.1 или 0.7 не могут быть конвертированы в свои внутренние двоичные аналоги без небольшой потери точности. Это может привести к неожиданным результатам: например, floor((0.1+0.7)*10) скорее всего возвратит 7 вместо ожидаемой 8 как результат внутреннего представления числа, являющегося в действительности чем-то вроде 7.9999999999....

Это связано с невозможностью точно выразить некоторые дроби в десятичной системе счисления конечным числом цифр. Например, 1/3 в десятичной форме принимает вид 0.3333333. . ..

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


Конвертация в число с плавающей точкой

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


Строки

Строка - это набор символов. В PHP символ это то же самое, что и байт, это значит, что возможно ровно 256 различных символов. Это также означает, что PHP не имеет встроенной поддержки Unicode'а. Некоторую поддержку Unicode'а обеспечивают эти функции utf8_enncode() и utf8_decode().

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


Синтаксис

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


Одинарные кавычки

Простейший способ определить строку - это заключить ее в одинарные кавычки (символ ').

Чтобы использовать одинарную кавычку внутри строки, как и во многих других языках, ее необходимо предварить символом обратной косой черты (\), т. е. мнемонизировать ее. Если обратная наклонная черта должна идти перед одинарной кавычкой либо быть в конце строки, вам необходимо продублировать ее. Обратите внимание, что если вы попытаетесь мнемонизировать любой другой символ, обратная косая черта также будет напечатана! Так что, как правило, нет необходимости мнемонизировать саму обратную косую черту.

Замечание: В PHP 3 в данном случае будет выдано сообщение уровня E_NOTICE.

Замечание: В отличие от двух других синтаксисов, переменные, встречающиеся в строках, заключенных в одинарные кавычки, не обрабатываются.

echo ''это простая строка';
echo 'Вы можете вставлять в строки символ новой строки
таким образом';
echo 'Однажды Арнольд сказал: "I\'ll be back"';
// вывод: ... "I'll be back"
echo 'Вы уверены, что хотите удалить C:\\*.*?';
// вывод: ... удалить C:\*.*?
echo 'Вы уверены, что хотите удалить C:\*.*?';
// вывод: ... удалить C:\*.*?
echo 'Я пытаюсь вставить в этой точке: \n символ новой строки';
// вывод: ... в этой точке: \n символ новой строки


Двойные кавычки

Если строка заключена в двойные кавычки ("), PHP распознает большее количество мнемоник специальных символов:

Таблица 7-1. Мнемоники символов

последовательностьзначение
\nновая строка (LF или 0x0A (10) в ASCII)
\rвозврат каретки (CR или 0x0D (13) в ASCII)
\tгоризонтальная табуляция (HT или 0x09 (9) в ASCII)
\\обратная наклонная черта
\$знак доллара
\"двойная кавычка
\[0-7]{1,3} последовательность символов, соответсвующая регулярному выражению, символ в восьмеричной системе счисления
\x[0-9A-Fa-f]{1,2} последовательность символов, соответсвующая регулярному выражению, символ в шестнадцатеричной системе счисления

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

Но самым важным свойством строк в двойных кавычках является обработка переменных. Смотрите более подробно: обработка строк.


Heredoc

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

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

Внимание

Важно отметить, что строка с закрывающим идентификатором не содержит других символов, за исключением, возможно, точки с запятой (;). Это означает, что идентификатор не должен вводиться с отступом и что не может быть никаких пробелов или знаков табуляции до или после точки с запятой.

Heredoc-текст ведёт себя так же, как и строка в двойных кавычках, но без них. Это означает, что вам нет необходимости мнемонизировать кавычки в heredoc, но вы по-прежнему можете использовать вышеперечисленные коды-мнемоники. Переменные обрабатываются, но с применением сложных переменных внутри heredoc нужно быть также внимательным, как и при работе со строками.

Пример 7-2. Пример определения heredoc-строки

<?php
$str = <<<EOD
Пример строки,
охватывающей несколько строчек
с использованием heredoc-синтаксиса.
EOD;

/* Более сложный пример с переменными. */
class foo
{
    var $foo;
    var $bar;

    function foo()
    {
        $this->foo = 'Foo';
        $this->bar = array('Bar1', 'Bar2', 'Bar3');
    }
}

$foo = new foo();
$name = 'МоеИмя';

echo <<<EOT
Меня зовут "$name". Я печатаю $foo->foo.
Теперь я вывожу {$foo->bar[1]}.
Это должно вывести заглавную букву 'A': \x41
EOT;
?>

Замечание: Поддержка heredoc была добавлена в PHP 4.


Обработка переменных

Если строка определяется в двойных кавычках, либо при помощи heredoc, переменные внутри нее обрабатываются.

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

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


Простой синтаксис

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

$beer = 'Heineken';
echo "$beer's taste is great"; // работает, "'" это неверный символ для имени переменной
echo "He drank some $beers";   // не работает, 's' это верный символ для имени переменной
echo "He drank some ${beer}s"; // работает

Точно также могут быть обработаны элемент массива или свойство объекта. В элементах массива закрывающая квадратная скобка (]) обозначает конец определения элемента. Для свойств объекта применяются те же правила, что и для простых переменных, хотя с ними невозможен трюк, как с переменными.

$fruits = array('strawberry' => 'red', 'banana' => 'yellow');

// Заметьте, что вне кавычек эта конструкция работает по-другому
echo "A banana is $fruits[banana].";

echo "This square is $square->width meters broad.";

// Не работает. Для решения см. сложный синтаксис.
echo "This square is $square->width00 centimeters broad.";

Для чего-либо более сложного вы должны использовать сложный синтаксис.


Сложный (фигурный) синтаксис

Он называется сложным не потому, что труден в понимании, а потому что позволяет использовать сложные выражения.

Фактически, вы можете включить любое значение, находящееся в пространстве имени в строке с этим синтаксисом. Вы просто записываете выражение таким же образом, как и вне строки, а затем заключаете его в { и }. Поскольку вы не можете заменить мнемоникой '{', этот синтаксис будет распознаваться только когда $ следует непосредственно за {. (Используйте "{\$" или "\{$" чтобы отобразить "{$"). Несколько поясняющих примеров:

$great = 'fantastic';
echo "This is { $great}"; // не будет работать, выведет: This is { fantastic}
echo "This is {$great}";  // работает, выведет: This is fantastic
echo "Этот квадрат шириной {$square->width}00 сантиметров."; 
echo "Это работает: {$arr[4][3]}";

// Это неверно по той же причине,
// что и $foo[bar] неверно вне строки.
echo "Это неправильно: {$arr[foo][3]}"; 

echo "Следует делать это так: {$arr['foo'][3]}";
echo "Вы можете даже записать {$obj->values[3]->name}";
echo "Это значение переменной по имени $name: {${$name}}";


Доступ к символу в строке

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

Замечание: Для обеспечения обратной совместимости, вы по-прежнему имеете возможность использовать в тех же целях скобки массива. Однако, начиная с PHP 4, этот синтаксис нежелателен к использованию.

Пример 7-3. Несколько примеров строк

<?php
// Получение первого символа строки
$str = 'Это тест.';
$first = $str{0};

// Получение последнего символа строки
$str = 'Это все еще тест.';
$last = $str{strlen($str)-1}; 
?>


Полезные функции и операторы

Строки могут быть объединены при помощи оператора '.' (точка). Обратите внимание, оператор сложения '+' здесь не работает. Дополнительную информацию смотрите в разделе Строковые операторы.

Для модификации строк существует множество полезных функций.

Основные функции описаны в разделе строковых функций, функции регулярных выражений для расширенного поиска и замены (в двух частях: Perl и POSIX расширенный).

Также существуют функции для URL-строк, и функции для шифрования/дешифрования строк (mcrypt и mhash).

Наконец, если вы все еще не нашли, что искали, смотрите также функции для символьного типа.


Конвертация в строку

Вы можете конвертировать значение в строку, используя приведение (string), либо функцию strval(). В выражениях, где необходима строка, конвертация происходит автоматически. Это происходит, когда вы используете функции echo() или print(), либо когда вы сравниваете значение переменной со строкой.

Логическое значение TRUE конвертируется в строку "1", а значение FALSE представляется как "" (пустая строка). Этим способом вы можете конвертировать значения в обе стороны из булева типа в строковый и наоборот.

Целое или число с плавающей точкой конвертируется в строку, представленную числом, состоящим из его цифр (включая показалтель степени для чисел с плавающей точкой).

Массивы всегда конвертируются в строку "Array", так что вы не можете отобразить содержимое массива, используя echo() или print(), чтобы узнать, что он содержит. Дополнительные советы вы можете найти ниже.

Объекты всегда конвертируются в строку "Object". Если вы хотите вывести значение переменной-члена объекта по причине отладки, прочтите следующие абзацы. Если вы хотите получить имя класса требуемого объекта, используйте функцию get_class().

Ресурсы всегда конвертируются в строки со структурой "Resource id #1", где 1 - это уникальный номер ресурса, присвоенный ему PHP во время выполнения. Если вы хотите получить тип ресурса, используйте функцию get_resource_type().

NULL всегда конвертируется в пустую строку.

Как вы могли видеть выше, вывод массивов, объектов или ресурсов не предоставляет вам никакой полезной информации о самих значениях. Более подходящий способ вывода значений для отладки - использовать функции print_r() и var_dump().

Вы также можете конвертировать значения PHP в строки для постоянного хранения. Этот метод называется сериализацией и может быть выполнен при помощи функции serialize(). Кроме того, если в вашей установке PHP есть поддержка WDDX, вы можете сериализовать значения PHP в структуры XML.


Конвертация строк в числа

Если строка распознается как числовое значение, результирующее значение и тип определяется так как показано далее.

Строка будет распознана как float, если она содержит любой из символов '.', 'e', или 'E'. Иначе она будет определена как целое.

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

$foo = 1 + "10.5";              // $foo это float (11.5)
$foo = 1 + "-1.3e3";            // $foo это float (-1299)
$foo = 1 + "bob-1.3e3";         // $foo это integer (1)
$foo = 1 + "bob3";              // $foo это integer (1)
$foo = 1 + "10 Small Pigs";     // $foo это integer (11)
$foo = 4 + "10.2 Little Piggies"; // $foo это float (14.2)
$foo = "10.0 pigs " + 1;        // $foo это float (11)
$foo = "10.0 pigs " + 1.0;      // $foo это float (11)

Более подробную информацию об этой конвертации смотрите в документации по Unix в разделе о strtod(3).

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

echo "\$foo==$foo; тип: " . gettype ($foo) . "<br />\n";

Не ожидайте получить код символа, конвертировав его в целое (как вы могли бы сделать, например, в C). Для конвертации символов в их коды и обратно используйте функции ord() и chr().


Массивы

An array in PHP is actually an ordered map. A map is a type that maps values to keys. This type is optimized in several ways, so you can use it as a real array, or a list (vector), hashtable (which is an implementation of a map), dictionary, collection, stack, queue and probably more. Because you can have another PHP-array as a value, you can also quite easily simulate trees.

Explanation of those structures is beyond the scope of this manual, but you'll find at least one example for each of those structures. For more information we refer you to external literature about this broad topic.


Syntax

Specifying with array()

An array can be created by the array() language-construct. It takes a certain number of comma-separated key => value pairs.

array( [key =>] value
     , ...
     )
// key is either string or nonnegative integer
// value can be anything

array("foo" => "bar", 12 => true);

A key is either an integer or a string. If a key is the standard representation of an integer, it will be interpreted as such (i.e. "8" will be interpreted as 8, while "08" will be interpreted as "08"). There are no different indexed and associative array types in PHP, there is only one array type, which can both contain integer and string indices.

A value can be of any PHP type.

array("somearray" => array(6 => 5, 13 => 9, "a" => 43));

If you omit a key, the maximum of the integer-indices is taken, and the new key will be that maximum + 1. As integers can be negative, this is also true for negative indices. Having e.g. the highest index being -6 will result in being -5 the new key. If no integer-indices exist yet, the key will be 0 (zero). If you specify a key that already has a value assigned to it, that value will be overwritten.

// This array is the same as ...
array(5 => 43, 32, 56, "b" => 12);

// ...this array
array(5 => 43, 6 => 32, 7 => 56, "b" => 12);

Using TRUE as a key will evalute to integer 1 as key. Using FALSE as a key will evalute to integer 0 as key. Using NULL as a key will evaluate to an empty string. Using an emptry string as key will create (or overwrite) a key with an empty string and its value, it is not the same as using empty brackets.

You cannot use arrays or objects as keys. Doing so will result in a warning: Illegal offset type.


Creating/modifying with square-bracket syntax

You can also modify an existing array, by explicitly setting values in it.

This is done by assigning values to the array while specifying the key in brackets. You can also omit the key, add an empty pair of brackets ("[]") to the variable-name in that case.
$arr[key] = value;
$arr[] = value;
// key is either string or nonnegative integer
// value can be anything
If $arr doesn't exist yet, it will be created. So this is also an alternative way to specify an array. To change a certain value, just assign a new value to an element specified with its key. If you want to remove a key/value pair, you need to unset() it.

$arr = array(5 => 1, 12 => 2);

$arr[] = 56;    // This is the same as $arr[13] = 56;
                // at this point of the script

$arr["x"] = 42; // This adds a new element to
                // the array with key "x"
                
unset($arr[5]); // This removes the element from the array

unset($arr);    // This deletes the whole array


Useful functions

There are quite some useful function for working with arrays, see the array functions section.

Замечание: The unset() function allows unsetting keys of an array. Be aware that the array will NOT be reindexed. If you only use "usual integer indices" (starting from zero, increasing by one), you can achive the reindex effect by using array_values().

$a = array(1 => 'one', 2 => 'two', 3 => 'three');
unset($a[2]);
/* will produce an array that would have been defined as
   $a = array(1 => 'one', 3 => 'three');
   and NOT
   $a = array(1 => 'one', 2 =>'three');
*/

$b = array_values($a);
// Now b is array(1 => 'one', 2 =>'three')

The foreach control structure exists specifically for arrays. It provides an easy way to traverse an array.


Array do's and don'ts

Why is $foo[bar] wrong?

You should always use quotes around an associative array index. For example, use $foo['bar'] and not $foo[bar]. But why is $foo[bar] wrong? You might have seen the following syntax in old scripts:

$foo[bar] = 'enemy';
echo $foo[bar];
// etc

This is wrong, but it works. Then, why is it wrong? The reason is that this code has an undefined constant (bar) rather than a string ('bar' - notice the quotes), and PHP may in future define constants which, unfortunately for your code, have the same name. It works, because the undefined constant gets converted to a string of the same name automatically for backward compatibility reasons.

As stated in the syntax section, there must be an expression between the square brackets ('[' and ']'). That means that you can write things like this:

echo $arr[foo(true)];

This is an example of using a function return value as the array index. PHP also knows about constants, as you may have seen the E_* ones before.

$error_descriptions[E_ERROR]   = "A fatal error has occured";
$error_descriptions[E_WARNING] = "PHP issued a warning";
$error_descriptions[E_NOTICE]  = "This is just an informal notice";

Note that E_ERROR is also a valid identifier, just like bar in the first example. But the last example is in fact the same as writing:

$error_descriptions[1] = "A fatal error has occured";
$error_descriptions[2] = "PHP issued a warning";
$error_descriptions[8] = "This is just an informal notice";

because E_ERROR equals 1, etc.

Then, how is it possible that $foo[bar] works? It works, because bar is due to its syntax expected to be a constant expression. However, in this case no constant with the name bar exists. PHP now assumes that you meant bar literally, as the string "bar", but that you forgot to write the quotes.


So why is it bad then?

At some point in the future, the PHP team might want to add another constant or keyword, or you may introduce another constant into your application, and then you get in trouble. For example, you already cannot use the words empty and default this way, since they are special reserved keywords.

Замечание: When you turn error_reporting to E_ALL, you will see that PHP generates notices whenever an index is used which is not defined. Consider this script:

<?php

// Turn on the display of all errors
error_reporting(E_ALL);

// Define the test array
$abc = array("x" => "y");

// Access element with the *bad* method
echo $abc[x];

?>

The output is:

<br />
<b>Notice</b>:  Use of undefined constant x - assumed 'x' in <b>/path/to/script.php</b> on
line <b>10</b><br />

Замечание: Inside a double-quoted string, another syntax is valid. See variable parsing in strings for more details.


Converting to array

For any of the types: integer, float, string, boolean and resource, if you convert a value to an array, you get an array with one element (with index 0), which is the scalar value you started with.

If you convert an object to an array, you get the properties (member variables) of that object as the array's elements. The keys are the member variable names.

If you convert a NULL value to an array, you get an empty array.


Examples

The array type in PHP is very versatile, so here will be some examples to show you the full power of arrays.

// this
$a = array( 'color' => 'red',
            'taste' => 'sweet',
            'shape' => 'round',
            'name'  => 'apple',
                       4        // key will be 0
          );

// is completely equivalent with
$a['color'] = 'red';
$a['taste'] = 'sweet';
$a['shape'] = 'round';
$a['name']  = 'apple';
$a[]        = 4;        // key will be 0

$b[] = 'a';
$b[] = 'b';
$b[] = 'c';
// will result in the array array(0 => 'a' , 1 => 'b' , 2 => 'c'),
// or simply array('a', 'b', 'c')

Пример 7-4. Using array()

// Array as (property-)map
$map = array( 'version'    => 4,
              'OS'         => 'Linux',
              'lang'       => 'english',
              'short_tags' => true
            );
            
// strictly numerical keys
$array = array( 7,
                8,
                0,
                156,
                -10
              );
// this is the same as array(0 => 7, 1 => 8, ...)

$switching = array(         10, // key = 0
                    5    =>  6,
                    3    =>  7, 
                    'a'  =>  4,
                            11, // key = 6 (maximum of integer-indices was 5)
                    '8'  =>  2, // key = 8 (integer!)
                    '02' => 77, // key = '02'
                    0    => 12  // the value 10 will be overwritten by 12
                  );
                  
// empty array
$empty = array();

Пример 7-5. Collection

$colors = array('red', 'blue', 'green', 'yellow');

foreach ($colors as $color) {
    echo "Do you like $color?\n";
}

/* output:
Do you like red?
Do you like blue?
Do you like green?
Do you like yellow?
*/

Note that it is currently not possible to change the values of the array directly in such a loop. A workaround is the following:

Пример 7-6. Collection

foreach ($colors as $key => $color) {
    // won't work:
    //$color = strtoupper($color);
    
    // works:
    $colors[$key] = strtoupper($color);
}
print_r($colors);

/* output:
Array
(
    [0] => RED
    [1] => BLUE
    [2] => GREEN
    [3] => YELLOW
)
*/

This example creates a one-based array.

Пример 7-7. One-based index

$firstquarter  = array(1 => 'January', 'February', 'March');
print_r($firstquarter);

/* output:
Array 
(
    [1] => 'January'
    [2] => 'February'
    [3] => 'March'
)
*/

Пример 7-8. Filling an array

// fill an array with all items from a directory
$handle = opendir('.');
while ($file = readdir($handle)) {
    $files[] = $file;
}
closedir($handle);

Arrays are ordered. You can also change the order using various sorting-functions. See the array functions section for more information. You can count the number of items in an array using the count() function.

Пример 7-9. Sorting array

sort($files);
print_r($files);

Because the value of an array can be everything, it can also be another array. This way you can make recursive and multi-dimensional arrays.

Пример 7-10. Recursive and multi-dimensional arrays

$fruits = array ( "fruits"  => array ( "a" => "orange",
                                       "b" => "banana",
                                       "c" => "apple"
                                     ),
                  "numbers" => array ( 1,
                                       2,
                                       3,
                                       4,
                                       5,
                                       6,
                                     ),
                  "holes"   => array (      "first",
                                       5 => "second",
                                            "third"
                                     )
                );

// Some examples to address values in the array above 
echo $fruits["holes"][5];    // prints "second"
echo $fruits["fruits"]["a"]; // prints "orange"
unset($fruits["holes"][0]);  // remove "first"

// Create a new multi-dimensional array
$juices["apple"]["green"] = "good";

You should be aware, that array assignment always involves value copying. You need to use the reference operator to copy an array by reference.

$arr1 = array(2, 3);
$arr2 = $arr1;
$arr2[] = 4; // $arr2 is changed,
             // $arr1 is still array(2,3)
             
$arr3 = &$arr1;
$arr3[] = 4; // now $arr1 and $arr3 are the same


Objects

Object Initialization

To initialize an object, you use the new statement to instantiate the object to a variable.

<?php
class foo
{
    function do_foo()
    {
        echo "Doing foo."; 
    }
}

$bar = new foo;
$bar->do_foo();
?>

For a full discussion, please read the section Classes and Objects.


Converting to object

If an object is converted to an object, it is not modified. If a value of any other type is converted to an object, a new instace of the stdClass built in class is created. If the value was null, the new instance will be empty. For any other value, a member variable named scalar will contain the value.

$obj = (object) 'ciao';
echo $obj->scalar;  // outputs 'ciao'


Resource

A resource is a special variable, holding a reference to an external resource. Resources are created and used by special functions. See the appendix for a listing of all these functions and the corresponding resource types.

Замечание: The resource type was introduced in PHP 4


Converting to resource

As resource types hold special handlers to opened files, database connections, image canvas areas and the like, you cannot convert any value to a resource.


Freeing resources

Due to the reference-counting system introduced with PHP4's Zend-engine, it is automatically detected when a resource is no longer referred to (just like Java). When this is the case, all resources that were in use for this resource are made free by the garbage collector. For this reason, it is rarely ever necessary to free the memory manually by using some free_result function.

Замечание: Persistent database links are special, they are not destroyed by the garbage collector. See also the section about persistent connections.


NULL

The special NULL value represents that a variable has no value. NULL is the only possible value of type NULL.

Замечание: The null type was introduced in PHP 4

A variable is considered to be NULL if

  • it has been assigned the constant NULL.

  • it has not been set to any value yet.

  • it has been unset().


Syntax

There is only one value of type NULL, and that is the case-insensitive keyword NULL.

$var = NULL;

See also is_null() and unset().


Pseudo-types used in this documentation

mixed

mixed indicates that a parameter may accept multiple (but not necesseraly all) types.

gettype() for example will accept all PHP types, while str_replace() will accept strings and arrays.


number

number indicates that a parameter can be either integer or float.


callback

Some functions like call_user_function() or usort() accept user defined callback functions as a parameter. Callback functions can not only be simple functions but also object methods including static class methods.

A PHP function is simply passed by its name as a string. You can pass any builtin or user defined function with the exception of array(), echo(), empty(), eval(), exit(), isset(), list(), print() and unset().

A method of an instantiated object is passed as an array containing an object as the element with index 0 and a method name as the element with index 1.

Static class methods can also be passed without instantiating an object of that class by passing the class name instead of an object as the element with index 0.

Пример 7-11. Callback function examples

<?php 

// simple callback example
function foobar() {
    echo "hello world!";
}
call_user_function("foobar"); 

// method callback examples
class foo {
  function bar() {
    echo "hello world!";
  }
}

$foo = new foo;

call_user_function(array($foo, "bar")); // object method call

call_user_function(array("foo", "bar")); // static class method call

?>


Type Juggling

PHP does not require (or support) explicit type definition in variable declaration; a variable's type is determined by the context in which that variable is used. That is to say, if you assign a string value to variable $var, $var becomes a string. If you then assign an integer value to $var, it becomes an integer.

An example of PHP's automatic type conversion is the addition operator '+'. If any of the operands is a float, then all operands are evaluated as floats, and the result will be a float. Otherwise, the operands will be interpreted as integers, and the result will also be an integer. Note that this does NOT change the types of the operands themselves; the only change is in how the operands are evaluated.

$foo = "0";  // $foo is string (ASCII 48)

$foo += 2;   // $foo is now an integer (2)
$foo = $foo + 1.3;  // $foo is now a float (3.3)
$foo = 5 + "10 Little Piggies"; // $foo is integer (15)
$foo = 5 + "10 Small Pigs";     // $foo is integer (15)

If the last two examples above seem odd, see String conversion to numbers.

If you wish to force a variable to be evaluated as a certain type, see the section on Type casting. If you wish to change the type of a variable, see settype().

If you would like to test any of the examples in this section, you can use the var_dump() function.

Замечание: The behaviour of an automatic conversion to array is currently undefined.

$a = "1";     // $a is a string
$a[0] = "f";  // What about string offsets? What happens?

Since PHP (for historical reasons) supports indexing into strings via offsets using the same syntax as array indexing, the example above leads to a problem: should $a become an array with its first element being "f", or should "f" become the first character of the string $a?

The current versions of PHP interpret the second assignment as a string offset identification, so $a becomes "f", the result of this automatic conversion however should be considered undefined. PHP 4 introduced the new curly bracket syntax to access characters in string, use this syntax instead of the one presented above:

$a    = "abc"; // $a is a string
$a{1} = "f";   // $a is now "afc"

See the section titled String access by character for more informaton.


Type Casting

Type casting in PHP works much as it does in C: the name of the desired type is written in parentheses before the variable which is to be cast.

$foo = 10;   // $foo is an integer
$bar = (boolean) $foo;   // $bar is a boolean

The casts allowed are:

  • (int), (integer) - cast to integer

  • (bool), (boolean) - cast to boolean

  • (float), (double), (real) - cast to float

  • (string) - cast to string

  • (array) - cast to array

  • (object) - cast to object

Note that tabs and spaces are allowed inside the parentheses, so the following are functionally equivalent:

$foo = (int) $bar;
$foo = ( int ) $bar;

Замечание: Instead of casting a variable to string, you can also enclose the variable in double quotes.

$foo = 10;            // $foo is an integer
$str = "$foo";        // $str is a string
$fst = (string) $foo; // $fst is also a string

// This prints out that "they are the same"
if ($fst === $str) {
    echo "they are the same";
}

It may not be obvious exactly what will happen when casting between certain types. For more info, see these sections:


Глава 8. Variables

Basics

Variables in PHP are represented by a dollar sign followed by the name of the variable. The variable name is case-sensitive.

Variable names follow the same rules as other labels in PHP. A valid variable name starts with a letter or underscore, followed by any number of letters, numbers, or underscores. As a regular expression, it would be expressed thus: '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'

Замечание: For our purposes here, a letter is a-z, A-Z, and the ASCII characters from 127 through 255 (0x7f-0xff).

<?php
$var = "Bob";
$Var = "Joe";
echo "$var, $Var";      // outputs "Bob, Joe"

$4site = 'not yet';     // invalid; starts with a number
$_4site = 'not yet';    // valid; starts with an underscore
$tдyte = 'mansikka';    // valid; 'д' is ASCII 228.
?>

In PHP 3, variables are always assigned by value. That is to say, when you assign an expression to a variable, the entire value of the original expression is copied into the destination variable. This means, for instance, that after assigning one variable's value to another, changing one of those variables will have no effect on the other. For more information on this kind of assignment, see the chapter on Expressions.

PHP 4 offers another way to assign values to variables: assign by reference. This means that the new variable simply references (in other words, "becomes an alias for" or "points to") the original variable. Changes to the new variable affect the original, and vice versa. This also means that no copying is performed; thus, the assignment happens more quickly. However, any speedup will likely be noticed only in tight loops or when assigning large arrays or objects.

To assign by reference, simply prepend an ampersand (&) to the beginning of the variable which is being assigned (the source variable). For instance, the following code snippet outputs 'My name is Bob' twice:

<?php
$foo = 'Bob';              // Assign the value 'Bob' to $foo
$bar = &$foo;              // Reference $foo via $bar.
$bar = "My name is $bar";  // Alter $bar...
echo $bar;
echo $foo;                 // $foo is altered too.
?>

One important thing to note is that only named variables may be assigned by reference.

<?php
$foo = 25;
$bar = &$foo;      // This is a valid assignment.
$bar = &(24 * 7);  // Invalid; references an unnamed expression.

function test()
{
   return 25;
}

$bar = &test();    // Invalid.
?>


Predefined variables

PHP provides a large number of predefined variables to any script which it runs. Many of these variables, however, cannot be fully documented as they are dependent upon which server is running, the version and setup of the server, and other factors. Some of these variables will not be available when PHP is run on the command line. For a listing of these variables, please see the section on Reserved Predefined Variables.

Внимание

In PHP 4.2.0 and later, the default value for the PHP directive register_globals is off. This is a major change in PHP. Having register_globals off affects the set of predefined variables available in the global scope. For example, to get DOCUMENT_ROOT you'll use $_SERVER['DOCUMENT_ROOT'] instead of $DOCUMENT_ROOT, or $_GET['id'] from the URL http://www.example.com/test.php?id=3 instead of $id, or $_ENV['HOME'] instead of $HOME.

For related information on this change, read the configuration entry for register_globals, the security chapter on Using Register Globals , as well as the PHP 4.1.0 and 4.2.0 Release Announcements.

Using the available PHP Reserved Predefined Variables, like the superglobal arrays, is preferred.

From version 4.1.0 onward, PHP provides an additional set of predefined arrays containing variables from the web server (if applicable), the environment, and user input. These new arrays are rather special in that they are automatically global--i.e., automatically available in every scope. For this reason, they are often known as 'autoglobals' or 'superglobals'. (There is no mechanism in PHP for user-defined superglobals.) The superglobals are listed below; however, for a listing of their contents and further discussion on PHP predefined variables and their natures, please see the section Reserved Predefined Variables. Also, you'll notice how the older predefined variables ($HTTP_*_VARS) still exist.

Variable variables: Superglobals cannot be used as variable variables.

If certain variables in variables_order are not set, their appropriate PHP predefined arrays are also left empty.

PHP Superglobals

$GLOBALS

Contains a reference to every variable which is currently available within the global scope of the script. The keys of this array are the names of the global variables. $GLOBALS has existed since PHP 3.

$_SERVER

Variables set by the web server or otherwise directly related to the execution environment of the current script. Analogous to the old $HTTP_SERVER_VARS array (which is still available, but deprecated).

$_GET

Variables provided to the script via HTTP GET. Analogous to the old $HTTP_GET_VARS array (which is still available, but deprecated).

$_POST

Variables provided to the script via HTTP POST. Analogous to the old $HTTP_POST_VARS array (which is still available, but deprecated).

$_COOKIE

Variables provided to the script via HTTP cookies. Analogous to the old $HTTP_COOKIE_VARS array (which is still available, but deprecated).

$_FILES

Variables provided to the script via HTTP post file uploads. Analogous to the old $HTTP_POST_FILES array (which is still available, but deprecated). See POST method uploads for more information.

$_ENV

Variables provided to the script via the environment. Analogous to the old $HTTP_ENV_VARS array (which is still available, but deprecated).

$_REQUEST

Variables provided to the script via any user input mechanism, and which therefore cannot be trusted. The presence and order of variable inclusion in this array is defined according to the variables_order configuration directive. This array has no direct analogue in versions of PHP prior to 4.1.0. See also import_request_variables().

Замечание: When running on the command line , this will not include the argv and argc entries; these are present in the $_SERVER array.

$_SESSION

Variables which are currently registered to a script's session. Analogous to the old $HTTP_SESSION_VARS array (which is still available, but deprecated). See the Session handling functions section for more information.


Variable scope

The scope of a variable is the context within which it is defined. For the most part all PHP variables only have a single scope. This single scope spans included and required files as well. For example:

<?php
$a = 1;
include "b.inc";
?>

Here the $a variable will be available within the included b.inc script. However, within user-defined functions a local function scope is introduced. Any variable used inside a function is by default limited to the local function scope. For example:

<?php
$a = 1; /* global scope */ 

function Test()
{ 
    echo $a; /* reference to local scope variable */ 
} 

Test();
?>

This script will not produce any output because the echo statement refers to a local version of the $a variable, and it has not been assigned a value within this scope. You may notice that this is a little bit different from the C language in that global variables in C are automatically available to functions unless specifically overridden by a local definition. This can cause some problems in that people may inadvertently change a global variable. In PHP global variables must be declared global inside a function if they are going to be used in that function. An example:

<?php
$a = 1;
$b = 2;

function Sum()
{
    global $a, $b;

    $b = $a + $b;
} 

Sum();
echo $b;
?>

The above script will output "3". By declaring $a and $b global within the function, all references to either variable will refer to the global version. There is no limit to the number of global variables that can be manipulated by a function.

A second way to access variables from the global scope is to use the special PHP-defined $GLOBALS array. The previous example can be rewritten as:

<?php
$a = 1;
$b = 2;

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

Sum();
echo $b;
?>

The $GLOBALS array is an associative array with the name of the global variable being the key and the contents of that variable being the value of the array element. Notice how $GLOBALS exists in any scope, this is because $GLOBALS is a superglobal. Here's an example demonstrating the power of superglobals:

<?php
function test_global()
{
    // Most predefined variables aren't "super" and require 
    // 'global' to be available to the functions local scope.
    global $HTTP_POST_VARS;
    
    print $HTTP_POST_VARS['name'];
    
    // Superglobals are available in any scope and do 
    // not require 'global'.  Superglobals are available 
    // as of PHP 4.1.0
    print $_POST['name'];
}
?>

Another important feature of variable scoping is the static variable. A static variable exists only in a local function scope, but it does not lose its value when program execution leaves this scope. Consider the following example:

<?php
function Test ()
{
    $a = 0;
    echo $a;
    $a++;
}
?>

This function is quite useless since every time it is called it sets $a to 0 and prints "0". The $a++ which increments the variable serves no purpose since as soon as the function exits the $a variable disappears. To make a useful counting function which will not lose track of the current count, the $a variable is declared static:

<?php
function Test()
{
    static $a = 0;
    echo $a;
    $a++;
}
?>

Now, every time the Test() function is called it will print the value of $a and increment it.

Static variables also provide one way to deal with recursive functions. A recursive function is one which calls itself. Care must be taken when writing a recursive function because it is possible to make it recurse indefinitely. You must make sure you have an adequate way of terminating the recursion. The following simple function recursively counts to 10, using the static variable $count to know when to stop:

<?php
function Test()
{
    static $count = 0;

    $count++;
    echo $count;
    if ($count < 10) {
        Test ();
    }
    $count--;
}
?>

The Zend Engine 1, driving PHP4, implements the static and global modifier for variables in terms of references. For example, a true global variable imported inside a function scope with the global statement actually creates a reference to the global variable. This can lead to unexpected behaviour which the following example addresses:

<?php
function test_global_ref() {
    global $obj;
    $obj = &new stdclass;
}

function test_global_noref() {
    global $obj;
    $obj = new stdclass;
}

test_global_ref();
var_dump($obj);
test_global_noref();
var_dump($obj);
?>

Executing this example will result in the following output:

NULL
object(stdClass)(0) {
}

A similar behaviour applies to the static statement. References are not stored statically:

<?php
function &get_instance_ref() {
    static $obj;

    echo "Static object: ";
    var_dump($obj);
    if (!isset($obj)) {
        // Assign a reference to the static variable
        $obj = &new stdclass;
    }
    $obj->property++;
    return $obj;
}

function &get_instance_noref() {
    static $obj;

    echo "Static object: ";
    var_dump($obj);
    if (!isset($obj)) {
        // Assign the object to the static variable
        $obj = new stdclass;
    }
    $obj->property++;
    return $obj;
}

$obj1 = get_instance_ref();
$still_obj1 = get_instance_ref();
echo "\n";
$obj2 = get_instance_noref();
$still_obj2 = get_instance_noref();
?>

Executing this example will result in the following output:

Static object: NULL
Static object: NULL

Static object: NULL
Static object: object(stdClass)(1) {
  ["property"]=>
  int(1)
}

This example demonstrates that when assigning a reference to a static variable, it's not remembered when you call the &get_instance_ref() function a second time.


Variable variables

Sometimes it is convenient to be able to have variable variable names. That is, a variable name which can be set and used dynamically. A normal variable is set with a statement such as:

<?php
$a = "hello";
?>

A variable variable takes the value of a variable and treats that as the name of a variable. In the above example, hello, can be used as the name of a variable by using two dollar signs. i.e.

<?php
$$a = "world";
?>

At this point two variables have been defined and stored in the PHP symbol tree: $a with contents "hello" and $hello with contents "world". Therefore, this statement:

<?php
echo "$a ${$a}";
?>

produces the exact same output as:

<?php
echo "$a $hello";
?>

i.e. they both produce: hello world.

In order to use variable variables with arrays, you have to resolve an ambiguity problem. That is, if you write $$a[1] then the parser needs to know if you meant to use $a[1] as a variable, or if you wanted $$a as the variable and then the [1] index from that variable. The syntax for resolving this ambiguity is: ${$a[1]} for the first case and ${$a}[1] for the second.

Внимание

Please note that variable variables cannot be used with PHP's Superglobal arrays. This means you cannot do things like ${$_GET}. If you are looking for a way to handle availability of superglobals and the old HTTP_*_VARS, you might want to try referencing them.


Variables from outside PHP

HTML Forms (GET and POST)

When a form is submitted to a PHP script, the information from that form is automatically made available to the script. There are many ways to access this information, for example:

Пример 8-1. A simple HTML form

<form action="foo.php" method="post">
    Name:  <input type="text" name="username"><br>
    Email: <input type="text" name="email"><br>
    <input type="submit" name="submit" value="Submit me!">
</form>

Depending on your particular setup and personal preferences, there are many ways to access data from your HTML forms. Some examples are:

Пример 8-2. Accessing data from a simple POST HTML form

<?php 
// Available since PHP 4.1.0

   print $_POST['username'];
   print $_REQUEST['username'];

   import_request_variables('p', 'p_');
   print $p_username;

// Available since PHP 3.

   print $HTTP_POST_VARS['username'];

// Available if the PHP directive register_globals = on.  As of 
// PHP 4.2.0 the default value of register_globals = off.
// Using/relying on this method is not preferred.

   print $username;
?>

Using a GET form is similar except you'll use the appropriate GET predefined variable instead. GET also applies to the QUERY_STRING (the information after the '?' in an URL). So, for example, http://www.example.com/test.php?id=3 contains GET data which is accessible with $_GET['id']. See also $_REQUEST and import_request_variables().

Замечание: Superglobal arrays, like $_POST and $_GET, became available in PHP 4.1.0

As shown, before PHP 4.2.0 the default value for register_globals was on. And, in PHP 3 it was always on. The PHP community is encouraging all to not rely on this directive as it's preferred to assume it's off and code accordingly.

Замечание: The magic_quotes_gpc configuration directive affects Get, Post and Cookie values. If turned on, value (It's "PHP!") will automagically become (It\'s \"PHP!\"). Escaping is needed for DB insertion. See also addslashes(), stripslashes() and magic_quotes_sybase.

PHP also understands arrays in the context of form variables (see the related faq). You may, for example, group related variables together, or use this feature to retrieve values from a multiple select input. For example, let's post a form to itself and upon submission display the data:

Пример 8-3. More complex form variables

<?php
if ($HTTP_POST_VARS['action'] == 'submitted') {
    print '<pre>';

    print_r($HTTP_POST_VARS);
    print '<a href="'. $HTTP_SERVER_VARS['PHP_SELF'] .'">Please try again</a>';

    print '</pre>';
} else {
?>
<form action="<?php echo $HTTP_SERVER_VARS['PHP_SELF']; ?>" 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>
        <option value="guinness">Guinness</option>
        <option value="stuttgarter">Stuttgarter Schwabenbrдu</option>
    </select><br>
    <input type="hidden" name="action" value="submitted">
    <input type="submit" name="submit" value="submit me!">
</form>
<?php
}
?>

In PHP 3, the array form variable usage is limited to single-dimensional arrays. In PHP 4, no such restriction applies.


IMAGE SUBMIT variable names

When submitting a form, it is possible to use an image instead of the standard submit button with a tag like:

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

When the user clicks somewhere on the image, the accompanying form will be transmitted to the server with two additional variables, sub_x and sub_y. These contain the coordinates of the user click within the image. The experienced may note that the actual variable names sent by the browser contains a period rather than an underscore, but PHP converts the period to an underscore automatically.


HTTP Cookies

PHP transparently supports HTTP cookies as defined by Netscape's Spec. Cookies are a mechanism for storing data in the remote browser and thus tracking or identifying return users. You can set cookies using the setcookie() function. Cookies are part of the HTTP header, so the SetCookie function must be called before any output is sent to the browser. This is the same restriction as for the header() function. Cookie data is then available in the appropriate cookie data arrays, such as $_COOKIE, $HTTP_COOKIE_VARS as well as in $_REQUEST. See the setcookie() manual page for more details and examples.

If you wish to assign multiple values to a single cookie variable, you may assign it as an array. For example:

<?php
  setcookie("MyCookie[foo]", "Testing 1", time()+3600);
  setcookie("MyCookie[bar]", "Testing 2", time()+3600);
?>

That will create two seperate cookies although MyCookie will now be a single array in your script. If you want to set just one cookie with multiple values, consider using serialize() or explode() on the value first.

Note that a cookie will replace a previous cookie by the same name in your browser unless the path or domain is different. So, for a shopping cart application you may want to keep a counter and pass this along. i.e.

Пример 8-4. A setcookie() example

<?php
$count++;
setcookie("count", $count, time()+3600);
setcookie("Cart[$count]", $item, time()+3600);
?>

Dots in incoming variable names

Typically, PHP does not alter the names of variables when they are passed into a script. However, it should be noted that the dot (period, full stop) is not a valid character in a PHP variable name. For the reason, look at it:
<?php
$varname.ext;  /* invalid variable name */
?>
Now, what the parser sees is a variable named $varname, followed by the string concatenation operator, followed by the barestring (i.e. unquoted string which doesn't match any known key or reserved words) 'ext'. Obviously, this doesn't have the intended result.

For this reason, it is important to note that PHP will automatically replace any dots in incoming variable names with underscores.


Determining variable types

Because PHP determines the types of variables and converts them (generally) as needed, it is not always obvious what type a given variable is at any one time. PHP includes several functions which find out what type a variable is, such as: gettype(), is_array(), is_float(), is_int(), is_object(), and is_string(). See also the chapter on Types.


Глава 9. Constants

A constant is an identifier (name) for a simple value. As the name suggests, that value cannot change during the execution of the script (except for magic constants, which aren't actually constants). A constant is case-sensitive by default. By convention, constant identifiers are always uppercase.

The name of a constant follows the same rules as any label in PHP. A valid constant name starts with a letter or underscore, followed by any number of letters, numbers, or underscores. As a regular expression, it would be expressed thusly: [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*

Замечание: For our purposes here, a letter is a-z, A-Z, and the ASCII characters from 127 through 255 (0x7f-0xff).

Like superglobals, the scope of a constant is global. You can access constants anywhere in your script without regard to scope. For more information on scope, read the manual section on variable scope.


Syntax

You can define a constant by using the define()-function. Once a constant is defined, it can never be changed or undefined.

Only scalar data (boolean, integer, float and string) can be contained in constants.

You can get the value of a constant by simply specifying its name. Unlike with variables, you should not prepend a constant with a $. You can also use the function constant() to read a constant's value if you wish to obtain the constant's name dynamically. Use get_defined_constants() to get a list of all defined constants.

Замечание: Constants and (global) variables are in a different namespace. This implies that for example TRUE and $TRUE are generally different.

If you use an undefined constant, PHP assumes that you mean the name of the constant itself. A notice will be issued when this happens. Use the defined()-function if you want to know if a constant is set.

These are the differences between constants and variables:

  • Constants do not have a dollar sign ($) before them;

  • Constants may only be defined using the define() function, not by simple assignment;

  • Constants may be defined and accessed anywhere without regard to variable scoping rules;

  • Constants may not be redefined or undefined once they have been set; and

  • Constants may only evaluate to scalar values.

Пример 9-1. Defining Constants

<?php
define("CONSTANT", "Hello world.");
echo CONSTANT; // outputs "Hello world."
echo Constant; // outputs "Constant" and issues a notice.
?>


Predefined constants

PHP provides a large number of predefined constants to any script which it runs. Many of these constants, however, are created by various extensions, and will only be present when those extensions are available, either via dynamic loading or because they have been compiled in.

There are four magical constants that change depending on where they are used. For example, the value of __LINE__ depends on the line that it's used on in your script. These special constants are case-insensitive and are as follows:

Таблица 9-1. A few "magical" PHP constants

NameDescription
__LINE__ The current line number of the file.
__FILE__ The full path and filename of the file.
__FUNCTION__ The function name. (This was added in PHP 4.3.0.)
__CLASS__ The class name. (This was added in PHP 4.3.0.)

A list of predefined constants is available in the reserved predefined constants section.


Глава 10. Expressions

Expressions are the most important building stones of PHP. In PHP, almost anything you write is an expression. The simplest yet most accurate way to define an expression is "anything that has a value".

The most basic forms of expressions are constants and variables. When you type "$a = 5", you're assigning '5' into $a. '5', obviously, has the value 5, or in other words '5' is an expression with the value of 5 (in this case, '5' is an integer constant).

After this assignment, you'd expect $a's value to be 5 as well, so if you wrote $b = $a, you'd expect it to behave just as if you wrote $b = 5. In other words, $a is an expression with the value of 5 as well. If everything works right, this is exactly what will happen.

Slightly more complex examples for expressions are functions. For instance, consider the following function:

function foo ()
{
    return 5;
}

Assuming you're familiar with the concept of functions (if you're not, take a look at the chapter about functions), you'd assume that typing $c = foo() is essentially just like writing $c = 5, and you're right. Functions are expressions with the value of their return value. Since foo() returns 5, the value of the expression 'foo()' is 5. Usually functions don't just return a static value but compute something.

Of course, values in PHP don't have to be integers, and very often they aren't. PHP supports three scalar value types: integer values, floating point values and string values (scalar values are values that you can't 'break' into smaller pieces, unlike arrays, for instance). PHP also supports two composite (non-scalar) types: arrays and objects. Each of these value types can be assigned into variables or returned from functions.

So far, users of PHP/FI 2 shouldn't feel any change. However, PHP takes expressions much further, in the same way many other languages do. PHP is an expression-oriented language, in the sense that almost everything is an expression. Consider the example we've already dealt with, '$a = 5'. It's easy to see that there are two values involved here, the value of the integer constant '5', and the value of $a which is being updated to 5 as well. But the truth is that there's one additional value involved here, and that's the value of the assignment itself. The assignment itself evaluates to the assigned value, in this case 5. In practice, it means that '$a = 5', regardless of what it does, is an expression with the value 5. Thus, writing something like '$b = ($a = 5)' is like writing '$a = 5; $b = 5;' (a semicolon marks the end of a statement). Since assignments are parsed in a right to left order, you can also write '$b = $a = 5'.

Another good example of expression orientation is pre- and post-increment and decrement. Users of PHP/FI 2 and many other languages may be familiar with the notation of variable++ and variable--. These are increment and decrement operators. In PHP/FI 2, the statement '$a++' has no value (is not an expression), and thus you can't assign it or use it in any way. PHP enhances the increment/decrement capabilities by making these expressions as well, like in C. In PHP, like in C, there are two types of increment - pre-increment and post-increment. Both pre-increment and post-increment essentially increment the variable, and the effect on the variable is idential. The difference is with the value of the increment expression. Pre-increment, which is written '++$variable', evaluates to the incremented value (PHP increments the variable before reading its value, thus the name 'pre-increment'). Post-increment, which is written '$variable++' evaluates to the original value of $variable, before it was incremented (PHP increments the variable after reading its value, thus the name 'post-increment').

A very common type of expressions are comparison expressions. These expressions evaluate to either 0 or 1, meaning FALSE or TRUE (respectively). PHP supports > (bigger than), >= (bigger than or equal to), == (equal), != (not equal), < (smaller than) and <= (smaller than or equal to). These expressions are most commonly used inside conditional execution, such as if statements.

The last example of expressions we'll deal with here is combined operator-assignment expressions. You already know that if you want to increment $a by 1, you can simply write '$a++' or '++$a'. But what if you want to add more than one to it, for instance 3? You could write '$a++' multiple times, but this is obviously not a very efficient or comfortable way. A much more common practice is to write '$a = $a + 3'. '$a + 3' evaluates to the value of $a plus 3, and is assigned back into $a, which results in incrementing $a by 3. In PHP, as in several other languages like C, you can write this in a shorter way, which with time would become clearer and quicker to understand as well. Adding 3 to the current value of $a can be written '$a += 3'. This means exactly "take the value of $a, add 3 to it, and assign it back into $a". In addition to being shorter and clearer, this also results in faster execution. The value of '$a += 3', like the value of a regular assignment, is the assigned value. Notice that it is NOT 3, but the combined value of $a plus 3 (this is the value that's assigned into $a). Any two-place operator can be used in this operator-assignment mode, for example '$a -= 5' (subtract 5 from the value of $a), '$b *= 7' (multiply the value of $b by 7), etc.

There is one more expression that may seem odd if you haven't seen it in other languages, the ternary conditional operator:

$first ? $second : $third

If the value of the first subexpression is TRUE (non-zero), then the second subexpression is evaluated, and that is the result of the conditional expression. Otherwise, the third subexpression is evaluated, and that is the value.

The following example should help you understand pre- and post-increment and expressions in general a bit better:

function double($i)
{
    return $i*2;
}
$b = $a = 5;        /* assign the value five into the variable $a and $b */
$c = $a++;          /* post-increment, assign original value of $a 
                       (5) to $c */
$e = $d = ++$b;     /* pre-increment, assign the incremented value of 
                       $b (6) to $d and $e */

/* at this point, both $d and $e are equal to 6 */

$f = double($d++);  /* assign twice the value of $d <emphasis>before</emphasis> 
                       the increment, 2*6 = 12 to $f */
$g = double(++$e);  /* assign twice the value of $e <emphasis>after</emphasis>
                       the increment, 2*7 = 14 to $g */
$h = $g += 10;      /* first, $g is incremented by 10 and ends with the 
                       value of 24. the value of the assignment (24) is 
                       then assigned into $h, and $h ends with the value 
                       of 24 as well. */

In the beginning of the chapter we said that we'll be describing the various statement types, and as promised, expressions can be statements. However, not every expression is a statement. In this case, a statement has the form of 'expr' ';' that is, an expression followed by a semicolon. In '$b=$a=5;', $a=5 is a valid expression, but it's not a statement by itself. '$b=$a=5;' however is a valid statement.

One last thing worth mentioning is the truth value of expressions. In many events, mainly in conditional execution and loops, you're not interested in the specific value of the expression, but only care about whether it means TRUE or FALSE. The constants TRUE and FALSE (case-insensitive) are the two possible boolean values. When necessary, an expression is automatically converted to boolean. See the section about type-casting for details about how.

PHP provides a full and powerful implementation of expressions, and documenting it entirely goes beyond the scope of this manual. The above examples should give you a good idea about what expressions are and how you can construct useful expressions. Throughout the rest of this manual we'll write expr to indicate any valid PHP expression.


Глава 11. Operators


Operator Precedence

The precedence of an operator specifies how "tightly" it binds two expressions together. For example, in the expression 1 + 5 * 3, the answer is 16 and not 18 because the multiplication ("*") operator has a higher precedence than the addition ("+") operator. Parentheses may be used to force precedence, if necessary. For instance: (1 + 5) * 3 evaluates to 18.

The following table lists the precedence of operators with the lowest-precedence operators listed first.

Таблица 11-1. Operator Precedence

AssociativityOperators
left,
leftor
leftxor
leftand
rightprint
left = += -= *= /= .= %= &= |= ^= <<= >>=
left? :
left||
left&&
left|
left^
left&
non-associative== != === !==
non-associative< <= > >=
left<< >>
left+ - .
left* / %
right! ~ ++ -- (int) (float) (string) (array) (object) @
right[
non-associativenew

Замечание: Although ! has a higher precedence than =, PHP will still allow expressions similar to the following: if (!$a = foo()), in which case the output from foo() is put into $a.


Arithmetic Operators

Remember basic arithmetic from school? These work just like those.

Таблица 11-2. Arithmetic Operators

ExampleNameResult
$a + $bAdditionSum of $a and $b.
$a - $bSubtractionDifference of $a and $b.
$a * $bMultiplicationProduct of $a and $b.
$a / $bDivisionQuotient of $a and $b.
$a % $bModulusRemainder of $a divided by $b.

The division operator ("/") returns a float value anytime, even if the two operands are integers (or strings that get converted to integers).

See also the manual page on Math functions.


Assignment Operators

The basic assignment operator is "=". Your first inclination might be to think of this as "equal to". Don't. It really means that the the left operand gets set to the value of the expression on the rights (that is, "gets set to").

The value of an assignment expression is the value assigned. That is, the value of "$a = 3" is 3. This allows you to do some tricky things:

$a = ($b = 4) + 5; // $a is equal to 9 now, and $b has been set to 4.

In addition to the basic assignment operator, there are "combined operators" for all of the binary arithmetic and string operators that allow you to use a value in an expression and then set its value to the result of that expression. For example:

$a = 3;
$a += 5; // sets $a to 8, as if we had said: $a = $a + 5;
$b = "Hello ";
$b .= "There!"; // sets $b to "Hello There!", just like $b = $b . "There!";

Note that the assignment copies the original variable to the new one (assignment by value), so changes to one will not affect the other. This may also have relevance if you need to copy something like a large array inside a tight loop. PHP 4 supports assignment by reference, using the $var = &$othervar; syntax, but this is not possible in PHP 3. 'Assignment by reference' means that both variables end up pointing at the same data, and nothing is copied anywhere. To learn more about references, please read References explained.


Bitwise Operators

Bitwise operators allow you to turn specific bits within an integer on or off. If both the left- and right-hand parameters are strings, the bitwise operator will operate on the characters in this string.

<?php
    echo 12 ^ 9; // Outputs '5'

    echo "12" ^ "9"; // Outputs the Backspace character (ascii 8)
                     // ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8

    echo "hallo" ^ "hello"; // Outputs the ascii values #0 #4 #0 #0 #0
                            // 'a' ^ 'e' = #4
?>

Таблица 11-3. Bitwise Operators

ExampleNameResult
$a & $bAndBits that are set in both $a and $b are set.
$a | $bOrBits that are set in either $a or $b are set.
$a ^ $bXor Bits that are set in $a or $b but not both are set.
~ $aNot Bits that are set in $a are not set, and vice versa.
$a << $bShift left Shift the bits of $a $b steps to the left (each step means "multiply by two")
$a >> $bShift right Shift the bits of $a $b steps to the right (each step means "divide by two")

Comparison Operators

Comparison operators, as their name implies, allow you to compare two values.

Таблица 11-4. Comparison Operators

ExampleNameResult
$a == $bEqualTRUE if $a is equal to $b.
$a === $bIdentical TRUE if $a is equal to $b, and they are of the same type. (PHP 4 only)
$a != $bNot equalTRUE if $a is not equal to $b.
$a <> $bNot equalTRUE if $a is not equal to $b.
$a !== $bNot identical TRUE if $a is not equal to $b, or they are not of the same type. (PHP 4 only)
$a < $bLess thanTRUE if $a is strictly less than $b.
$a > $bGreater thanTRUE if $a is strictly greater than $b.
$a <= $bLess than or equal to TRUE if $a is less than or equal to $b.
$a >= $bGreater than or equal to TRUE if $a is greater than or equal to $b.

Another conditional operator is the "?:" (or ternary) operator, which operates as in C and many other languages.

<?php
// Example usage for: Ternary Operator
$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];

// The above is identical to this if/else statement
if (empty($_POST['action'])) {
    $action = 'default';
} else {
    $action = $_POST['action'];
}
?>

The expression (expr1) ? (expr2) : (expr3) evaluates to expr2 if expr1 evaluates to TRUE, and expr3 if expr1 evaluates to FALSE.

See also strcasecmp(), strcmp(), and the manual section on Types.


Error Control Operators

PHP supports one error control operator: the at sign (@). When prepended to an expression in PHP, any error messages that might be generated by that expression will be ignored.

If the track_errors feature is enabled, any error message generated by the expression will be saved in the variable $php_errormsg. This variable will be overwritten on each error, so check early if you want to use it.

<?php
/* Intentional file error */
$my_file = @file ('non_existent_file') or
    die ("Failed opening file: error was '$php_errormsg'");

// this works for any expression, not just functions:
$value = @$cache[$key]; 
// will not issue a notice if the index $key doesn't exist.

?>

Замечание: The @-operator works only on expressions. A simple rule of thumb is: if you can take the value of something, you can prepend the @ operator to it. For instance, you can prepend it to variables, function and include() calls, constants, and so forth. You cannot prepend it to function or class definitions, or conditional structures such as if and foreach, and so forth.

See also error_reporting() and the manual section for Error Handling and Logging functions.

Замечание: The "@" error-control operator prefix will not disable messages that are the result of parse errors.

Внимание

Currently the "@" error-control operator prefix will even disable error reporting for critical errors that will terminate script execution. Among other things, this means that if you use "@" to suppress errors from a certain function and either it isn't available or has been mistyped, the script will die right there with no indication as to why.


Execution Operators

PHP supports one execution operator: backticks (``). Note that these are not single-quotes! PHP will attempt to execute the contents of the backticks as a shell command; the output will be returned (i.e., it won't simply be dumped to output; it can be assigned to a variable). Use of the backtick operator is identical to shell_exec().

$output = `ls -al`;
echo "<pre>$output</pre>";

Замечание: The backtick operator is disabled when safe mode is enabled or shell_exec() is disabled.

See also the manual section on Program Execution functions, popen() proc_open(), and Using PHP from the commandline.


Incrementing/Decrementing Operators

PHP supports C-style pre- and post-increment and decrement operators.

Таблица 11-5. Increment/decrement Operators

ExampleNameEffect
++$aPre-incrementIncrements $a by one, then returns $a.
$a++Post-incrementReturns $a, then increments $a by one.
--$aPre-decrementDecrements $a by one, then returns $a.
$a--Post-decrementReturns $a, then decrements $a by one.

Here's a simple example script:

<?php
echo "<h3>Postincrement</h3>";
$a = 5;
echo "Should be 5: " . $a++ . "<br />\n";
echo "Should be 6: " . $a . "<br />\n";

echo "<h3>Preincrement</h3>";
$a = 5;
echo "Should be 6: " . ++$a . "<br />\n";
echo "Should be 6: " . $a . "<br />\n";

echo "<h3>Postdecrement</h3>";
$a = 5;
echo "Should be 5: " . $a-- . "<br />\n";
echo "Should be 4: " . $a . "<br />\n";

echo "<h3>Predecrement</h3>";
$a = 5;
echo "Should be 4: " . --$a . "<br />\n";
echo "Should be 4: " . $a . "<br />\n";
?>

PHP follows Perl's convention when dealing with arithmetic operations on character variables and not C's. For example, in Perl 'Z'+1 turns into 'AA', while in C 'Z'+1 turns into '[' ( ord('Z') == 90, ord('[') == 91 ). Note that character variables can be incremented but not decremented.

Пример 11-1. Arithmetric Operations on Character Variables

<?php
$i = 'W';
for($n=0; $n<6; $n++)
  echo ++$i . "\n";

/*
  Produces the output similar to the following:

X
Y
Z
AA
AB
AC

*/
?>


Logical Operators

Таблица 11-6. Logical Operators

ExampleNameResult
$a and $bAndTRUE if both $a and $b are TRUE.
$a or $bOrTRUE if either $a or $b is TRUE.
$a xor $bXorTRUE if either $a or $b is TRUE, but not both.
! $aNotTRUE if $a is not TRUE.
$a && $bAndTRUE if both $a and $b are TRUE.
$a || $bOrTRUE if either $a or $b is TRUE.

The reason for the two different variations of "and" and "or" operators is that they operate at different precedences. (See Operator Precedence.)


String Operators

There are two string operators. The first is the concatenation operator ('.'), which returns the concatenation of its right and left arguments. The second is the concatenating assignment operator ('.='), which appends the argument on the right side to the argument on the left side. Please read Assignment Operators for more information.

$a = "Hello ";
$b = $a . "World!"; // now $b contains "Hello World!"

$a = "Hello ";
$a .= "World!";     // now $a contains "Hello World!"

See also the manual sections on the String type and String functions.


Array Operators

The only array operator in PHP is the + operator. It appends the right handed array to the left handed, whereas duplicated keys are NOT overwritten.

$a = array("a" => "apple", "b" => "banana");
$b = array("a" =>"pear", "b" => "strawberry", "c" => "cherry");

$c = $a + $b;

var_dump($c);
array(3) {
  ["a"]=>
  string(5) "apple"
  ["b"]=>
  string(6) "banana"
  ["c"]=>
  string(6) "cherry"
}

See also the manual sections on the Array type and Array functions.


Глава 12. Control Structures

Any PHP script is built out of a series of statements. A statement can be an assignment, a function call, a loop, a conditional statement of even a statement that does nothing (an empty statement). Statements usually end with a semicolon. In addition, statements can be grouped into a statement-group by encapsulating a group of statements with curly braces. A statement-group is a statement by itself as well. The various statement types are described in this chapter.


if

The if construct is one of the most important features of many languages, PHP included. It allows for conditional execution of code fragments. PHP features an if structure that is similar to that of C:

if (expr)
    statement

As described in the section about expressions, expr is evaluated to its Boolean value. If expr evaluates to TRUE, PHP will execute statement, and if it evaluates to FALSE - it'll ignore it. More information about what values evaluate to FALSE can be found in the 'Converting to boolean' section.

The following example would display a is bigger than b if $a is bigger than $b:

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

Often you'd want to have more than one statement to be executed conditionally. Of course, there's no need to wrap each statement with an if clause. Instead, you can group several statements into a statement group. For example, this code would display a is bigger than b if $a is bigger than $b, and would then assign the value of $a into $b:

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

If statements can be nested indefinitely within other if statements, which provides you with complete flexibility for conditional execution of the various parts of your program.


else

Often you'd want to execute a statement if a certain condition is met, and a different statement if the condition is not met. This is what else is for. else extends an if statement to execute a statement in case the expression in the if statement evaluates to FALSE. For example, the following code would display a is bigger than b if $a is bigger than $b, and a is NOT bigger than b otherwise:

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

The else statement is only executed if the if expression evaluated to FALSE, and if there were any elseif expressions - only if they evaluated to FALSE as well (see elseif).


elseif

elseif, as its name suggests, is a combination of if and else. Like else, it extends an if statement to execute a different statement in case the original if expression evaluates to FALSE. However, unlike else, it will execute that alternative expression only if the elseif conditional expression evaluates to TRUE. For example, the following code would display a is bigger than b, a equal to b or a is smaller than 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";
}

There may be several elseifs within the same if statement. The first elseif expression (if any) that evaluates to TRUE would be executed. In PHP, you can also write 'else if' (in two words) and the behavior would be identical to the one of 'elseif' (in a single word). The syntactic meaning is slightly different (if you're familiar with C, this is the same behavior) but the bottom line is that both would result in exactly the same behavior.

The elseif statement is only executed if the preceding if expression and any preceding elseif expressions evaluated to FALSE, and the current elseif expression evaluated to TRUE.


Alternative syntax for control structures

PHP offers an alternative syntax for some of its control structures; namely, if, while, for, foreach, and switch. In each case, the basic form of the alternate syntax is to change the opening brace to a colon (:) and the closing brace to endif;, endwhile;, endfor;, endforeach;, or endswitch;, respectively.

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

In the above example, the HTML block "A is equal to 5" is nested within an if statement written in the alternative syntax. The HTML block would be displayed only if $a is equal to 5.

The alternative syntax applies to else and elseif as well. The following is an if structure with elseif and else in the alternative format:

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;

See also while, for, and if for further examples.


while

while loops are the simplest type of loop in PHP. They behave just like their C counterparts. The basic form of a while statement is:

while (expr) statement

The meaning of a while statement is simple. It tells PHP to execute the nested statement(s) repeatedly, as long as the while expression evaluates to TRUE. The value of the expression is checked each time at the beginning of the loop, so even if this value changes during the execution of the nested statement(s), execution will not stop until the end of the iteration (each time PHP runs the statements in the loop is one iteration). Sometimes, if the while expression evaluates to FALSE from the very beginning, the nested statement(s) won't even be run once.

Like with the if statement, you can group multiple statements within the same while loop by surrounding a group of statements with curly braces, or by using the alternate syntax:

while (expr): statement ... endwhile;

The following examples are identical, and both print numbers from 1 to 10:

/* example 1 */

$i = 1;
while ($i <= 10) {
    print $i++;  /* the printed value would be
                    $i before the increment
                    (post-increment) */
}

/* example 2 */

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


do..while

do..while loops are very similar to while loops, except the truth expression is checked at the end of each iteration instead of in the beginning. The main difference from regular while loops is that the first iteration of a do..while loop is guaranteed to run (the truth expression is only checked at the end of the iteration), whereas it's may not necessarily run with a regular while loop (the truth expression is checked at the beginning of each iteration, if it evaluates to FALSE right from the beginning, the loop execution would end immediately).

There is just one syntax for do..while loops:

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

The above loop would run one time exactly, since after the first iteration, when truth expression is checked, it evaluates to FALSE ($i is not bigger than 0) and the loop execution ends.

Advanced C users may be familiar with a different usage of the do..while loop, to allow stopping execution in the middle of code blocks, by encapsulating them with do..while(0), and using the break statement. The following code fragment demonstrates this:

do {
    if ($i < 5) {
        print "i is not big enough";
        break;
    }
    $i *= $factor;
    if ($i < $minimum_limit) {
        break;
    }
    print "i is ok";

     ...process i...

} while(0);

Don't worry if you don't understand this right away or at all. You can code scripts and even powerful scripts without using this 'feature'.


for

for loops are the most complex loops in PHP. They behave like their C counterparts. The syntax of a for loop is:

for (expr1; expr2; expr3) statement

The first expression (expr1) is evaluated (executed) once unconditionally at the beginning of the loop.

In the beginning of each iteration, expr2 is evaluated. If it evaluates to TRUE, the loop continues and the nested statement(s) are executed. If it evaluates to FALSE, the execution of the loop ends.

At the end of each iteration, expr3 is evaluated (executed).

Each of the expressions can be empty. expr2 being empty means the loop should be run indefinitely (PHP implicitly considers it as TRUE, like C). This may not be as useless as you might think, since often you'd want to end the loop using a conditional break statement instead of using the for truth expression.

Consider the following examples. All of them display numbers from 1 to 10:

/* example 1 */

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

/* example 2 */

for ($i = 1;;$i++) {
    if ($i > 10) {
        break;
    }
    print $i;
}

/* example 3 */

$i = 1;
for (;;) {
    if ($i > 10) {
        break;
    }
    print $i;
    $i++;
}

/* example 4 */

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

Of course, the first example appears to be the nicest one (or perhaps the fourth), but you may find that being able to use empty expressions in for loops comes in handy in many occasions.

PHP also supports the alternate "colon syntax" for for loops.

for (expr1; expr2; expr3): statement; ...; endfor;

Other languages have a foreach statement to traverse an array or hash. PHP 3 has no such construct; PHP 4 does (see foreach). In PHP 3, you can combine while with the list() and each() functions to achieve the same effect. See the documentation for these functions for an example.


foreach

PHP 4 (not PHP 3) includes a foreach construct, much like Perl and some other languages. This simply gives an easy way to iterate over arrays. foreach works only on arrays, and will issue an error when you try to use it on a variable with a different data type or an uninitialized variables. There are two syntaxes; the second is a minor but useful extension of the first:

foreach(array_expression as $value) statement
foreach(array_expression as $key => $value) statement

The first form loops over the array given by array_expression. On each loop, the value of the current element is assigned to $value and the internal array pointer is advanced by one (so on the next loop, you'll be looking at the next element).

The second form does the same thing, except that the current element's key will be assigned to the variable $key on each loop.

Замечание: When foreach first starts executing, the internal array pointer is automatically reset to the first element of the array. This means that you do not need to call reset() before a foreach loop.

Замечание: Also note that foreach operates on a copy of the specified array, not the array itself, therefore the array pointer is not modified as with the each() construct and changes to the array element returned are not reflected in the original array. However, the internal pointer of the original array is advanced with the processing of the array. Assuming the foreach loop runs to completion, the array's internal pointer will be at the end of the array.

Замечание: foreach does not support the ability to suppress error messages using '@'.

You may have noticed that the following are functionally identical:

$arr = array("one", "two", "three");
reset ($arr);
while (list(, $value) = each ($arr)) {
    echo "Value: $value<br>\n";
}

foreach ($arr as $value) {
    echo "Value: $value<br>\n";
}

The following are also functionally identical:

reset ($arr);
while (list($key, $value) = each ($arr)) {
    echo "Key: $key; Value: $value<br>\n";
}

foreach ($arr as $key => $value) {
    echo "Key: $key; Value: $value<br>\n";
}

Some more examples to demonstrate usages:

/* foreach example 1: value only */

$a = array (1, 2, 3, 17);

foreach ($a as $v) {
   print "Current value of \$a: $v.\n";
}

/* foreach example 2: value (with key printed for illustration) */

$a = array (1, 2, 3, 17);

$i = 0; /* for illustrative purposes only */

foreach($a as $v) {
    print "\$a[$i] => $v.\n";
    $i++;
}

/* foreach example 3: key and value */

$a = array (
    "one" => 1,
    "two" => 2,
    "three" => 3,
    "seventeen" => 17
);

foreach($a as $k => $v) {
    print "\$a[$k] => $v.\n";
}

/* foreach example 4: multi-dimensional arrays */

$a[0][0] = "a";
$a[0][1] = "b";
$a[1][0] = "y";
$a[1][1] = "z";

foreach($a as $v1) {
    foreach ($v1 as $v2) {
        print "$v2\n";
    }
}

/* foreach example 5: dynamic arrays */

foreach(array(1, 2, 3, 4, 5) as $v) {
    print "$v\n";
}


break

break ends execution of the current for, foreach while, do..while or switch structure.

break accepts an optional numeric argument which tells it how many nested enclosing structures are to be broken out of.

$arr = array ('one', 'two', 'three', 'four', 'stop', 'five');
while (list (, $val) = each ($arr)) {
    if ($val == 'stop') {
        break;    /* You could also write 'break 1;' here. */
    }
    echo "$val<br>\n";
}

/* Using the optional argument. */

$i = 0;
while (++$i) {
    switch ($i) {
    case 5:
        echo "At 5<br>\n";
        break 1;  /* Exit only the switch. */
    case 10:
        echo "At 10; quitting<br>\n";
        break 2;  /* Exit the switch and the while. */
    default:
        break;
    }
}


continue

continue is used within looping structures to skip the rest of the current loop iteration and continue execution at the beginning of the next iteration.

continue accepts an optional numeric argument which tells it how many levels of enclosing loops it should skip to the end of.

while (list ($key, $value) = each ($arr)) {
    if (!($key % 2)) { // skip odd members
        continue;
    }
    do_something_odd ($value);
}

$i = 0;
while ($i++ < 5) {
    echo "Outer<br>\n";
    while (1) {
        echo "&nbsp;&nbsp;Middle<br>\n";
        while (1) {
            echo "&nbsp;&nbsp;Inner<br>\n";
            continue 3;
        }
        echo "This never gets output.<br>\n";
    }
    echo "Neither does this.<br>\n";
}


switch

The switch statement is similar to a series of IF statements on the same expression. In many occasions, you may want to compare the same variable (or expression) with many different values, and execute a different piece of code depending on which value it equals to. This is exactly what the switch statement is for.

The following two examples are two different ways to write the same thing, one using a series of if statements, and the other using the switch statement:

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

switch ($i) {
    case 0:
        print "i equals 0";
        break;
    case 1:
        print "i equals 1";
        break;
    case 2:
        print "i equals 2";
        break;
}

It is important to understand how the switch statement is executed in order to avoid mistakes. The switch statement executes line by line (actually, statement by statement). In the beginning, no code is executed. Only when a case statement is found with a value that matches the value of the switch expression does PHP begin to execute the statements. PHP continues to execute the statements until the end of the switch block, or the first time it sees a break statement. If you don't write a break statement at the end of a case's statement list, PHP will go on executing the statements of the following case. For example:

switch ($i) {
    case 0:
        print "i equals 0";
    case 1:
        print "i equals 1";
    case 2:
        print "i equals 2";
}

Here, if $i is equal to 0, PHP would execute all of the print statements! If $i is equal to 1, PHP would execute the last two print statements. You would get the expected behavior ('i equals 2' would be displayed) only if $i is equal to 2. Thus, it is important not to forget break statements (even though you may want to avoid supplying them on purpose under certain circumstances).

In a switch statement, the condition is evaluated only once and the result is compared to each case statement. In an elseif statement, the condition is evaluated again. If your condition is more complicated than a simple compare and/or is in a tight loop, a switch may be faster.

The statement list for a case can also be empty, which simply passes control into the statement list for the next case.

switch ($i) {
    case 0:
    case 1:
    case 2:
        print "i is less than 3 but not negative";
        break;
    case 3:
        print "i is 3";
}

A special case is the default case. This case matches anything that wasn't matched by the other cases, and should be the last case statement. For example:

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";
}

The case expression may be any expression that evaluates to a simple type, that is, integer or floating-point numbers and strings. Arrays or objects cannot be used here unless they are dereferenced to a simple type.

The alternative syntax for control structures is supported with switches. For more information, see Alternative syntax for control structures .

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";
endswitch;


declare

The declare construct is used to set execution directives for a block of code. The syntax of declare is similar to the syntax of other flow control constructs:

declare (directive) statement

The directive section allows the behavior of the declare block to be set. Currently only one directive is recognized: the ticks directive. (See below for more information on the ticks directive)

The statement part of the declare block will be executed -- how it is executed and what side effects occur during execution may depend on the directive set in the directive block.


Ticks

A tick is an event that occurs for every N low-level statements executed by the parser within the declare block. The value for N is specified using ticks=N within the declare blocks's directive section.

The event(s) that occur on each tick are specified using the register_tick_function(). See the example below for more details. Note that more than one event can occur for each tick.

Пример 12-1. Profile a section of PHP code

<?php
// A function that records the time when it is called
function profile ($dump = FALSE)
{
    static $profile;

    // Return the times stored in profile, then erase it
    if ($dump) {
        $temp = $profile;
        unset ($profile);
        return ($temp);
    }

    $profile[] = microtime ();
}

// Set up a tick handler
register_tick_function("profile");

// Initialize the function before the declare block
profile ();

// Run a block of code, throw a tick every 2nd statement
declare (ticks=2) {
    for ($x = 1; $x < 50; ++$x) {
        echo similar_text (md5($x), md5($x*$x)), "<br />;";
    }
}

// Display the data stored in the profiler
print_r (profile (TRUE));
?>
The example profiles the PHP code within the 'declare' block, recording the time at which every second low-level statement in the block was executed. This information can then be used to find the slow areas within particular segments of code. This process can be performed using other methods: using ticks is more convenient and easier to implement.

Ticks are well suited for debugging, implementing simple multitasking, backgrounded I/O and many other tasks.

See also register_tick_function() and unregister_tick_function().


return

If called from within a function, the return() statement immediately ends execution of the current function, and returns its argument as the value of the function call. return() will also end the execution of an eval() statement or script file.

If called from the global scope, then execution of the current script file is ended. If the current script file was include()ed or require()ed, then control is passed back to the calling file. Furthermore, if the current script file was include()ed, then the value given to return() will be returned as the value of the include() call. If return() is called from within the main script file, then script execution ends. If the current script file was named by the auto_prepend_file or auto_append_file configuration options in php.ini, then that script file's execution is ended.

For more information, see Returning values.

Замечание: Note that since return() is a language construct and not a function, the parentheses surrounding its arguments are not required--in fact, it is more common to leave them out than to use them, although it doesn't matter one way or the other.


require()

The require() statement includes and evaluates the specific file.

require() includes and evaluates a specific file. Detailed information on how this inclusion works is described in the documentation for include().

require() and include() are identical in every way except how they handle failure. include() produces a Warning while require() results in a Fatal Error. In other words, don't hesitate to use require() if you want a missing file to halt processing of the page. include() does not behave this way, the script will continue regardless. Be sure to have an appropriate include_path setting as well.

Пример 12-2. Basic require() examples

<?php

require 'prepend.php';

require $somefile;

require ('somefile.txt');

?>

See the include() documentation for more examples.

Замечание: Prior to PHP 4.0.2, the following applies: require() will always attempt to read the target file, even if the line it's on never executes. The conditional statement won't affect require(). However, if the line on which the require() occurs is not executed, neither will any of the code in the target file be executed. Similarly, looping structures do not affect the behaviour of require(). Although the code contained in the target file is still subject to the loop, the require() itself happens only once.

Внимание

В настоящее время версия PHP для Windows не поддерживает возможность использования удаленных файлов этой функцией даже в том случае, если включена опция allow_url_fopen.

See also include(), require_once(), include_once(), eval(), file(), readfile(), virtual() and include_path.


include()

The include() statement includes and evaluates the specified file.

The documentation below also applies to require(). The two constructs are identical in every way except how they handle failure. include() produces a Warning while require() results in a Fatal Error. In other words, use require() if you want a missing file to halt processing of the page. include() does not behave this way, the script will continue regardless. Be sure to have an appropriate include_path setting as well.

When a file is included, the code it contains inherits the variable scope of the line on which the include occurs. Any variables available at that line in the calling file will be available within the called file, from that point forward.

Пример 12-3. Basic include() example

vars.php
<?php

$color = 'green';
$fruit = 'apple';

?>

test.php
<?php

echo "A $color $fruit"; // A

include 'vars.php';

echo "A $color $fruit"; // A green apple

?>

If the include occurs inside a function within the calling file, then all of the code contained in the called file will behave as though it had been defined inside that function. So, it will follow the variable scope of that function.

Пример 12-4. Including within functions

<?php

function foo()
{
global $color;

    include 'vars.php';

    echo "A $color $fruit";
}

/* vars.php is in the scope of foo() so     *
 * $fruit is NOT available outside of this  *
 * scope.  $color is because we declared it *
 * as global.                               */

foo();                    // A green apple
echo "A $color $fruit";   // A green

?>

When a file is included, parsing drops out of PHP mode and into HTML mode at the beginning of the target file, and resumes again at the end. For this reason, any code inside the target file which should be executed as PHP code must be enclosed within valid PHP start and end tags.

If "URL fopen wrappers" are enabled in PHP (which they are in the default configuration), you can specify the file to be included using an URL (via HTTP or other supported wrapper - see Прил. I for a list of protocols) instead of a local pathname. If the target server interprets the target file as PHP code, variables may be passed to the included file using an URL request string as used with HTTP GET. This is not strictly speaking the same thing as including the file and having it inherit the parent file's variable scope; the script is actually being run on the remote server and the result is then being included into the local script.

Внимание

В настоящее время версия PHP для Windows не поддерживает возможность использования удаленных файлов этой функцией даже в том случае, если включена опция allow_url_fopen.

Пример 12-5. include() through HTTP

<?php

/* This example assumes that www.example.com is configured to parse .php *
 * files and not .txt files. Also, 'Works' here means that the variables *
 * $foo and $bar are available within the included file.                 */

// Won't work; file.txt wasn't handled by www.example.com as PHP
include 'http://www.example.com/file.txt?foo=1&bar=2';

// Won't work; looks for a file named 'file.php?foo=1&bar=2' on the
// local filesystem.
include 'file.php?foo=1&bar=2';

// Works.
include 'http://www.example.com/file.php?foo=1&bar=2';

$foo = 1;
$bar = 2;
include 'file.txt';  // Works.
include 'file.php';  // Works.

?>
See also Remote files, fopen() and file() for related information.

Because include() and require() are special language constructs, you must enclose them within a statement block if it's inside a conditional block.

Пример 12-6. include() and conditional blocks

<?php

// This is WRONG and will not work as desired.
if ($condition)
    include $file;
else
    include $other;


// This is CORRECT.
if ($condition) {
    include $file;
} else {
    include $other;
}

?>

Handling Returns: It is possible to execute a return() statement inside an included file in order to terminate processing in that file and return to the script which called it. Also, it's possible to return values from included files. You can take the value of the include call as you would a normal function.

Замечание: In PHP 3, the return may not appear inside a block unless it's a function block, in which case the return() applies to that function and not the whole file.

Пример 12-7. include() and the return() statement

return.php
<?php

$var = 'PHP';

return $var;

?>

noreturn.php
<?php

$var = 'PHP';

?>

testreturns.php
<?php

$foo = include 'return.php';

echo $foo; // prints 'PHP'

$bar = include 'noreturn.php';

echo $bar; // prints 1

?>

$bar is the value 1 because the include was successful. Notice the difference between the above examples. The first uses return() within the included file while the other does not. A few other ways to "include" files into variables are with fopen(), file() or by using include() along with Output Control Functions.

See also require(), require_once(), include_once(), readfile(), virtual(), and include_path.


require_once()

The require_once() statement includes and evaluates the specified file during the execution of the script. This is a behavior similar to the require() statement, with the only difference being that if the code from a file has already been included, it will not be included again. See the documentation for require() for more information on how this statement works.

require_once() should be used in cases where the same file might be included and evaluated more than once during a particular execution of a script, and you want to be sure that it is included exactly once to avoid problems with function redefinitions, variable value reassignments, etc.

For examples on using require_once() and include_once(), look at the PEAR code included in the latest PHP source code distributions.

Замечание: require_once() was added in PHP 4.0.1pl2

Замечание: Be aware, that the behaviour of require_once() and include_once() may not be what you expect on a non case sensitive operating system (such as Windows).

Пример 12-8. require_once() is case sensitive

require_once("a.php"); // this will include a.php
require_once("A.php"); // this will include a.php again on Windows!

Внимание

В настоящее время версия PHP для Windows не поддерживает возможность использования удаленных файлов этой функцией даже в том случае, если включена опция allow_url_fopen.

See also: require(), include(), include_once(), get_required_files(), get_included_files(), readfile(), and virtual().


include_once()

The include_once() statement includes and evaluates the specified file during the execution of the script. This is a behavior similar to the include() statement, with the only difference being that if the code from a file has already been included, it will not be included again. As the name suggests, it will be included just once.

include_once() should be used in cases where the same file might be included and evaluated more than once during a particular execution of a script, and you want to be sure that it is included exactly once to avoid problems with function redefinitions, variable value reassignments, etc.

For more examples on using require_once() and include_once(), look at the PEAR code included in the latest PHP source code distributions.

Замечание: include_once() was added in PHP 4.0.1pl2

Замечание: Be aware, that the behaviour of include_once() and require_once() may not be what you expect on a non case sensitive operating system (such as Windows).

Пример 12-9. include_once() is case sensitive

include_once("a.php"); // this will include a.php
include_once("A.php"); // this will include a.php again on Windows!