Авторские права © 1997 - 2023 принадлежат группе документирования PHP. Эти материалы могут быть распространены только на условиях и соглашениях, установленных в лицензии Creative Commons Attribution версии 3.0 или более поздней. Копия лицензии Creative Commons Attribution 3.0 распространяется вместе с руководством. Последняя на данный момент версия доступна по адресу » http://creativecommons.org/licenses/by/3.0/.
Если вы заинтересованы в распространении или публикации данного документа полностью или частично, с изменениями или без, и у вас есть вопросы, вы можете связаться с владельцами авторского права по адресу » doc-license@lists.php.net. Помните, что это адрес публичного списка рассылки.
PHP, расшифровывающийся как
"PHP: Hypertext Preprocessor" - «PHP: Препроцессор Гипертекста»,
является распространённым интерпретируемым языком общего назначения
с открытым исходным кодом. PHP создавался специально для ведения
веб-разработок и код на нем может внедряться непосредственно в HTML-код.
Синтаксис языка берет начало из C, Java и Perl, и является лёгким для изучения.
Основной целью PHP является предоставление веб-разработчикам
возможности быстрого создания динамически генерируемых веб-страниц,
однако область применения PHP не ограничивается только этим.
Это руководство состоит, главным образом, из справочника функций, а также содержит справочник языка, комментарии к наиболее важным из отличительных особенностей PHP, и другие дополнительные сведения.
Это руководство доступно в нескольких форматах по адресу » https://www.php.net/download-docs.php. Более подробную информацию о том, как ведётся работа над руководством, вы сможете получить обратившись к приложению Об этом руководстве. Если вам интересна история PHP, обратитесь к соответствующему приложению.
Мы публикуем имена самых активных на данный момент участников разработки документации на первой странице, но есть ещё множество людей, которые помогают нам в процессе разработки или оказали неоценимую помощь в прошлом. Также, есть огромное количество людей, помогающих нам с помощью системы пользовательских замечаний, которые постоянно включаются в основную документацию. Все списки ниже отсортированы в алфавитном порядке.
Следующие участники внесли значительный вклад в наполнение документации в прошлом: Bill Abt, Jouni Ahto, Alexander Aulbach, Stig Bakken, George Peter Banyard, Christoph M. Becker, Daniel Beckham, Nilgün Belma Bugüner, Jesus M. Castagnetto, Ron Chmara, Sean Coates, John Coggeshall, Simone Cortesi, Peter Cowburn, Daniel Egeberg, Markus Fischer, Wez Furlong, Sara Golemon, Rui Hirokawa, Brad House, Pierre-Alain Joye, Etienne Kneuss, Moriyoshi Koizumi, Rasmus Lerdorf, Andrew Lindeman, Stanislav Malyshev, Justin Martin, Rafael Martinez, Rick McGuire, Moacir de Oliveira Miranda Júnior, Kalle Sommer Nielsen, Yasuo Ohgaki, Philip Olson, Richard Quadling, Derick Rethans, Rob Richards, Sander Roobol, Egon Schmid, Thomas Schoefbeck, Sascha Schumann, Dan Scott, Masahiro Takagi, Yoshinari Takaoka, Yannick Torres, Michael Wallner, Lars Torben Wilson, Jim Winstead, Jeroen van Wolffelaar и Andrei Zmievski.
Следующие участники внесли значительный вклад в редактирование и корректирование документации в прошлом: Stig Bakken, Gabor Hojtsy, Hartmut Holzgraefe, Philip Olson и Egon Schmid.
Текущие наиболее активные редакторы: Daniel Brown, Nuno Lopes, Felipe Pena, Thiago Pojda и Maciek Sokolewicz.
Эти люди внесли свой вклад в управление пользовательскими замечаниями в прошлом: Mehdi Achour, Daniel Beckham, Friedhelm Betz, Victor Boivie, Jesus M. Castagnetto, Nicolas Chaillan, Ron Chmara, Sean Coates, James Cox, Vincent Gevers, Sara Golemon, Zak Greant, Szabolcs Heilig, Oliver Hinckel, Hartmut Holzgraefe, Etienne Kneuss, Rasmus Lerdorf, Matthew Li, Andrew Lindeman, Aidan Lister, Hannes Magnusson, Maxim Maletsky, Bobby Matthis, James Moore, Philip Olson, Sebastian Picklum, Derick Rethans, Sander Roobol, Damien Seguy, Jason Sheets, Tom Sommer, Jani Taskinen, Yasuo Ohgaki, Jakub Vrana, Lars Torben Wilson, Jim Winstead, Jared Wyles и Jeroen van Wolffelaar.
Наиболее активные переводчики присылавшие патчи: Spbima, Тигрович, Иван Ремень, Serg, Wolg, Degit, Nooneon, StelZek, Grul, Alexandr Fedotov, Marina Lagun, Mike, HaJIuBauKa, Sunny, dba, Александр Тушин.
Мы публикуем имена самых активных на данный момент переводчиков документации, но есть ещё множество людей, которые помогают нам. И каждый их перевод, поправка или совет ценен и важен.
Переводчики, ранее принимавшие участие в переводе руководства на русский язык (в алфавитном порядке): Alexander Voytsekhovskyy, Alexey Asemov, Andrey Demenev, Antony Dovgal, Boris Bezrukov, Daniil Reuzhkov, Evgeniy Syuzev, Irina Goble, Ivan Kovalenko, Jigkayev Kazbek, Kirill Barashkin, Olishuk Andrey, Veniamin Zolotukhin.
А также неизвестные переводчики со следующими никами: freespace, santiago, shafff, sveta.
PHP (рекурсивный акроним словосочетания
PHP: Hypertext Preprocessor) - это распространённый
язык программирования общего назначения с открытым исходным кодом.
PHP специально сконструирован для веб-разработок и
его код может внедряться непосредственно в HTML.
Простой ответ, но что он может означать? Вот пример кода:
Пример #1 Пример программирования на PHP
<!DOCTYPE html>
<html>
<head>
<title>Пример</title>
</head>
<body>
<?php
echo "Привет, я - скрипт PHP!";
?>
</body>
</html>
Вместо рутинного вывода HTML-кода командами языка
(как это происходит, например, в Perl или C),
скрипт PHP содержит HTML с встроенным кодом (в нашем
случае, это вывод текста "Привет, я - скрипт PHP!").
Код PHP отделяется специальными начальным и конечным тегами
<?php и ?>,
которые позволяют "переключаться" в "PHP-режим" и выходить из него.
PHP отличается от JavaScript тем, что PHP-скрипты выполняются на сервере и генерируют HTML, который посылается клиенту. Если бы у вас на сервере был размещён скрипт, подобный вышеприведённому, клиент получил бы только результат его выполнения, но не смог бы выяснить, какой именно код его произвёл. Вы даже можете настроить свой сервер таким образом, чтобы обычные HTML-файлы обрабатывались процессором PHP, так что клиенты даже не смогут узнать, получают ли они обычный HTML-файл или результат выполнения скрипта.
PHP крайне прост для освоения, но вместе с тем способен удовлетворить запросы профессиональных программистов. Не пугайтесь длинного списка возможностей PHP. Вы можете быстро начать, и уже в течение нескольких часов сможете создавать простые PHP-скрипты.
Хотя PHP, главным образом, предназначен для работы в среде веб-серверов, область его применения не ограничивается только этим. Читайте дальше и не пропустите главу Возможности PHP либо, начните непосредственно с Вводного руководства, если вас интересует исключительно веб-программирование.
PHP может все. Главная область применения PHP - написание скриптов, работающих на стороне сервера; таким образом, PHP способен выполнять все то, что выполняет любая другая программа CGI, например, обрабатывать данные форм, генерировать динамические страницы или отсылать и принимать cookies. Но PHP способен выполнять намного больше.
Существуют три основных области применения PHP.
PHP доступен для большинства операционных систем, включая Linux, многие модификации Unix (такие как HP-UX, Solaris и OpenBSD), Microsoft Windows, macOS, RISC OS и многие другие. Также в PHP включена поддержка большинства современных веб-серверов, таких как Apache, IIS и многих других. В принципе, подойдёт любой веб-сервер, способный использовать бинарный файл FastCGI PHP, например, lighttpd или nginx. PHP может работать в качестве модуля или функционировать в качестве процессора CGI.
Таким образом, выбирая PHP, вы получаете свободу выбора операционной системы и веб-сервера. Более того, у вас появляется выбор между использованием процедурного или объектно-ориентированного программирования (ООП) или же их сочетания.
PHP способен генерировать не только HTML. Доступно формирование изображений, файлов PDF и даже роликов Flash (с использованием libswf и Ming), создаваемых «на лету». PHP также способен генерировать любые текстовые данные, такие, как XHTML и другие XML-файлы. PHP может осуществлять автоматическую генерацию таких файлов и сохранять их в файловой системе вашего сервера вместо того, чтобы отдавать клиенту, организуя, таким образом, серверный кеш для вашего динамического контента.
Одним из значительных преимуществ PHP является поддержка широкого круга баз данных. Создать скрипт, использующий базы данных, - невероятно просто. Можно воспользоваться модулем, специфичным для отдельной базы данных (таким как mysql) или использовать уровень абстракции от базы данных, такой как PDO, или подсоединиться к любой базе данных, поддерживающей Открытый Стандарт Соединения Баз Данных (ODBC), с помощью одноимённого модуля ODBC. Для других баз данных, таких как CouchDB, можно воспользоваться cURL или сокетами.
PHP также поддерживает взаимодействие с другими сервисами через такие протоколы, как LDAP, IMAP, SNMP, NNTP, POP3, HTTP, COM (на платформах Windows) и многих других. Кроме того, вы получаете возможность работать с сетевыми сокетами напрямую. PHP поддерживает стандарт обмена сложными структурами данных WDDX практически между всеми языками веб-программирования. Обращая внимание на взаимодействие между различными языками, следует упомянуть о поддержке объектов Java и возможности их использования в качестве объектов PHP.
PHP имеет много возможностей по обработке текста, включая регулярные выражения Perl (PCRE) и много других модулей и инструментов для обработки и доступа к XML-документам. В PHP обработка XML-документов стандартизирована и происходит на базе мощной библиотеки libxml2, расширив возможности обработки XML добавлением новых модулей SimpleXML, XMLReader и XMLWriter.
Есть ещё много других интересных модулей, которые можно просмотреть как в алфавитном порядке, так и по категориям. Есть ещё много дополнительных модулей PECL, которые также могут (а могут и нет) быть документированы в данном руководстве, такие как » XDebug.
Как вы видите, этой страницы не хватит для того, чтобы перечислить все, что может предложить вам PHP. Читайте следующую главу, Установка PHP и обратитесь к главе Справочник по функциям за более подробными сведениями о перечисленных выше модулях.
В этом кратком и простом учебнике мы бы хотели показать самые основы PHP. Этот текст включает в себя только создание динамических Web-страниц с помощью PHP, однако реальная область применения PHP гораздо шире. В разделе "Что может PHP" приведена дополнительная информация.
Web-страницы, созданные с использованием PHP, обрабатываются как обычные HTML-страницы. Их можно создавать и изменять точно таким же образом, как и обычные страницы на HTML.
В данном руководстве мы предполагаем, что ваш сервер имеет поддержку PHP и что все файлы, заканчивающиеся на .php, обрабатываются PHP. В большинстве серверов обычно используется это расширение для PHP-файлов, но всё-таки не лишним будет уточнить это у вашего администратора сервера. Итак, если ваш сервер поддерживает PHP, то у вас есть все, что требуется. Просто создавайте файлы .php и размещайте их в вашем каталоге Web-сервера - они будут обрабатываться автоматически. Не нужно ничего компилировать, не нужно никаких дополнительных программ. Считайте файлы PHP обычными файлами HTML с набором новых "волшебных" тегов, которые могут делать кучу разных вещей.
Например, вы хотите сэкономить на интернет-канале и вести разработку локально. В этом случае вам нужно будет установить веб-сервер, такой как » Apache, и, разумеется, » PHP. Скорее всего, вы также захотите установить базу данных, например, » MySQL.
Все это может быть установлено как отдельно друг от друга, так и более простым способом. В нашем руководстве есть инструкции по установке PHP (предполагается, что вы уже установили веб-сервер). Если у вас возникли проблемы при установке PHP, мы предлагаем вам задать вопросы в нашем » списке рассылки по вопросам установки. Если же вы выбрали более простой способ, то » найдите уже настроенный пакет для вашей операционной системы, который автоматически установит все вышеперечисленное несколькими кликами мыши. Устанавливать веб-сервер с поддержкой PHP довольно легко на любой операционной системе, включая MacOSX, Linux и Windows. На Linux вам, возможно, пригодятся » rpmfind и » PBone при поиске RPM-пакетов. Можно также использовать » apt-get для поиска пакетов под Debian.
Создайте файл с именем hello.php в корневом каталоге веб-сервера (DOCUMENT_ROOT) и запишите в него следующее:
Пример #1 Первый скрипт на PHP: hello.php
<!DOCTYPE html>
<html>
<head>
<title>Тестируем PHP</title>
</head>
<body>
<?php echo '<p>Привет, мир!</p>'; ?>
</body>
</html>
Откройте данный файл в браузере, набрав имя вашего веб-сервера и
/hello.php. При локальной разработке эта ссылка
может быть чем-то вроде http://localhost/hello.php
или http://127.0.0.1/hello.php, но это зависит от
настроек вашего сервера. Если всё настроено правильно, этот файл
будет обработан PHP и браузер выведет следующий текст:
<!DOCTYPE html>
<html>
<head>
<title>Тестируем PHP</title>
</head>
<body>
<p>Привет, мир!</p>
</body>
</html>
Эта программа чрезвычайно проста, и для создания настолько простой
странички даже необязательно использовать PHP. Все, что она делает,
это вывод Hello World, используя инструкцию
PHP echo. Заметьте, что файл не обязан быть
выполняемым или ещё как-то отличаться от других файлов.
Сервер знает, что этот файл должен быть обработан PHP, так как файл обладает
расширением ".php", о котором в настройках сервера сказано, что подобные
файлы должны передаваться PHP. Рассматривайте его как обычный HTML-файл,
которому посчастливилось заполучить набор специальных тегов (доступных также и вам),
способных на кучу интересных вещей.
Если у вас этот пример не отображает ничего или выводит окно загрузки, или если вы видите весь этот файл в текстовом виде, то, скорее всего, ваш веб-сервер не имеет поддержки PHP или был сконфигурирован неправильно. Попросите вашего администратора сервера включить такую поддержку. Предложите ему инструкцию по установке: раздел Установка данной документации. Если же вы разрабатываете скрипты на PHP дома (локально), то также прочтите эту главу, чтобы убедиться, что вы все настроили верно. Убедитесь также, что вы запрашиваете файл у сервера через протокол http. Если вы просто откроете файл из вашей файловой системы, он не будет обработан PHP. Если проблемы всё же остались, не стесняйтесь попросить помощи одним из » множества доступных способов получения поддержки по PHP.
Цель примера - показать формат специальных тегов PHP. В этом примере
мы использовали <?php в качестве открывающего
тега, затем шли команды PHP, завершающиеся закрывающим тегом
?>. Таким образом можно где угодно "запрыгивать"
и "выпрыгивать" из режима PHP в HTML файле. Подробнее об этом можно прочесть
в разделе руководства
Основной синтаксис.
Замечание: Замечание о переводах строк
Переводы строк немногое означают в HTML, однако считается хорошей идеей поддерживать HTML в удобочитаемом виде, перенося его на новую строку. PHP автоматически удаляет перевод строки, идущий сразу после закрывающего тега
?>. Это может быть чрезвычайно полезно, если вы используете множество блоков PHP-кода или подключаете PHP-файлы, которые не должны ничего выводить. В то же время, это может приводить в недоумение. Можно поставить пробел после закрывающего тега?>и тогда пробел будет выведен вместе с переводом строки, или же вы можете специально добавить перевод строки в последний вызов echo/print из блока PHP-кода.
Замечание: Пара слов о текстовых редакторах
Существует множество текстовых редакторов и интегрированных сред разработки (IDE), в которых вы можете создавать и редактировать файлы PHP. Список некоторых редакторов содержится в разделе » Список редакторов PHP. Если вы хотите порекомендовать какой-либо редактор, посетите данную страницу и попросите добавить редактор в список. Использование редактора с подсветкой синтаксиса может быть очень большим подспорьем в вашей работе.
Замечание: Пара слов о текстовых процессорах
Текстовые процессоры (StarOffice Writer, Microsoft Word, Abiword и др.) в большинстве случаев не подходят для редактирования файлов PHP. Если вы всё же хотите использовать какой-либо из них для тестового скрипта, убедитесь, что сохраняете файл как простой текст (plain text), иначе PHP будет не в состоянии прочесть и запустить ваш скрипт.
Теперь, когда вы успешно создали работающий PHP-скрипт, самое время создать самый знаменитый PHP-скрипт! Вызовите функцию phpinfo() и вы увидите множество полезной информации о вашей системе и настройке, такой как доступные предопределённые переменные, загруженные PHP-модули и параметры настройки. Уделите некоторое время изучению этой важной информации.
Пример #2 Получение информации о системе из PHP
<?php phpinfo(); ?>Давайте сделаем что-нибудь полезное. К примеру, определим, какой браузер использует тот, кто смотрит в данный момент нашу страницу. Для этого мы проверим строку с именем браузера, посылаемую нам в HTTP-запросе. Эта информация хранится в переменной. Переменные в PHP всегда предваряются знаком доллара. Интересующая нас в данный момент переменная называется $_SERVER['HTTP_USER_AGENT'].
Замечание:
$_SERVER - специальная зарезервированная переменная PHP, которая содержит всю информацию, полученную от Web-сервера. Её также называют суперглобальной. Для более подробной информации смотрите раздел Суперглобальные переменные.
Для вывода данной переменной мы сделаем так:
Пример #1 Вывод значения переменной (элемента массива)
<?php
echo $_SERVER['HTTP_USER_AGENT'];
?>Пример вывода данной программы:
Mozilla/5.0 (Linux) Firefox/112.0
В PHP существует огромное количество типов переменных. В предыдущем примере мы печатали элемент массива. Массивы могут быть очень полезны.
$_SERVER - это просто одна из переменных, которые предоставляются вам языком PHP. Список таких переменных можно посмотреть в разделе "Зарезервированные переменные" или просмотрев вывод функции phpinfo(), используемой в примере в предыдущем разделе.
Внутрь PHP-тегов можно помещать несколько выражений и создавать маленькие блоки кода, делающие больше, чем простой вызов echo. Например, если вы хотите добавить проверку для Firefox, можно сделать так:
Пример #2 Пример использования управляющих структур и функций
<?php
if (str_contains($_SERVER['HTTP_USER_AGENT'], 'Firefox')) {
echo 'Вы используете Firefox.';
}
?>Пример вывода данной программы:
Вы используете Firefox.
Здесь мы показали несколько новых элементов. Во-первых, здесь есть конструкция if. Если вы знакомы с основами синтаксиса языка C, то вы уже заметили что-то схожее. Если же вы не знаете C или подобного по синтаксису языка, то лучший вариант - взять какую-либо вводную книжку по PHP и прочитать первые пару глав. Другой вариант - почитать раздел Описание языка данного руководства.
Кроме этого, здесь присутствует вызов функции str_contains().
str_contains() - встроенная в PHP функция, которая определяет,
содержит ли данная строка другую строку. В данном случае мы ищем строку
'Firefox' (так называемую "иголку" - needle)
в $_SERVER['HTTP_USER_AGENT'] (в так называемом "сене"
- haystack). Если "иголка" найдена внутри "сена", функция возвращает
true. В противном случае она возвращает false.
Если она вернёт true, то условие в
if окажется истинным (true), и
код в фигурных скобках ({ }) выполнится. В противном случае этот код
не выполняется. Попробуйте создать аналогичные примеры с использованием
команд if,
else и других функций,
таких, как strtoupper() и strlen().
Также подобные примеры содержатся во многих описаниях функций в данном руководстве.
Если вы не знаете, как использовать функции, возможно, вам стоит
прочесть страницу руководства о том,
как читать определения функций и раздел о
функциях в PHP.
Продемонстрируем, как можно входить в режим кода PHP и выходить из него даже прямо посередине блока с кодом:
Пример #3 Смешение режимов HTML и PHP
<?php
if (str_contains($_SERVER['HTTP_USER_AGENT'], 'Firefox')) {
?>
<h3>str_contains() возвращает true</h3>
<p>Вы используете Firefox</p>
<?php
} else {
?>
<h3>str_contains() возвращает false</h3>
<p>Вы не используете Firefox</p>
<?php
}
?>Пример вывода данной программы:
<h3>str_contains() возвращает true</h3> <p>Вы используете Firefox</p>
Вместо использования команды PHP echo для вывода, мы вышли из режима
кода и просто послали содержимое HTML. Важный момент здесь то, что логическая
структура кода PHP при этом не теряется. Только одна HTML-часть будет
послана клиенту в зависимости от результата функции
str_contains() (другими словами, в зависимости от того,
найдена была строка Firefox или нет).
Одно из главнейших достоинств PHP - то, как он работает с формами HTML. Здесь основным является то, что каждый элемент формы автоматически становится доступным вашим программам на PHP. Для подробной информации об использовании форм в PHP читайте раздел Переменные из внешних источников. Вот пример формы HTML:
Пример #1 Простейшая форма HTML
<form action="action.php" method="post">
<label for="name">Ваше имя:</label>
<input name="name" id="name" type="text">
<label for="age">Ваш возраст:</label>
<input name="age" id="age" type="number">
<button type="submit">Submit</button>
</form>
В этой форме нет ничего особенного. Это обычная форма HTML без каких-либо специальных тегов. Когда пользователь заполнит форму и нажмёт кнопку отправки, будет вызвана страница action.php. В этом файле может быть что-то вроде:
Пример #2 Выводим данные формы
Здравствуйте, <?php echo htmlspecialchars($_POST['name']); ?>.
Вам <?php echo (int)$_POST['age']; ?> лет.Пример вывода данной программы:
Здравствуйте, Сергей. Вам 30 лет.
Если не принимать во внимание куски кода с htmlspecialchars() и
(int), принцип работы данного кода должен быть прост и понятен.
htmlspecialchars() обеспечивает правильную кодировку "особых"
HTML-символов так, чтобы вредоносный HTML или Javascript не был вставлен на вашу
страницу. Поле age, о котором нам известно, что оно должно быть число, мы можем просто
преобразовать в int,
что автоматически избавит нас от нежелательных символов. PHP также может сделать это
автоматически с помощью модуля filter. Переменные
$_POST['name'] и $_POST['age']
автоматически установлены для вас средствами PHP. Ранее мы использовали
суперглобальную переменную $_SERVER, здесь же мы точно так же
используем суперглобальную переменную $_POST, которая содержит
все POST-данные. Заметим, что метод отправки (method) нашей
формы - POST. Если бы мы использовали метод GET, то
информация нашей формы была бы в суперглобальной переменной
$_GET.
Кроме этого, можно использовать переменную $_REQUEST, если
источник данных не имеет значения. Эта переменная содержит смесь данных GET, POST,
COOKIE.
В PHP можно также работать и с XForms, хотя вы найдёте работу с обычными HTML-формами довольно комфортной уже через некоторое время. Несмотря на то, что работа с XForms не для новичков, они могут показаться вам интересными. В разделе возможностей PHP у нас также есть короткое введение в обработку данных из XForms.
То, что вы узнали, поможет вам понять большую часть руководства и разобраться в большинстве приведённых примеров программ.
Если вы хотите посмотреть различные презентации и слайды, шире раскрывающие возможности PHP, вы можете посетить сайт с материалами PHP конференций: » http://talks.php.net/
Перед началом установки вы должны знать, для чего вы хотите использовать PHP. Вы можете использовать PHP для целей, описанных в разделе Что может PHP?
Для первой и наиболее распространённой цели вам нужны три вещи: Сам PHP, веб-сервер и веб-браузер. Вероятно, у вас уже есть веб-браузер и, в зависимости от настроек вашей операционной системы, вы также можете иметь и веб-сервер (например, Apache в Linux и macOS; IIS в Windows). Также вы можете арендовать веб-сервер или некоторое дисковое пространство на веб-сервере. В этом случае вам не нужно устанавливать дополнительное программное обеспечение, только писать PHP-скрипты, загружать их на сервер и просматривать результат их работы в браузере.
В случае установки сервера и PHP самостоятельно у вас есть два варианта установки PHP. Для многих серверов PHP может быть установлен как модуль сервера. Это возможно для таких серверов, как Apache, Microsoft Internet Information Server, Netscape и iPlanet. Если PHP не поддерживает интерфейс для вашего сервера, вы всегда можете использовать его как обработчик CGI или FastCGI. Это означает, что вы должны настроить ваш сервер так, чтобы он исполнял все PHP файлы, как CGI-скрипты.
Если вы также собираетесь использовать PHP в командной строке (для генерации изображений, обработки текстов и т.д.), то вам понадобится PHP CLI. Подробнее об этом можно прочитать в разделе Использование PHP в командной строке. В этом случае вам не понадобятся ни сервер, ни браузер.
Вы также можете создавать приложения с графическим интерфейсом, используя при этом модуль PHP-GTK. Это требует абсолютно другого подхода, чем программирование под Веб, т.к. вы не выводите HTML или текст, а управляете окнами при помощи PHP. Для получения более полной информации о PHP-GTK » посетите сайт, посвящённый этому модулю . PHP-GTK не включён в стандартную поставку PHP.
Начиная с этого момента мы будем описывать установку PHP для веб-серверов на Unix и Windows, как модуля сервера и как CGI. Вы также можете найти информацию об использовании PHP в командной строке в следующих разделах.
Исходные коды и бинарные сборки для Windows можно получить здесь: » https://www.php.net/downloads.php.
Этот раздел описывает установку и настройку PHP на Unix-системах. Пожалуйста, прочитайте все разделы, касающиеся вашей платформы или веб-сервера, прежде чем вы приступите к установке.
Как сказано в разделе Общие указания по установке, в этом разделе в основном мы описываем установку PHP, ориентированную на веб, однако мы также затрагиваем установку PHP для использования в командной строке.
Есть несколько способов установки PHP на Unix платформы. Один из них - процесс конфигурирования и компиляции исходников, другой - установка из пакетов. Этот документ сфокусирован на установке из исходных кодов. Много Unix-подобных систем имеют различные системы установки программ из пакетов. Они могут помочь при установке стандартных конфигураций, но если вам необходимы другие варианты (такие как безопасный сервер или другой драйвер базы данных), вам может потребоваться скомпилировать PHP и/или ваш веб-сервер. Если вы незнакомы с компилированием собственного программного обеспечения, то, может быть, стоит поискать готовый пакет PHP с нужными вам возможностями, собранный кем-нибудь ещё.
Для компиляции PHP из исходных кодов вам потребуется следующее:
При сборке непосредственно из исходников Git или после ручных изменений вам может также понадобиться:
Общая (или начальная) конфигурация PHP задаётся параметрами скрипта configure. Вы можете просмотреть список допустимых параметров вместе с их кратким пояснением при помощи команды ./configure --help. Различные опции документированы в данном руководстве отдельно, список основных параметров можно просмотреть в приложении Основные параметры конфигурации, тогда как параметры, специфичные для различных модулей, описаны на страницах документации, посвящённых этим модулям.
Когда PHP сконфигурирован, все готово к сборке модулей и/или исполняемых файлов. Об этом должна позаботиться команда make. Если что-то не получилось и вы не можете понять почему, смотрите раздел Проблемы установки.
Замечание:
Некоторые Unix системы (такие как OpenBSD и SELinux) могут запрещать, из соображений безопасности, выделение памяти одновременно как записываемой и исполняемой. Это называется PaX MPROTECT или нарушение защиты W^X. Тем не менее, такой режим выделения памяти необходим для поддержки JIT компиляции PCRE JIT, так что в таких случаях необходимо собирать PHP без поддержки JIT компиляции PCRE, либо бинарные файлы должны быть внесены в белый список операционной системы,
Замечание: Кросс-компиляция под ARM с помощью "Android toolchain" на данный момент не поддерживается.
Этот раздел описывает установку PHP c Apache 2.x на Unix системах.
Мы не рекомендуем использовать потоковый MPM в промышленной среде вместе с Apache 2. Вместо этого, используйте prefork MPM, используемый по умолчанию в Apache 2.0 и 2.2. Подробную информацию по этому вопросу вы можете найти в соответствующем разделе FAQ Apache2 и потоковый MPM
Самым авторитетным источником информации по Apache 2.x является » документация Apache. Более подробная информация о настройках при установке может быть найдена там.
Самая последняя версия Apache Http Server может быть получена на » странице загрузки Apache, а адрес соответствующей версии PHP был указан выше. Это краткое руководство описывает лишь базовую установку Apache 2.x и PHP. Для получения более детальной информации прочитайте » документацию Apache. В инструкции ниже опущены номера версий - замените 'NN' на номер, соответствующий скачанной вами версии Apache.
На данный момент есть две версии Apache 2.x - 2.4 и 2.2. Хотя для выбора каждой из них существуют отдельные доводы, 2.4 является наиболее свежей и рекомендуемой версией, если вас устраивает такой выбор. Тем не менее, данные инструкции будут работать как для 2.4, так и для 2.2. Обратите внимание, что Apache httpd 2.2 официально больше не поддерживается, поэтому дальнейшая разработка не будет продолжаться, также как и приниматься новые патчи.
Скачайте Apache HTTP server как было указано выше и распакуйте его:
tar -xzf httpd-2.x.NN.tar.gz
Аналогично, скачайте и распакуйте исходные коды PHP:
tar -xzf php-NN.tar.gz
Скомпилируйте и установите Apache. Более подробную информацию по сборке Apache смотрите в его документации.
cd httpd-2_x_NN ./configure --enable-so make make install
Теперь ваш Apache 2.x.NN доступен как /usr/local/apache2, сконфигурирован с поддержкой подгружаемых модулей и стандартным мульти-процессным модулем (MPM) prefork. Чтобы протестировать правильность установки используйте стандартную процедуру запуска Apache, такую как:
/usr/local/apache2/bin/apachectl start
/usr/local/apache2/bin/apachectl stop
Теперь мы сконфигурируем и соберём PHP. Здесь вы можете настроить установку PHP с помощью различных опций, указывающих, например, какие модули нужно включить. Просмотрите вывод команды ./configure --help для получения полного списка параметров конфигурации. В нашем примере мы сконфигурируем PHP очень просто - с поддержкой Apache и MySQL.
Если вы собирали Apache из исходников, как было описано выше, то используйте путь до apxs как указано в следующем примере, иначе, корректируйте этот путь соответствующим вашей установке образом. Учтите также, что в некоторых дистрибутивах apxs может иметь имя apxs2.
cd ../php-NN ./configure --with-apxs2=/usr/local/apache2/bin/apxs --with-pdo-mysql make make install
Если вы решите изменить параметры конфигурации после установки, вам надо будет повторить только три последних шага (configure, make, make install). Вам нужно будет только перезапустить Apache, чтобы новые модули подгрузились и начали работать. Перекомпиляция Apache для этого не требуется.
Заметьте, что если не указано обратное, то 'make install' установит так же PEAR, различные инструменты PHP - такие как phpize, версию PHP для командной строки (PHP CLI) и т.д.
Настройка вашего php.ini
cp php.ini-development /usr/local/lib/php.ini
Вероятно, вы захотите изменить некоторые настройки в php.ini. Если вы предпочитаете держать файл php.ini в другом месте, используйте параметр --with-config-file-path=/some/path в шаге 5.
Если же вы используете php.ini-production, прочитайте его, чтобы знать какие изменения в поведении PHP это повлечёт.
Отредактируйте ваш httpd.conf, чтобы Apache загружал модуль PHP. Путь в правой части инструкции LoadModule должен указывать на модуль PHP. Команда make install может добавить эту инструкцию автоматически, но этого может и не произойти, поэтому проверьте, чтобы убедиться.
Для PHP 8:
LoadModule php_module modules/libphp.so
Для PHP 7:
LoadModule php7_module modules/libphp7.so
Теперь следует сконфигурировать Apache, чтобы он передавал файлы с некоторыми расширениями на обработку модулю PHP. В нашем примере сделаем это для .php файлов. Вместо обычного использования директивы Apache AddType, мы хотим избежать интерпретации как PHP потенциально опасных загрузок и файлов наподобие exploit.php.jpg. С помощью данного примера можно указать для интерпретации PHP любые расширения, просто добавив их в конец списка. Продемонстрируем это на расширении .php.
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
Или, если мы хотим добавить расширения .php, .php2, .php3, .php4, .php5, .php6 и .phtml, это можно записать так:
<FilesMatch "\.ph(p[2-6]?|tml)$">
SetHandler application/x-httpd-php
</FilesMatch>
Чтобы PHP отображал содержимое файлов .phps с подсветкой синтаксиса, нужно внести соответствующую директиву
<FilesMatch "\.phps$">
SetHandler application/x-httpd-php-source
</FilesMatch>
Можно использовать mod_rewrite для отображения любого .php файла с подсветкой синтаксиса, без нужды его переименования в .phps:
RewriteEngine On RewriteRule (.*\.php)s$ $1 [H=application/x-httpd-php-source]
Данный фильтр, отображающий исходный код, должен быть отключён в промышленном использовании, так как он может открыть конфиденциальную или другую важную информацию, включённую в исходный код.
Используйте стандартную процедуру запуска Apache, например:
/usr/local/apache2/bin/apachectl start
ИЛИ
service httpd restart
Если вы следовали инструкциям выше, то на данном этапе должны иметь запущенный
веб-сервер Apache2 с поддержкой PHP, как модуля SAPI.
Конечно, для PHP и Apache доступно гораздо больше параметров конфигурации.
Используйте ./configure --help в соответствующей папке с
исходными кодами для получения полного списка параметров конфигурации.
Если вы хотите собрать многопоточную версию Apache, то при сборке вам следует указать модуль MPM worker вместо стандартного модуля MPM prefork. Чтобы сделать это, нужно добавить следующий аргумент к ./configure на шаге 3:
--with-mpm=worker
Не следует бездумно использовать эту настройку, используйте её только если вы понимаете все последствия этого решения. Документация Apache по » модулям MPM значительно глубже раскрывает эту тему.
Замечание:
Если вы хотите использовать зависимый контент (content negotiation), прочитайте Apache MultiViews FAQ.
Замечание:
Для сборки многопоточной версии Apache, ваша система должна поддерживать потоки. Это так же подразумевает сборку PHP c поддержкой Zend Thread Safety (ZTS). И, как следствие, не все модули PHP смогут работать. Рекомендуется установка Apache с модулем MPM по умолчанию - prefork.
Данная документация описывает процесс установки и настройки PHP с PHP-FPM для Nginx 1.4.x HTTP сервера.
Данное руководство подразумевает, что вы собрали Nginx из исходников, следовательно,
все бинарные файлы и файлы конфигурации располагаются в
/usr/local/nginx. Если нет, и вы получили Nginx другим способом, тогда,
пожалуйста, обратитесь к » Nginx Wiki, чтобы перевести
данное руководство для вашей установки.
Данное руководство охватывает азы настройки Nginx сервера, для обработки PHP приложений и отображения их на порту 80. Рекомендуется изучить документацию Nginx и PHP-FPM, если вы хотите оптимизировать вашу установку за рамками данной документации.
Пожалуйста, обратите внимание, что во всей данной документации номера версий были заменены на 'x', чтобы данная документация оставалась корректной в будущем. Пожалуйста, замените 'x' на необходимый вам номер версии.
Рекомендуется посетить » страницу установки на Nginx Wiki, для информации о получении и установке Nginx.
Получение и распаковка исходники PHP:
tar zxf php-x.x.x
Настройка и сборка PHP. В этом разделе описывается настройка и сборка PHP из исходных кодов. Запустите ./configure --help для получения списка доступных опций. В нашем примере мы сделаем простые настройки с PHP-FPM и поддержкой MySQLi.
cd ../php-x.x.x ./configure --enable-fpm --with-mysqli make sudo make install
Перемещение файлов настройки в нужные директории
cp php.ini-development /usr/local/php/php.ini cp /usr/local/etc/php-fpm.d/www.conf.default /usr/local/etc/php-fpm.d/www.conf cp sapi/fpm/php-fpm /usr/local/bin
Важно, что мы запрещаем Nginx от отправлять запросы в бэкенд PHP-FPM, если файл не существует, что помогает избежать атаки инъекции скрипта.
Мы может исправить это путём установки директивы
cgi.fix_pathinfo
равной 0 в нашем php.ini файле.
Редактирование php.ini:
vim /usr/local/php/php.ini
Найдите опцию cgi.fix_pathinfo= и измените её следующим образом:
cgi.fix_pathinfo=0
php-fpm.conf должен быть модифицирован, чтобы точно определить, что php-fpm должен работать под пользователем www-data и группой www-data до того, как мы запустим сервис:
vim /usr/local/etc/php-fpm.d/www.conf
Найдите и измените следующее:
; Unix user/group of processes ; Замечание: Пользователь является обязательным. Если группа не установлена, ; то будет использована стандартная группа пользователя. user = www-data group = www-data
Теперь можно запускать сервис php-fpm:
/usr/local/bin/php-fpm
Более в этом руководстве мы не будет касаться настройки php-fpm. Если вам необходимо произвести дополнительные настройки - обратитесь к документации по php-fpm.
Теперь Nginx должен быть настроен на поддержку выполнения PHP:
vim /usr/local/nginx/conf/nginx.conf
Измените блок "location", заданный по умолчанию, так, чтобы можно было обрабатывать .php файлы:
location / {
root html;
index index.php index.html index.htm;
}
Следующий шаг - убедиться, что .php файлы отправляются в бэкенд PHP-FPM. Введите следующее:
location ~* \.php$ {
fastcgi_index index.php;
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
}
Перезапустите Nginx.
sudo /usr/local/nginx/sbin/nginx -s stop sudo /usr/local/nginx/sbin/nginx
Создайте тестовый файл
rm /usr/local/nginx/html/index.html echo "<?php phpinfo(); ?>" >> /usr/local/nginx/html/index.php
Теперь откройте в браузере http://localhost. Должна отобразиться информация phpinfo().
Следуя вышеуказанным шагам, вы получите рабочий Nginx сервер с
поддержкой PHP как модуля FPM SAPI. Конечно, доступно
большое число опций настроек для Nginx и PHP. Для более
подробной информации наберите ./configure --help
в соответствующем дереве исходных кодов.
Этот раздел содержит информацию по установке PHP на Unix-системы с сервером Lighttpd 1.4.
Прочитайте, пожалуйста, инструкции по установке Lighttpd в » документации по Lighttpd перед установкой PHP.
FastCGI - предпочитаемый интерфейс для связи PHP и Lighttpd. FastCGI доступен по умолчанию в php-cgi.
Для настройки Lighttpd на соединение с PHP и порождения процессов FastCGI необходимо отредактировать конфигурационный файл lighttpd.conf. Предпочтительнее подключаться к процессам FastCGI используя Unix-сокеты.
Пример #1 Пример части файла lighttpd.conf
server.modules += ( "mod_fastcgi" )
fastcgi.server = ( ".php" =>
((
"socket" => "/tmp/php.socket",
"bin-path" => "/usr/local/bin/php-cgi",
"bin-environment" => (
"PHP_FCGI_CHILDREN" => "16",
"PHP_FCGI_MAX_REQUESTS" => "10000"
),
"min-procs" => 1,
"max-procs" => 1,
"idle-timeout" => 20
))
)
Директива bin-path позволяет lighttpd динамически запускать процессы FastCGI.
Lighttpd будет динамически создавать дочерние процессы php,
согласно переменной окружения PHP_FCGI_CHILDREN.
Директива bin-environment задаёт настройки для
дочерних процессов. PHP_FCGI_MAX_REQUESTS определяет порог, при достижении
которого PHP завершит дочерний процесс. Директив min-procs и max-procs
обычно стоит избегать. PHP управляет только своими дочерними процессами, и
инструменты кеширования в байт-код (например, APC) будут использоваться
только в этих дочерних процессах.
Если значение min-procs установлено больше 1, общее количество процессов,
обрабатывающих запросы, будет равно PHP_FCGI_CHILDREN * min-procs.
Lighttpd предоставляет программу spawn-fcgi для облегчения управления дочерними процессами FastCGI.
Управлять процессами можно и без spawn-fcgi, но это потребует некоторых доработок. Переменная окружения PHP_FCGI_CHILDREN указывает количество дочерних процессов, запускаемых PHP для обработки входящих запросов. Переменная PHP_FCGI_MAX_REQUESTS отвечает за количество запросов, которые обработает один процесс. Ниже приведён простой bash-скрипт, облегчающий создание дочерних процессов.
Пример #2 Создание FastCGI-обработчиков
#!/bin/sh
# Местоположение бинарного файла php-cgi
PHP=/usr/local/bin/php-cgi
# Местоположение PID-файла
PHP_PID=/tmp/php.pid
# Привязка к адресу
#FCGI_BIND_ADDRESS=10.0.1.1:10000
# Привязка к сокету
FCGI_BIND_ADDRESS=/tmp/php.sock
PHP_FCGI_CHILDREN=16
PHP_FCGI_MAX_REQUESTS=10000
env -i PHP_FCGI_CHILDREN=$PHP_FCGI_CHILDREN \
PHP_FCGI_MAX_REQUESTS=$PHP_FCGI_MAX_REQUESTS \
$PHP -b $FCGI_BIND_ADDRESS &
echo $! > "$PHP_PID"
Обработчики FastCGI могут находиться на нескольких отдельных машинах для масштабирования нагрузки.
Пример #3 Подключение к удалённым процессам fastcgi
fastcgi.server = ( ".php" =>
(( "host" => "10.0.0.2", "port" => 1030 ),
( "host" => "10.0.0.3", "port" => 1030 ))
)
LiteSpeed PHP - это оптимизированная сборка PHP для работы с продуктами LiteSpeed через LiteSpeed SAPI. LSPHP запускается как самостоятельный процесс и имеет отдельный исполняемый файл, который используется как обычный исполняемый файл командной строки для запуска скриптов PHP.
LSAPI - это очень оптимизированный API, позволяющий LiteSpeed взаимодействовать с веб-движками других производителей. Он имеет тот же протокол, что и FCGI, но гораздо более эффективный.
Эта документация содержит инструкции по установке и конфигурированию PHP с LSAPI для веб-серверов LiteSpeed (LSWS) )и OpenLiteSpeed (OLS).
Это руководство предполагает, что LSWS или OLS установлены по стандартным путям и со стандартными флагами. Директория установки по умолчанию для обоих веб-серверов - /usr/local/lsws, и оба они запускаются из её подкаталога bin.
Обратите внимание, что во всей документации номера версий заменены на
x, что говорит о том, что эта документация останется актуальной
и в будущем. Так что смело можете заменить эти символы на номер вашей версии.
Для получения и установки LSWS и OLS посетите сайт с документацией по LiteSpeed Web Server - » инструкции по установке или сайт с документацией по OpenLiteSpeed - » инструкции по установке.
Загрузите и распакуйте исходные коды PHP:
mkdir /home/php cd /home/php wget http://us1.php.net/get/php-x.x.x.tar.gz/from/this/mirror tar -zxvf php-x.x.x.tar.gz cd php-x.x.x
Сконфигурируйте и соберите PHP. На этом этапе можно воспользоваться дополнительными опциями для более тонкой настройки PHP и добавления необходимых модулей. Запустите ./configure --help для получения списка возможных опций. В нижеследующем примере используются стандартные рекомендованные настройки для LSWS:
./configure ... '--with-litespeed' make sudo make install
Проверьте установку LSPHP
Один из самых простых путей для проверки корректности установки PHP - это запустить следующие команды:
cd /usr/local/lsws/fcgi-bin/ ./lsphp5 -v
Должна появиться информация о сборке PHP:
PHP 5.6.17 (litespeed) (built: Mar 22 2016 11:34:19) Copyright (c) 1997-2014 The PHP Group Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies
Обратите внимание на слово litespeed. Это означает, что PHP собран
с поддержкой LSAPI.
После выполнения описанных выше шагов, LSWS/OLS должны запускаться с поддержкой PHP как модуля SAPI. Существует достаточно много дополнительных опций конфигурации для настройки работы LSWS / OLS c PHP. Более подробно почитать о них можно на сайте с документацией по LiteSpeed в разделе » PHP.
Использование LSPHP из командной строки:
Режим командной строки LSPHP(LSAPI + PHP) используется для обработки скриптов PHP запущенных на удалённом сервере без необходимости держать на нем веб-сервер. Это используется для обработки скриптов PHP на локальном веб-сервере (раздельно). Такая установка удобна для удобства масштабирования, так как нагрузка по обработке скриптов ложится на удалённый сервер.
Запустите lsphp из командной строки на удалённом сервере: LSPHP - является исполняемым файлом, может быть запущен вручную и привязан к IPv4, IPv6 или сокету Unix с помощью опции -b socket_address.
Пример:
Привязка LSPHP к порту 3000 на всех интерфейсах IPv4 и IPv6:
/path/to/lsphp -b [::]:3000
Привязка LSPHP к 3000 всех интерфейсов IPv4:
/path/to/lsphp -b *:3000
Привязка LSPHP к 192.168.0.2:3000:
/path/to/lsphp -b 192.168.0.2:3000
Привязка LSPHP к сокету Unix /tmp/lsphp_manual.sock с
возможностью получать из него запросы:
/path/to/lsphp -b /tmp/lsphp_manual.sock
Перед запуском LSPHP можно выставить переменные окружения:
PHP_LSAPI_MAX_REQUESTS=500 PHP_LSAPI_CHILDREN=35 /path/to/lsphp -b IP_address:port
На данный момент LiteSpeed PHP можно использовать с веб-серверами LiteSpeed, OpenLiteSpeed и Apache mod_lsapi. Подробности о конфигурации сервера читайте на страницах » LiteSpeed Web Server и » OpenLiteSpeed.
LSPHP можно установить различными способами.
CentOS: На CentOS, LSPHP может быть установлен из репозиториев LiteSpeed или Remi, используя » RPM.
Debian: На Debian, LSPHP можно поставить из репозитория LiteSpeed, используя » apt.
cPanel: Для установки с cPanel и LSWS/OLS используя EasyApache 4, читайте соответствующую » документацию.
Plesk: Plesk можно использовать с LSPHP на CentOS, CloudLinux, Debian и Ubuntu. Более подробно описано в » документации
По умолчанию, PHP собирается одновременно как CLI и CGI программа, которая может быть использована для обработки CGI-запросов. PHP как модуль сервера выигрывает в производительности, однако PHP CGI позволяет запускать PHP от пользователя, отличного от того, под которым исполняется сервер.
Используя установку CGI, ваш сервер открыт перед несколькими возможными уязвимостями. Пожалуйста, ознакомьтесь с разделом "Безопасность CGI" чтобы узнать, как можно защитить себя от таких атак.
Если вы собрали PHP как CGI, вы можете протестировать вашу сборку командой make test. Тестирование вашей сборки - всегда хорошая идея. Таким образом вы сможете раньше обнаружить проблемы PHP на вашей платформе, вместо того, чтобы бороться с ними позже.
Некоторые переменные окружения сервера не определены в текущей » спецификации CGI/1.1. Определены только следующие переменные: 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 и SERVER_SOFTWARE. Все остальное должно обрабатываться как дополнительные модули (vendor extensions).
Эта секция содержит замечания и советы, касающиеся установки PHP на » OpenBSD.
Использование бинарных пакетов для установки PHP на OpenBSD - это простейший и рекомендованный способ. Ядро (основной пакет) отделено от различных модулей, но каждый из них может быть установлен или удалён независимо от другого. Файлы, которые вам понадобятся, вы можете найти на вашем OpenBSD CD или на FTP.
Основной пакет, который необходимо установить - это php, он содержит базовый движок (плюс fpm, gettext и iconv) и может быть доступен в нескольких версиях на выбор. Далее, обратите внимание на пакеты модулей, такие как php-mysqli или php-imap. Вам следует использовать команду phpxs для активации или деактивации этих модулей в вашем php.ini.
Пример #1 Пример установки пакетов в OpenBSD
# pkg_add php # pkg_add php-apache # pkg_add php-mysqli (install the PEAR libraries) # pkg_add pear Следуйте инструкциям, выводимым пакетами во время установки! (to remove packages) # pkg_delete php # pkg_delete php-apache # pkg_delete php-mysqli # pkg_delete pear
Читайте страницу руководства » packages(7) для большей информации о бинарных пакетах в OpenBSD.
Вы можете также скомпилировать PHP из исходников, используя » дерево портов. Тем не менее, этот способ рекомендован только для тех, кто хорошо знакомых с OpenBSD. Порт PHP разбит на ядро и модули. Модули генерируют подпакеты для всех поддерживаемых модулей PHP. Если какие-либо из них вам не нужны, используйте FLAVOR no_*. Например, для пропуска модуля imap, установите FLAVOR в no_imap.
Данный раздел содержит инструкции и советы для установки PHP на ОС Solaris.
Зачастую в составе операционной системы Solaris отсутствует компиляторы языка C и сопутствующие им утилиты. Ознакомьтесь с этим FAQ, чтобы узнать, почему необходимо использовать GNU-версии этих утилит.
Для распаковки дистрибутива PHP вам понадобится
Для компиляции PHP вам понадобится
Для сборки некоторых модулей или редактирования исходников PHP также могут понадобиться
Вы можете упростить процесс установки в Solaris, используя утилиту pkgadd для установки нужных вам компонент. Система управления пакетами (IPS) операционной системы Solaris 11 Express также позволяет установить большинство требуемых компонент с помощью команды pkg.
Раздел содержит информацию и подсказки, относящиеся к установке PHP на » Debian GNU/Linux.
Неофициальные сборки от третьих лиц не поддерживаются. О любых ошибках следует сообщать разработчикам Debian, но перед этим стоит проверить, возможно они уже исправлены в новых релизах, которые можно скачать на » странице загрузки.
Хотя и существует универсальная инструкция по установке PHP на Unix/Linux,
в этом разделе мы рассмотрим особенности специфичные для Debian,
такие как использование команд apt или aptitude.
В рамках этого руководства обе эти команды рассматриваются как взаимозаменяемые.
Во первых, обратите внимание на то, что некоторые пакеты связаны:
libapache-mod-php нужен для интеграции с Apache 2, и
php-pear с PEAR.
Во-вторых, перед установкой убедитесь, что список пакетов находится в актуальном состоянии. Как правило, это делается с помощью команды apt update.
Пример #1 Пример установки Apache 2 на Debian
# apt install php-common libapache2-mod-php php-cli
APT автоматически установит модуль PHP для Apache 2 и все их зависимости и, затем, активирует их. Apache должен быть перезапущен для того, чтобы изменения вступили в силу. Например:
Пример #2 Остановка и запуск Apache после установки PHP
# /etc/init.d/apache2 stop # /etc/init.d/apache2 start
Изначально, PHP устанавливается только с основными модулями ядра.
Если вы хотите установить дополнительные модули, такие как
MySQL,
cURL,
GD и т.д., это также можно сделать с помощью
команды apt.
Пример #3 Способы получить список дополнительных пакетов PHP
# apt-cache search php # apt search php | grep -i mysql # aptitude search php
Будет выведен список большого числа пакетов, включая несколько
специфичных, таких как php-cgi, php-cli and php-dev. Определите, какие вам нужны
и установите с помощью apt-get или aptitude.
И, так как Debian производит проверку зависимостей, вам будет выведен запрос
на их установку.
Пример #4 Установка PHP с MySQL и cURL
# apt install php-mysql php-curl
APT автоматически добавит необходимые строки в соответствующие
php.ini, /etc/php/7.4/php.ini,
/etc/php/7.4/conf.d/*.ini, и т.д. В зависимости от модуля, будут
внесены записи типа extension=foo.so.
В любом случае, чтобы эти изменения вступили в силу, необходимо будет перезапустить
сервер веб-сервер.
apt и aptitude.
Объяснения их синтаксиса, особенностей и отличий друг от друга выходит за
рамки данного руководства.
Этот раздел содержит руководство и различные советы по установке PHP на macOS. PHP поставлялся вместе с macOS, начиная с macOS X (10.0.0) по macOS Monterey (12.0.0). Компилирование на которых схоже с установкой в Unix-системах.
Существуют несколько предварительно упакованных и предварительно скомпилированных версий PHP для macOS. Это может помочь в создании стандартных конфигураций, но если вам нужны специфические функции (например, безопасный сервер, или другой драйвер базы данных), вы можете установить PHP и/или веб-сервер самостоятельно. Если вы не знакомы с процессом сборки и компиляции программного обеспечения, стоит проверить, может кто-то уже собрал версию PHP с функциями, которые вам необходимы.
Самый быстрый способ установить PHP на macOS - с помощью homebrew:
Установите homebrew, следуя инструкциям на » brew.sh
Следующие альтернативные ресурсы также предлагают простые в установке пакеты и предварительно скомпилированные двоичные файлы для PHP в Mac OS:
PHP поставлялся вместе с macOS, начиная с macOS X (10.0.0) по macOS Monterey (12.0.0). Включение PHP в стандартный веб-сервер делается простым раскомментированием нескольких строк в конфигурационном файле Apache httpd.conf в то время как CGI и/или CLI включены по умолчанию (доступны для использования терминальными программами).
Включение PHP согласно приведённой ниже инструкции предназначено для быстрой настройки локальной среды разработки. Крайне рекомендуется всегда обновлять PHP до новейшей стабильной версии. Для любого развивающегося ПО, новые версии выпускаются для исправления ошибок и добавления новой функциональности и PHP не является исключением. Читайте соответствующую документацию по установке на macOS, в которой описываются все подробности. Следующие инструкции предназначены для начинающих разработчиков и описывают стандартную установку, позволяющую быстро приступить к работе. Всем пользователям рекомендуется скомпилировать или установить из репозитория самую новую версию PHP.
Стандартная установка с использованием mod_php, который включается для стандартного веб-сервера macOS (сервер по умолчанию доступен через системные настройки) включает следующие шаги:
Finder или Spotlight для
нахождения файла может быть не простым, так как он располагается
в приватном пространстве и принадлежит пользователю root.
Замечание: Один из вариантов, как открыть этот файл - использовать консольный редактор, к примеру,
nano, запустив его через терминал. Так как файл принадлежит пользователюroot, для его открытия будет необходимо использовать командуsudo(которая повышает привилегии до пользователяroot). Просто запустите приложениеTerminal, введите командуsudo nano /private/etc/apache2/httpd.confи, когда будет запрошен пароль, введите его. Полезные команды nano:^w(искать),^o(сохранить) и^x(закрыть), где^- это клавиша Ctrl.
Замечание: Версии macOS до 10.5 содержат устаревшие версии PHP и Apache. В этом случае конфигурационный файл может располагаться по пути /etc/httpd/httpd.conf.
В текстовом редакторе найдите следующие строки и раскомментируйте их удалив символ # из начала строки (эти строки обычно находятся в разных местах файла):
# LoadModule php5_module libexec/httpd/libphp5.so # AddModule mod_php5.c
Убедитесь, что выбранные модули будут обрабатываться как файлы PHP (.php .html и .inc).
Так как следующие выражения уже содержатся в httpd.conf (по состоянию на Mac Panther), единожды включив PHP, файлы .php будут автоматически обрабатываться им.
<IfModule mod_php5.c>
# Если PHP разрешён, он будет обрабатывать файлы .php и .phps.
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps
# Часто требуется, чтобы index.php рассматривался как
# страница по умолчанию, если она прямо не указана.
# Сделать это можно следующим образом
<IfModule mod_dir.c>
DirectoryIndex index.html index.php
</IfModule>
</IfModule>
Замечание:
До macOS 10.5 (Leopard), в состав ОС был включён PHP 4, а не PHP 5. В таком случае в инструкциях выше просто поменяйте 5 на 4.
DocumentRoot
DocumentRoot - это корневая директория веб-сервера, в которой лежат
скрипты сайта. Обычно, путь по умолчанию, он равен
/Library/WebServer/Documents, но его можно изменить
на любой другой в httpd.conf. Также, для индивидуальных
пользователей, DocumentRoot может быть установлен как
/Users/yourusername/Sites
Функция phpinfo() отображает информацию о PHP. Создайте в DocumentRoot скрипт с таким кодом:
<?php phpinfo(); ?>
Для перезапуска выполните sudo apachectl graceful в терминале
или выполните stop/start для "Personal Web Server" в системных настройках
macOS. По умолчанию, локальные файлы можно загрузить введя в строке браузера
URL, например, так:
http://localhost/info.php, или используя DocumentRoot
в локальной директории пользователя, таким образом:
http://localhost/~yourusername/info.php
CLI (или в более старых версиях CGI) именуется как
php и содержится в /usr/bin/php.
Откройте терминал, прочитайте раздел документации PHP
командная строка, и запустите
php -v для проверки установленной версии PHP.
Вызов функции phpinfo() также покажет эту информацию.
Установка PHP в современных операционных системах Microsoft Windows и рекомендуемая конфигурация под распространённые веб-серверы.
Официальные релизы PHP для Windows рекомендованы для использования в промышленной эксплуатации. Однако, вы также можете собрать PHP из исходных кодов. Вам потребуется окружение Visual Studio. Обратитесь к разделу » Пошаговое руководство по сборке для получения более полной информации.
Установка PHP на Azure App Services (он же Microsoft Azure, Windows Azure, или (Windows) Azure Web Apps).
Для PHP требуется как минимум Windows 2008/Vista. 32-Bit или 64-bit (AKA X86 или X64. PHP не работает на Windows RT/WOA/ARM). Начиная с PHP 7.2.0, Windows 2008 и Vista больше не поддерживаются.
PHP требует наличия Visual C runtime(CRT). Многие приложения требуют, чтобы это уже было установлено.
Распространяемый Microsoft Visual C ++ для Visual Studio 2019 подходит для всех этих версий PHP, смотрите » https://visualstudio.microsoft.com/downloads/.
Вы должны скачать x86 CRT для сборки PHP x86 и x64 CRT для сборки PHP x64.
Если CRT уже установлен, установщик скажет вам об этом и ничего не будет устанавливать.
Инсталятор CRT поддерживает опции командной строки /quiet и /norestart, вы можете использовать их при запуске скрипта.
PECL модули для Windows предварительно скомпилированы и доступны по ссылке: » http://windows.php.net/downloads/pecl/releases/
Некоторые модули используют особенности, специфичные для Unix систем и не доступны для Windows. Или напротив модули могут быть доступны только для Windows.
» XAMPP, WampServer и BitNami установят PHP с использованием в качестве веб-сервера Apache под Windows.
Установка и настройка Nginx на Windows потребует немного больше конфигурации. Смотрите » документацию по Nginx для получения помощи по установке.
Крайне рекомендуется использовать OpCache. Этот модуль идёт в составе дистрибутива для Windows. Модуль компилирует PHP-скрипт, оптимизирует его и кеширует в памяти , что позволяет не тратить время и ресурсы сервера на компиляцию скрипта при каждом запросе к нему.
Установите в вашем php.ini следующие опции
Пример #1 Рекомендованная конфигурация OpCache
opcache.enable=On opcache.enable_cli=On
Если вы используете IIS, то рекомендуется вместе с ним использовать WinCache, особенно если используется виртуальный хостинг или сетевое хранилище (NAS). Все приложения PHP будут автоматически получать преимущества WinCache. Файловые операции будут кешироваться в памяти. Также WinCache может кешировать в памяти пользовательский объекты и разделять их между разными процессами php.exe или php-cgi.exe (разделение объектом между запросами). Многие веб-приложения имеют плагин, модуль или опции настройки, позволяющие использовать кеширование пользовательских объектов с помощью WinCache. Если вам нужна высокая производительность, вам придётся кешировать объекты в своём приложении. Загрузить WinCache можно по ссылке » http://pecl.php.net/package/WinCache. После загрузки будет нужно сохранить WinCache DLL в директорию модулей PHP (extensions_dir в вашем php.ini). Установите в вашем php.ini следующие опции:
Пример #2 Рекомендованная конфигурация WinCache
extension=php_wincache.dll wincache.fcenabled=1 wincache.ocenabled=1 ; удалено в wincache 2.0.0.0
В IIS Manager установите модуль FastCGI и добавьте обработку `.php` файлом PHP-CGI.exe (не PHP.exe)
Вы можете использовать приложение APPCMD из командной строки для автоматизации настройки ISS.
Наверное вам понадобится сервер баз данных. Для всех популярных баз данных существуют модули PHP. Если ваш сайт не рассчитывается под высокую нагрузку, то сервер баз данных можно держать на том же хосте, что и веб-сервер. Под Windows доступно множество различных баз данных.
PHP модули включают mysqli и pdo_mysql.
Дополнительно читайте » https://dev.mysql.com/downloads/windows/
IIS является встроенным в Windows. На сервере Windows используйте Server Manager для добавления роли IIS. Убедитесь, что функция роли CGI включена. На рабочем столе Windows используйте панель "Установка и удаление программ" для добавления IIS. В документации Microsoft есть » подробные инструкции. Для настольных веб-приложений и веб-разработки можно также использовать IIS/Express или рабочий стол PHP.
Пример #1 Командная строка для настройки IIS и PHP
@echo off REM download .ZIP file of PHP build from http://windows.php.net/downloads/ REM path to directory you decompressed PHP .ZIP file into (no trailing \) set phppath=c:\php REM Clear current PHP handlers %windir%\system32\inetsrv\appcmd clear config /section:system.webServer/fastCGI REM The following command will generate an error message if PHP is not installed. This can be ignored. %windir%\system32\inetsrv\appcmd set config /section:system.webServer/handlers /-[name='PHP_via_FastCGI'] REM Set up the PHP handler %windir%\system32\inetsrv\appcmd set config /section:system.webServer/fastCGI /+[fullPath='%phppath%\php-cgi.exe'] %windir%\system32\inetsrv\appcmd set config /section:system.webServer/handlers /+[name='PHP_via_FastCGI',path='*.php',verb='*',modules='FastCgiModule',scriptProcessor='%phppath%\php-cgi.exe',resourceType='Unspecified'] %windir%\system32\inetsrv\appcmd set config /section:system.webServer/handlers /accessPolicy:Read,Script REM Configure FastCGI Variables %windir%\system32\inetsrv\appcmd set config -section:system.webServer/fastCgi /[fullPath='%phppath%\php-cgi.exe'].instanceMaxRequests:10000 %windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/fastCgi /+"[fullPath='%phppath%\php-cgi.exe'].environmentVariables.[name='PHP_FCGI_MAX_REQUESTS',value='10000']" %windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/fastCgi /+"[fullPath='%phppath%\php-cgi.exe'].environmentVariables.[name='PHPRC',value='%phppath%\php.ini']"
Существует несколько версий Apache2 для Windows. Мы поддерживаем ApacheLounge, но другие варианты включают XAMPP, WampServer и BitNami, которые предоставляют средства автоматической установки. Вы можете использовать mod_php или mod_fastcgi для загрузки PHP на Apache. Если вы используете mod_php, необходимо использовать TS-build Apache, Visual C той же версии и тот же процессор (x86 или x64).
Скачайте PHP-релизы с » http://windows.php.net/download/. Все сборки оптимизированы (PGO), а выпуски QA и GA тщательно протестированы.
Есть 4 типа сборок PHP:
Thread-Safe(TS) - для одного процесса веб-служб, как Apache с mod_php
Non-Thread-Safe(NTS) - для служб IIS и других FastCGI веб-серверов (Apache с mod_fastcgi) рекомендуется и для сценариев командной строки
для x86 - для 32-разрядной версии
для x64 - для 64-разрядной версии
В этой главе рассказывается, как скомпилировать PHP из исходных кодов в Windows с помощью инструментов Microsoft. Чтобы скомпилировать PHP с помощью cygwin, обратитесь к Установка на Unix-системы.
Смотрите Wiki-документацию по адресу: » https://wiki.php.net/internals/windows/stepbystepbuild
Этот раздел содержит примечания и подсказки, относящиеся к запуску PHP из командной строки для Windows.
Замечание:
Сначала следует прочитать шаги ручной установки!
Запуск PHP из командной строки можно выполнить без внесения каких-либо изменений в Windows.
C:\php\php.exe -f "C:\PHP Scripts\script.php" -- -arg1 -arg2 -arg3
Но есть несколько шагов, которые помогут упростить этот процесс. Некоторые из этих шагов уже должны были быть предприняты, но они повторяются здесь, чтобы иметь возможность предоставить полную пошаговую последовательность.
Замечание:
И PATH, и PATHEXT являются важными переменными, изначально существовавшими в Windows, и следует позаботиться о том, чтобы не перезаписывать ни одну из переменных, а только добавлять к ним.
Добавьте расположение исполняемого файла PHP (php.exe, php-win.exe или php-cli.exe в зависимости от вашей версии PHP и предпочтений отображения) в переменную окружения PATH. Подробнее о том, как добавить каталог PHP в PATH, читайте в соответствующей записи часто задаваемых вопросов.
Добавьте расширение .PHP к переменной окружения
PATHEXT. Это можно сделать одновременно с изменением
переменной окружения PATH. Выполните те же действия, что и в
ЧАВО, но измените
переменную окружения PATHEXT, а не PATH.
Замечание:
Позиция, в которую вы помещаете
.PHP, будет определять, какой скрипт или программа будет выполняться при совпадении имён файлов. Например, размещение.PHPперед.BATприведёт к запуску вашего скрипта, а не пакетного файла, если существует пакетный файл с тем же именем.
Свяжите расширение .PHP с типом файла. Это делается с
помощью следующей команды:
assoc .php=phpfile
Свяжите тип файла phpfile с соответствующим исполняемым
файлом PHP. Это делается с помощью следующей команды:
ftype phpfile="C:\php\php.exe" -f "%1" -- %~2
Выполнение этих шагов позволит запускать скрипты PHP из любого каталога без
необходимости вводить исполняемый файл PHP или расширение
.PHP, и все параметры будут переданы скрипту для обработки.
В приведённом ниже примере описаны подробности о некоторых изменениях в реестре, которые можно сделать вручную.
Пример #1 Изменения в реестре
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.php] @="phpfile" "Content Type"="application/php" [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\phpfile] @="PHP Script" "EditFlags"=dword:00000000 "BrowserFlags"=dword:00000008 "AlwaysShowExt"="" [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\phpfile\DefaultIcon] @="C:\\php\\php-win.exe,0" [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\phpfile\shell] @="Open" [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\phpfile\shell\Open] @="&Open" [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\phpfile\shell\Open\command] @="\"C:\\php\\php.exe\" -f \"%1\" -- %~2"
С этими изменениями эту же команду можно записать как:
"C:\PHP Scripts\script" -arg1 -arg2 -arg3
"C:\PHP Scripts" находится в переменной
окружения PATH:
script -arg1 -arg2 -arg3
Замечание:
Есть небольшая проблема, если вы собираетесь использовать эту технику и использовать свои скрипты PHP в качестве фильтра командной строки, как в примере ниже:
илиdir | "C:\PHP Scripts\script" -arg1 -arg2 -arg3Вы можете обнаружить, что сценарий просто зависает и ничего не выводится. Чтобы это заработало, необходимо внести ещё одно изменение в реестр.dir | script -arg1 -arg2 -arg3Дополнительную информацию по этой проблеме можно найти в этой » статье базы знаний Microsoft : 321788. В Windows 10 этот параметр изменён на противоположный, и стандартная установка Windows 10 поддерживает унаследованные дескрипторы консоли. Это » сообщение на форуме Microsoft предоставляет объяснение.Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\Explorer] "InheritConsoleHandles"=dword:00000001
Этот раздел содержит примечания и подсказки к установке PHP, связанной с Apache 2.x на системах Microsoft Windows.
Замечание:
Сначала следует прочитать шаги ручной установки!
Крайне рекомендуется обратиться к » Документации Apache, чтобы получить базовое представление о сервере Apache 2.x. Также подумайте о чтении » Примечаний для Windows для Apache 2.x перед чтением этого руководства.
Загрузите последнюю версию » Apache 2.x и подходящую версию PHP. Следуйте шагам ручной установки и возвращайтесь, чтобы продолжить интеграцию PHP и Apache.
Существует три способа настроить PHP для работы с Apache 2.x в Windows. PHP можно запускать как обработчик, как CGI или под FastCGI.
Замечание: Помните, что при указании путей в конфигурационных файлах Apache под Windows, все обратные слеши, например, c:\directory\file.ext должны быть изменены на прямые: c:/directory/file.ext. Для путей с директориями также может понадобиться слеш в конце.
Чтобы загрузить модуль PHP для Apache 2.x, необходимо вставить следующие строки в файл конфигурации Apache httpd.conf:
Пример #1 PHP и Apache 2.x в качестве обработчика
# до PHP 8.0.0 имя модуля было php7_module
LoadModule php_module "c:/php/php8apache2_4.dll"
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
# укажите путь до php.ini
PHPIniDir "C:/php"
Замечание: В приведённых выше примерах необходимо подставить фактический путь к PHP вместо C:/php/. Убедитесь, что файл, указанный в директиве
LoadModule, находился в указанном месте. Используйте php7apache2_4.dll для PHP 7 или php8apache2_4.dll для PHP 8.
Настоятельно рекомендуется обратиться к » Документации Apache CGI для более полного понимания того, как запускать CGI в Apache.
Чтобы запустить PHP как CGI, файлы php-cgi должны быть помещены в каталог, обозначенный как каталог CGI с использованием директивы ScriptAlias.
Строку #! необходимо будет поместить в файлы PHP, которые
указывают на расположение бинарного файла PHP:
Пример #2 PHP и Apache 2.x как CGI
#!C:/php/php.exe <?php phpinfo(); ?>
Используя установку CGI, ваш сервер открыт перед несколькими возможными уязвимостями. Пожалуйста, ознакомьтесь с разделом "Безопасность CGI" чтобы узнать, как можно защитить себя от таких атак.
Запуск PHP под FastCGI имеет ряд преимуществ перед запуском как CGI. Настройка таким способом довольно проста:
Загрузите mod_fcgid с
» https://www.apachelounge.com.
Бинарные файлы Win32 доступны для загрузки с этого сайта. Установите модуль
в соответствии с прилагаемой к нему инструкцией.
Настройте свой веб-сервер, как показано ниже, позаботившись о том, чтобы скорректировать все пути в соответствии с тем, как вы провели установку в своей конкретной системе:
Пример #3 Настройка Apache для запуска PHP как FastCGI
LoadModule fcgid_module modules/mod_fcgid.so
# Где находится ваш файл php.ini?
FcgidInitialEnv PHPRC "c:/php"
<FilesMatch \.php$>
SetHandler fcgid-script
</FilesMatch>
FcgidWrapper "c:/php/php-cgi.exe" .php
В Проводнике нажмите правой кнопкой мыши на временной директории, выберите пункт "Свойства" и перейдите в закладку "Доступ".
Для IIS, проверьте, что пользователь IIS_User имеет права на изменение для этой директории. Путь временной директории можно посмотреть в файле php.ini.
PHP устанавливается на облачных платформах.
PHP часто устанавливается на облачный сервис Azure App Services (также известный как Microsoft Azure, Windows Azure и Azure Web Apps).
Azure App Services управляет пулом Windows Web Servers для хостинга ваших веб-приложений и представляет альтернативу созданию собственного веб-сервера на собственном Azure Compute VMs и других платформах.
PHP по умолчанию доступен для вашего веб-сайта в Azure App Services. Просто выберите на Azure Portal ваш сайт и выберите нужную версию PHP. Вы можете выбрать более свежую версию, чем заданная по умолчанию.
Таким образом, PHP и его модули будут работать в Azure App Services так же как и на любом другом сервере Windows. Большая часть базы знаний также портирована, смотрите Windows Troubleshooting Page Тем не менее, интерфейс управления для Azure App Services имеет отличия:
Azure portal: создание, настройка и удаление сайтов. » Azure Portal
Панель Kudu: [имя вашего сайта].azurewebsites.net. Тогда панель Kudu » https://[имя вашего сайта].scm.azurewebsites.net/. Панель Kudu даёт вам доступ к некоторым возможностям отладки, управлению файлами и модулями сайта. Модули сайта - это механизм Azure по добавлению программ, например превью сборок PHP, на ваш сайт.
Вы не сможете использовать IIS Manager, Server Manager или RDP.
PHP SDK позволяет программно использовать множество Azure Services. Смотри » Azure SDK для PHP.
Для более подробной информации, смотри » Azure PHP Developer Center
WinCache по умолчанию разрешён в Azure App Services и рекомендуется его не отключать. Если вы установили собственную сборку PHP, вы должны разрешить WinCache.
Вы можете загрузить собственную сборку PHP в D:\Home (C:\ НЕ ДОСТУПЕН для записи). После чего, на Azure Portal, задайте SCRIPT_PROCESSOR для .php равный абсолютному пути к php-cgi.exe из вашей сборки.
FPM (FastCGI Process Manager, менеджер процессов FastCGI) является альтернативной реализацией PHP FastCGI с несколькими дополнительными возможностями обычно используемыми для высоконагруженных сайтов.
Эти возможности включают в себя:
Продвинутое управление процессами с корректной (graceful) процедурой остановки и запуска;
Пулы, дающие возможность запуска воркеров с разными uid/gid/chroot/окружением, прослушивая разные порты и используя разные php.ini (замещение safe_mode);
Настраиваемое ведение журнала потоков вывода (stdout) и ошибок (stderr);
Аварийный перезапуск в случае внезапного разрушения opcode-кеша;
Поддержка ускоренной загрузки (accelerated upload);
"slowlog" - логирование необычно медленно выполняющихся скриптов (не только их имена, но также и их трассировки. Это достигается с помощью ptrace и других подобных утилит для чтения данных исполнения удалённых процессов);
fastcgi_finish_request() - специальная функция для завершения запроса и сброса всех буферов данных, причём процесс может продолжать выполнение каких-либо длительных действий (конвертирование видео, обработка статистики и т.п.);
Динамическое/по требованию/статическое порождение дочерних процессов;
Базовая и расширенная информация о состоянии (аналогично Apache mod_status) с поддержкой различных форматов, таких как json, xml и openmetrics;
Конфигурационный файл, основанный на php.ini.
Для того, чтобы включить FPM при сборке PHP, добавьте строку --enable-fpm
Существуют также несколько других опций конфигурации FPM (все опциональны):
--with-fpm-user - установить пользователя FPM (по умолчанию - nobody).
--with-fpm-group - установить группу FPM (по умолчанию - nobody).
--with-fpm-systemd - Включить интеграцию с systemd (по умолчанию - no).
--with-fpm-acl - Использовать списки управления доступом (ACL) POSIX (по умолчанию - no).
--with-fpm-apparmor - Активировать интеграцию с AppArmor (по умолчанию - no).
--with-fpm-selinux - Активировать интеграцию с SELinux (по умолчанию - no).
| Версия | Описание |
|---|---|
| 8.2.0 |
Добавлена опция --with-fpm-selinux.
|
| 8.0.0 |
Добавлена опция --with-fpm-apparmor.
|
FPM использует синтаксис php.ini для своего файла конфигурации php-fpm.conf и файлов конфигурации пулов.
pid
string
Путь к PID-файлу. По умолчанию: none.
error_log
string
Путь к файлу журнала ошибок.
По умолчанию: #INSTALL_PREFIX#/log/php-fpm.log.
Если задано как "syslog", логирование будет производиться в syslogd, а не
в локальный файл.
log_level
string
Уровень журналирования ошибок. Возможные значения: alert, error, warning, notice, debug. По умолчанию: notice.
log_limit
int
Ограничить журналирование для журналируемых линиях, что позволяет записывать сообщения длиной более 1024 символов без упаковки (wrapping). Значение по умолчанию: 1024. Доступно с PHP 7.3.0.
log_buffering
bool
Экспериментальное журналирование без дополнительной буферизации. Значение по умолчанию: yes. Доступно с PHP 7.3.0.
syslog.facility
string
Используется для указания, какой тип программ будет логировать сообщения. По умолчанию: daemon.
syslog.ident
string
Предшествует любому сообщению. Если у вас запущено несколько экземпляры FPM, вы можете изменить значение по умолчанию на то, которое вам необходимо. По умолчанию: php-fpm.
emergency_restart_threshold
int
При данном числе рабочих процессов, завершённых с SIGSEGV или SIGBUS
за промежуток времени, установленный emergency_restart_interval
FPM будет перезагружен. Значение 0 означает 'Off' (отключено).
По умолчанию: 0 (Off).
emergency_restart_interval
mixed
Интервал времени, используемый emergency_restart_interval,
чтобы определить, когда FPM будет мягко перезагружен. Это полезно для
избежания случайных повреждений общей памяти ускорителя (accelerator).
Доступные единицы измерения: s(секунды), m(минуты), h(часы), или d(дни).
Единица измерения по умолчанию: секунды. Значение по умолчанию: 0 (Off).
process_control_timeout
mixed
Время, в течение которого дочерние процессы ждут ответа на сигналы мастер-процессу. Доступные единицы измерения: s(секунды), m(минуты), h(часы) или d(дни). Единица измерения по умолчанию: секунды. Значение по умолчанию: 0.
process.max
int
Максимальное количество процессов, которое может породить FPM. Это сделано для того, чтобы контролировать глобальное количество процессов, когда используется большой пул динамического PM. Используйте с осторожностью. По умолчанию: 0.
process.priority
int
Указывает приоритет (Unix nice(2)) мастер-процесса (только если установлено). Принимает значения от -19(максимальный приоритет) до 20(минимальный.) По умолчанию: не установлено.
daemonize
bool
Запустить FPM в фоновом режиме. Установите значение 'no', чтобы запустить FPM в диспетчере для отладки. По умолчанию: yes.
rlimit_files
int
Устанавливает rlimit открытых файловых дескрипторов для мастер-процесса. По умолчанию: Значение, определённое системой.
rlimit_core
int
Устанавливает rlimit максимального размера ядра для мастер-процесса. По умолчанию 0.
events.mechanism
string
Указывает, какой событийный механизм будет использован FPM. Возможны такие варианты: select, pool, epoll, kqueue (*BSD), port (Solaris). По умолчанию: не установлено (автоопределение).
systemd_interval
int
Если FPM собран с интеграцией с systemd, указывает интервал, в секундах, между оповещениями systemd о своём состоянии. Для отключения задайте 0. По умолчанию: 10.
С помощью FPM вы можете запускать несколько пулов процессов с различными настройками. Эти параметры могут быть переданы пулу.
listen
string
Адрес, который будет принимать FastCGI-запросы. Синтаксис: 'ip.add.re.ss:port', 'port', '/path/to/unix/socket'. Эта опция обязательна для каждого пула.
listen.backlog
int
Устанавливает listen(2) backlog. Значение -1 означает максимум на системах BSD.
Значение по умолчанию: -1 (FreeBSD или OpenBSD) или 511.
(Linux и другие платформы).
listen.allowed_clients
string
Список адресов IPv4 или IPv6 клиентов FastCGI, которым разрешено подключение. Эквивалент переменной окружения FCGI_WEB_SERVER_ADDRS в оригинальном PHP FastCGI (5.2.2+). Имеет смысл только с TCP-сокетом. Каждый адрес должен быть разделён запятой. Если оставить это значение пустым, соединения будут приниматься с любого IP-адреса. Значение по умолчанию: не задано (принимается любой ip-адрес).
listen.owner
string
Задаёт права для unix-сокета, если они используются. В Linux для разрешения соединений к веб-серверу, должны быть установлены права на чтение/запись. Во многих основанных на BSD-системах возможность соединения не зависит от прав доступа. Значение по умолчанию: используется пользователь и группа, от имени которого запущен сервер, установлен режим 0660.
listen.group
string
Смотрите listen.owner.
listen.mode
string
Смотрите listen.owner.
listen.acl_users
string
Если поддерживается список управления доступом (ACL) POSIX, вы можете настроить
его с помощью этой опции.
Если задано, то listen.owner и listen.group
будут проигнорированы.
Значение задаётся списком имён, разделённых запятой.
listen.acl_groups
string
Смотрите listen.acl_users.
Значение задаётся списком имён групп, разделённых запятой.
user
string
Unix-пользователь FPM-процессов. Этот параметр является обязательным.
group
string
Unix-группа FPM-процессов. Если не установлен, группа по умолчанию равняется имени пользователя.
pm
string
Выбор того, как менеджер процессов будет контролировать создание дочерних процессов.
Возможные значения: static, ondemand,
dynamic.
Этот параметр является обязательным.
static - фиксированное число дочерних процессов (pm.max_children).
ondemand - число процессов, порождающихся по требованию (когда появляются запросы,
в отличие от опции dynamic, когда стартует определённое количество процессов, равное pm.start_servers,
вместе с запуском службы.
dynamic - динамически изменяющееся число дочерних процессов, задаётся на основании
следующих директив: pm.max_children, pm.start_servers,
pm.min_spare_servers, pm.max_spare_servers.
pm.max_children
int
Число дочерних процессов, которые будут созданы, когда pm установлен в
static, или же максимальное число процессов, которые будут созданы,
когда pm установлен в dynamic.
Этот параметр является обязательным.
Этот параметр устанавливает ограничение на число одновременных запросов, которые будут обслуживаться. Эквивалент директивы ApacheMaxClients с mpm_prefork и переменной окружения среды PHP_FCGI_CHILDREN в в оригинальном PHP FastCGI.
pm.start_servers
int
Число дочерних процессов, создаваемых при запуске.
Используется, только когда pm установлен в dynamic.
Значение по умолчанию: min_spare_servers + (max_spare_servers -
min_spare_servers) / 2.
pm.min_spare_servers
int
Желаемое минимальное число неактивных процессов сервера. Используется, только когда
pm установлено в dynamic. Кроме того,
это обязательный параметр в этом случае.
pm.max_spare_servers
int
Желаемое максимальное число неактивных процессов сервера. Используется, только когда
pm установлен в dynamic. Кроме того,
это обязательный параметр в этом случае.
pm.max_spawn_rate
int
Количество одновременных порождений дочерних процессов.
Используется только тогда, когда у параметра pm установлено значение dynamic.
Значение по умолчанию: 32
pm.process_idle_timeout
mixed
Число секунд, по истечению которых простаивающий процесс будет завершён.
Используется только если pm установлено как ondemand.
Допустимые единицы: s(econds)(по умолчанию), m(inutes), h(ours) или d(ays).
По умолчанию: 10s.
pm.max_requests
int
Число запросов дочернего процесса, после которого процесс будет перезапущен. Это полезно для избежания утечек памяти при использовании сторонних библиотек. Для бесконечной обработки запросов укажите '0'. Эквивалент PHP_FCGI_MAX_REQUESTS. Значение по умолчанию: 0.
pm.status_listen
string
Адрес, по которому будет приниматься запрос состояния FastCGI. Создаёт новый невидимый пул, который может независимо обрабатывать запросы. Полезно, если основной пул занят долго выполняющимися запросами, так как всё ещё можно получить страницу состояния FPM до завершения долго выполняющихся запросов. Синтаксис такой же, как и для директивы listen. Значение по умолчанию: none.
pm.status_path
string
Ссылка, по которой можно посмотреть страницу состояния FPM. Значение должно начинаться со слеша (/). Если значение не установлено, то страница статуса отображаться не будет. Значение по умолчанию: none.
ping.path
string
Ссылка на ping-страницу мониторинга FPM. Если значение не установлено, ping-страница отображаться не будет. Может быть использовано для тестирования извне, чтобы убедиться, что FPM жив и отвечает. Обратите внимание, что значение должно начинаться с косой черты (/).
ping.response
string
Эта директива может быть использована на настройки ответа на ping-запрос. Ответ формируется как text/plain со кодом ответа 200. Значение по умолчанию: pong.
process.priority
int
Задаёт приоритет nice(2) для работающего процесса (только если задан). Значение от -19 (высший приоритет) до 20 (самый низкий). Значение по умолчанию: не задано.
process.dumpable
bool
Установить флаг процесса dumpable (PR_SET_DUMPABLE prctl), даже если the пользователь процесса или группа отличается от пользователя мастер-процесса. Это позволяет создавать дамп ядра процесса и выполнить ptrace процесса для пользователя пула. Значение по умолчанию: no. Доступно с PHP 7.0.29, 7.1.17 и 7.2.5.
prefix
string
Задаёт префикс для вычисления пути
request_terminate_timeout
mixed
Время ожидания обслуживания одного запроса, после чего рабочий процесс будет завершён. Этот вариант следует использовать, когда опция 'max_execution_time' в php.ini не останавливает выполнение скрипта по каким-то причинам. Значение '0' означает 'выключено'. Доступные единицы измерения: s(econds), m(inutes), h(ours) или d(ays). Значение по умолчанию: 0.
request_terminate_timeout_track_finished
bool
Время ожидания, установленное с помощью request_terminate_timeout, не включается после fastcgi_finish_request или когда приложение завершено и вызываются внутренние функции завершения работы. Эта директива позволит безоговорочно применять ограничение времени ожидания даже в таких случаях. Значение по умолчанию: нет, начиная с версии PHP 7.3.0.
request_slowlog_timeout
mixed
Время ожидания обслуживания одного запроса, после чего PHP backtrace будет сохранён в файл 'slowlog'. Значение '0' означает 'выключено'. Доступные единицы измерения: s(econds), m(inutes), h(ours) или d(ays). Значение по умолчанию: 0.
request_slowlog_trace_depth
int
Глубина трассировки стека журнала slowlog. Значение по умолчанию: 20, начиная с PHP 7.2.0.
slowlog
string
Лог-файл для медленных запросов. Значение по умолчанию:
#INSTALL_PREFIX#/log/php-fpm.log.slow.
rlimit_files
int
Устанавливает лимит дескрипторов открытых файлов rlimit для дочерних процессов в этом пуле. Значение по умолчанию: определяется значением системы.
rlimit_core
int
Устанавливает максимальное количество используемых ядер rlimit для дочерних процессов в этом пуле. Возможные значения: 'unlimited' или целое число большее или равное 0. Значение по умолчанию: определяется значением системы.
chroot
string
Директория chroot окружения при старте. Это значение должно быть определено как абсолютный путь. Если значение не установлено, chroot не используется.
chdir
string
Chdir изменяет текущую директорию при старте. Это значение должно быть определено как абсолютный путь. Значение по умолчанию: текущая директория или / при использовании chroot.
catch_workers_output
bool
Перенаправление STDOUT и STDERR рабочего процесса в главный лог ошибок. Если не установлен, STDOUT и STDERR будут перенаправлены в /dev/null в соответствии со спецификацией FastCGI. Значение по умолчанию: no.
decorate_workers_output
bool
Включите оформление выхода (output decoration) для вывода worker-процесса когда опция catch_workers_output включена. Значение по умолчанию: yes. Доступно с PHP 7.3.0.
clear_env
bool
Очищает окружение в worker-процессах FPM. Предотвращает попадание произвольных переменных окружения в worker-процессы FPM, очищая окружение у worker-процессах до того, как переменные окружения, указанные в этой конфигурации пула будут добавлены. По умолчанию: Yes.
security.limit_extensions
string
Ограничивает модули, которые FPM будет анализировать. Это может предотвратить ошибки конфигурации на стороне веб-сервера. Вы должны ограничить FPM только расширениями .php для предотвращения выполнения PHP-кода злоумышленниками другими расширениями. По умолчанию: .php .phar
apparmor_hat
string
Если AppArmor включён, позволяет изменить шапку. Значение по умолчанию: не установлено
access.log
string
Лог-файл доступа. Значение по умолчанию: не установлено
access.format
string
Формат лог-файла доступа.
Значение по умолчанию: "%R - %u %t \"%m %r\" %s":
| Заполнитель | Описание |
|---|---|
%C
|
%CPU |
%d
|
длительность µs |
%e
|
fastcgi env |
%f
|
скрипт |
%l
|
длина содержимого |
%m
|
метод |
%M
|
память |
%n
|
название пула |
%o
|
вывод заголовка |
%p
|
PID |
%q
|
строка запроса |
%Q
|
GLUE между %q и %r |
%r
|
URI запроса |
%R
|
удалённый IP-адрес |
%s
|
статус |
%T
|
время |
%t
|
время |
%u
|
удалённый пользователь |
Можно передать дополнительные переменные окружения и обновить настройки PHP для определённого пула. Для этого вам необходимо добавить следующие параметры в файл настройки пула.
Пример #1 Передача переменных окружения и настроек PHP пулу
env[HOSTNAME] = $HOSTNAME env[PATH] = /usr/local/bin:/usr/bin:/bin env[TMP] = /tmp env[TMPDIR] = /tmp env[TEMP] = /tmp php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com php_flag[display_errors] = off php_admin_value[error_log] = /var/log/fpm-php.www.log php_admin_flag[log_errors] = on php_admin_value[memory_limit] = 32M
php_value или
php_flag перезапишут их предыдущие значения.
Пожалуйста, обратите внимание, что определения
disable_functions или
disable_classes не
будут перезаписывать ранее определённые в php.ini значения,
а добавят новые значения.
Настройки, определённые через php_admin_value и php_admin_flag,
не могут быть перезаписаны через ini_set().
Настройки PHP можно устанавливать через веб-сервер.
Пример #2 Установка настроек PHP в nginx.conf
set $php_value "pcre.backtrack_limit=424242"; set $php_value "$php_value \n pcre.recursion_limit=99999"; fastcgi_param PHP_VALUE $php_value; fastcgi_param PHP_ADMIN_VALUE "open_basedir=/var/www/htdocs";
Так как эти настройки передаются в php-fpm как FastCGI-заголовки, php-fpm не должен быть привязан к общедоступному адресу из мира. В противном случае любой сможет изменить настройки PHP. Смотрите также listen.allowed_clients.
Замечание: Пулы не являются механизмом безопасности, потому что они не обеспечивают полного разделения; например все пулы будут использовать один экземпляр OPcache.
» PECL - это репозиторий модулей PHP, доступ к которым предоставляется через систему » PEAR. Эта часть руководства предназначена для демонстрации того, как вы можете получить и установить модули PECL.
Эти инструкции подразумевают, что /your/phpsrcdir/ является путём
к каталогу с дистрибутивом исходного кода PHP, а extname - это имя
модуля PECL, так что вносите соответствующие коррективы. Эти инструкции также подразумевают
знакомство с » командой pear.
Информация в руководстве PEAR для команды pear также применима для
команды pecl.
Для того, чтобы модуль можно было использовать, он должен быть собран, установлен и загружен. Описанные ниже методы предоставляют различные рекомендации по поводу того, как собрать и установить модули, но без применения их автоматической загрузки. Модули могут быть загружены с помощью директивы extension в файле php.ini или путём использования функции dl().
В процессе сборки модулей PHP важно иметь нужные версии необходимых утилит (autoconf, automake, libtool и т.д.). Информацию об этих утилитах и их версиях можно посмотреть в разделе "» Инструкции по осуществлению анонимного доступа к Git".
Есть несколько вариантов для загрузки модулей PECL, в том числе:
pecl install extname автоматически скачивает
код модуля, поэтому в этом случае нет нужды в отдельной
скачке этих файлов.
pecl download extname
Модули PECL, имеющие опубликованные релизы на сайте PECL, доступны для
скачивания и установки с помощью » команды pecl.
Можно также указать отдельные ревизии для установки.
В Windows есть два способа загрузки PHP-модуля: скомпилировать его вместе с PHP или загрузить DLL. Загрузка заранее скомпилированного модуля является наиболее простым и предпочитаемым способом.
Для загрузки модуля, он должен присутствовать в вашей системе в виде ".dll" файла. Все модули автоматически и периодически компилируются командой PHP (смотрите следующий раздел для загрузки).
За инструкциями по компиляции модуля в PHP обратитесь к разделу "Сборка из исходников".
Для компиляции отдельного модуля (или DLL-файла), обратитесь к разделу " Сборка из исходников". Если DLL-файла нет ни в стандартной поставке PHP ни в PECL, возможно, вам придётся скомпилировать его вручную.
PHP-модули обычно имеют имена вида "php_*.dll" (где звёздочка обозначает имя модуля) и располагаются в папке "PHP\ext".
PHP поставляет модули наиболее полезные большинству разработчиков. Такие модули называются "основными" ("core").
Однако, если вам требуется функционал, который не предоставляется ни одним из основных модулей, возможно, нужный вам модуль есть в » PECL. Библиотека модулей сообщества PHP (The PHP Extension Community Library, PECL) является хранилищем модулей PHP, предоставляя каталог и хостинг всех известных модулей для скачки и дальнейшей разработки модулей в PHP.
Если вы разработали какой-либо модуль для собственных нужд, возможно, вы захотите хранить его в PECL, так, чтобы другие также могли воспользоваться результатами вашего труда. Хорошим побочным эффектом будет неплохой шанс получить обратную связь, благодарности (надеемся, что так и будет), сообщения об ошибках и даже исправления/патчи. Пожалуйста, прочтите » публикация PECL; перед отправкой вашего модуля в PECL.
Очень часто существует несколько версий модуля DLL:
и т.д.
Помните, что настройки ваших модулей должны совпадать со всеми настройками используемого вами бинарного файла PHP. Следующий PHP-скрипт выведет вам все настройки PHP:
Пример #1 Вызов phpinfo()
<?php
phpinfo();
?>Или запустите из командной строки:
drive:\\path\to\php\executable\php.exe -i
Наиболее распространённым способом загрузки PHP-модуля является его включение в конфигурационном файле php.ini. Обратите внимание, что большинство модулей уже прописаны в вашем php.ini и для их активации вам просто нужно удалить точку с запятой.
Обратите внимание, что в PHP 7.2.0 и выше для указания модуля можно использовать не имя файла библиотеки, а название самого модуля. Данный подход рекомендуется для использования, так как он более простой и платформонезависимый. Однако вы всё ещё можете прямо указывать имя файла модуля.
;extension=php_extname.dll
extension=php_extname.dll
; В PHP 7.2 и выше лучше делать так: extension=extname zend_extension=another_extension
Однако, некоторые веб-серверы создают путаницу, т.к. они не используют php.ini, расположенный в дистрибутиве PHP, а используют свой собственный. Узнать, где находится, используемый сервером php.ini, можно посмотрев на выводимый путь в phpinfo():
Configuration File (php.ini) Path C:\WINDOWS
Loaded Configuration File C:\Program Files\PHP\5.2\php.ini
После активации модуля сохраните php.ini, перезагрузите веб-сервер и снова проверьте phpinfo(), в нем должен появиться отдельный раздел с новым модулем.
Если модуль не появился в выводе phpinfo(), проверьте лог-файлы на наличие сообщений об ошибках.
Если вы используете PHP в командной строке (CLI), ошибки загрузки модуля будут доступны сразу же на экране.
Если вы используете PHP на веб-сервере, расположение и формат лог-файлов сильно зависит от используемого вами веб-сервера. Пожалуйста, обратитесь к документации вашего веб-сервера, т.к. в данном случае эта ситуация не управляется самим PHP.
Распространёнными проблемами являются расположение библиотеки DLL и DLL-файлов, от которых она зависит, значение " extension_dir" в php.ini, а также несовпадение настроек компиляции.
Если проблемой является несовпадение настроек компиляции, то возможно, вы скачали не тот DLL-файл. Попробуйте снова скачать модуль, на этот раз с правильными настройками. Ещё раз, информация функции phpinfo() сильно помогает в этом случае.
PECL позволяет легко создавать разделяемые модули PHP. Используя » команду pecl, выполните следующее:
Эта команда загрузит исходный код для модуля extname, скомпилирует и установит extname.so в вашу директорию extension_dir. Файл extname.so может быть затем загружен в php.ini
По умолчанию, команда pecl не будет устанавливать пакеты,
отмеченные состоянием alpha или beta.
Если нет доступных стабильных (stable) версий пакетов, вы можете
установить beta-версию пакета, используя следующую команду:
Также, вы можете установить определённую версию, используя такой вариант:
Замечание:
После подключения модуля в php.ini необходимо перезапустить веб-сервер для того, чтобы изменения вступили в силу.
Иногда использование инсталлятора pecl не подходит. Это
может быть связано с тем, что вы находитесь за файерволом или из-за того,
что модуль, который вы хотите установить, недоступен в PECL-совместимом
пакете (к примеру, модули из git, у которых ещё нет релизов). Если вам необходимо
собрать такой модуль, вы можете использовать низкоуровневые утилиты для
выполнения сборки вручную.
Команда phpize используется для подготовки окружения
PHP-модуля. В следующем примере директория, где находятся исходные коды
модуля, называется extname:
$ cd extname $ phpize $ ./configure $ make # make install
В случае успешной установки будет создан файл extname.so и
помещён в PHP директорию модулей.
Вам будет необходимо добавить строку extension=extname.so в
php.ini перед использованием этого модуля.
Если в системе нет phpize, но существует возможность
установки заранее скомпилированных пакетов (типа RPM), убедитесь, что установлена
соответствующая версия пакета PHP для разработчиков, так как они часто
содержат команду phpize с подходящими файлами заголовков для
сборки PHP и его модулей.
Для дополнительной информации используйте команду phpize --help.
php-config - это простой скрипт командной строки для получения информации о конфигурации установленного PHP.
При компиляции модулей, если у вас установлено сразу несколько версий PHP,
вы должны уточнить нужную версию с помощью опции --with-php-config
во время конфигурирования сборки, указав путь до соответствующего php-config скрипта.
Список параметров командной строки доступных для php-config скрипта всегда можно получить запустив php-config с параметром -h:
Usage: /usr/local/bin/php-config [OPTION] Options: --prefix [...] --includes [...] --ldflags [...] --libs [...] --extension-dir [...] --include-dir [...] --php-binary [...] --php-sapis [...] --configure-options [...] --version [...] --vernum [...]
| Опция | Описание |
|---|---|
| --prefix | Директория, в которой установлен PHP, например, /usr/local |
| --includes | Список -I опций со всеми подключаемыми файлами |
| --ldflags | LD-флаги, с которыми был скомпилирован PHP |
| --libs | Внешние библиотеки, с которыми был скомпилирован PHP |
| --extension-dir | Директория, в которой по умолчанию ищутся модули |
| --include-dir | Директория, куда по умолчанию устанавливаются заголовочные файлы |
| --php-binary | Полный путь до исполняемых файлов php CLI или CGI |
| --php-sapis | Показывает все доступные модули SAPI |
| --configure-options | Конфигурационные опции для воссоздания настроек текущей установки PHP. |
| --version | Версия PHP |
| --vernum | Версия PHP в виде целого числа |
Возможно, вы захотите собрать модуль PECL статично в ваш бинарный файл PHP. Для этого необходимо поместить код модуля в директорию php-src/ext/ и вызвать перегенерацию конфигурационных скриптов через систему сборки PHP.
$ cd /your/phpsrcdir/ext $ pecl download extname $ gzip -d < extname.tgz | tar -xvf - $ mv extname-x.x.x extname
В результате будет создана следующая директория:
После этого, выполните заново сборку конфигурационного скрипта PHP и затем соберите PHP как обычно:
Замечание: Для запуска 'buildconf' скрипта вам понадобится autoconf версии 2.13 и automake версии 1.4+ (более новые версии autoconf могут работать, но это не поддерживается).
В зависимости от модуля будет использоваться одна из двух
опций --enable-extname или --with-extname
. Обычно, если модуль не требует подключения
внешних библиотек, используется --enable.
Чтобы узнать это, выполните следующую команду после buildconf:
Некоторые проблемы возникают чаще других. Наиболее часто встречающиеся из них перечислены в разделе PHP FAQ этого руководства.
Если вы всё ещё не можете установить PHP, список рассылки, возможно, сможет помочь вам. Не забудьте сначала просмотреть архив, возможно, кто-то уже сталкивался с похожей проблемой и успешно её решил. Архив рассылки доступен на странице поддержки: » https://www.php.net/support.php Для подписки на список рассылки об установке PHP пришлите пустое сообщение на » php-install-subscribe@lists.php.net. Адрес списка рассылки: » php-install@lists.php.net.
Если вы хотите получить помощь из списка рассылки, пожалуйста, постарайтесь точно описать детали вашего окружения (такие как операционная система, версия PHP, используемый веб-сервер, используете ли вы PHP как CGI или модулем и т.д.), а также достаточное количество кода, чтобы другие смогли воспроизвести вашу проблему и попробовать решить её.
Если вы думаете, что нашли ошибку в PHP, пожалуйста сообщите об этом. Возможно, разработчики PHP не знают об этой ошибке и пока вы не сообщите о ней, мало шансов что она будет исправлена. Вы можете сообщить об ошибке, используя систему отслеживания ошибок по адресу: » https://github.com/php/php-src/issues. Пожалуйста, не шлите сообщения об ошибках в список рассылки или на личные адреса разработчиков. Система отслеживания ошибок также пригодна и для запроса нововведений.
Прочитайте: » Как сообщать об ошибках перед тем как сообщать о них.
Файл конфигурации (php.ini) считывается при запуске PHP. Для версий серверных модулей PHP это происходит только один раз при запуске веб-сервера. Для CGI и CLI версий это происходит при каждом вызове.
Поиск php.ini производится в следующих местах (по порядку поиска):
PHPIniDir директива
Apache 2, -c параметр командной строки CGI и CLI)
php.ini
может быть указано для различных версий PHP. Корневой ключ реестра зависит
от разрядности операционной системы и установки PHP. Для 32-разрядного PHP на
32-разрядной Windows или 64-разрядного PHP и 64-разрядной Windows
используйте [(HKEY_LOCAL_MACHINE\SOFTWARE\PHP]. Для
32-разрядного PHP на 64-разрядной Windows
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\PHP].
Следующие ключи реестра исследуются при поиске для установок с совпадающей
разрядностью:
[HKEY_LOCAL_MACHINE\SOFTWARE\PHP\x.y.z],
[HKEY_LOCAL_MACHINE\SOFTWARE\PHP\x.y] и
[HKEY_LOCAL_MACHINE\SOFTWARE\PHP\x], где
x, y и z подразумевают major, minor и release версии PHP.
Для 32-разрядного PHP на 64-разрядной Windows ключи реестра будут другими:
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6421Node\PHP\x.y.z],
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6421Node\PHP\x.y] и
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6421Node\PHP\x].
Если также имеется значение IniFilePath в любом из этих
ключей, то местонахождение php.ini
будет определено первым ключом по порядку (только для Windows).
[HKEY_LOCAL_MACHINE\SOFTWARE\PHP] или
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\PHP], значение
IniFilePath (только для Windows).
--with-config-file-path с выбором при компиляции.
Если файл php-SAPI.ini существует (где SAPI - это тип интерфейса, который используется, например, php-cli.ini или php-apache.ini), то он используется вместо php.ini. Тип интерфейса между веб-сервером и PHP может быть определён с помощью функции php_sapi_name().
Замечание:
Веб-сервер Apache изменяет текущую директорию на корневую при запуске, в результате чего PHP считывает php.ini из корневой файловой системы, если файл существует.
В php.ini можно использовать переменные окружения, как показано ниже.
Пример #1 Переменные окружения php.ini
; PHP_MEMORY_LIMIT взята из переменных окружения
memory_limit = ${PHP_MEMORY_LIMIT}
Директивы php.ini, обрабатываемые модулями, описаны на соответствующих страницах модулей. Список директив ядра имеется в приложении. Не все директивы PHP документированы в этом руководстве: для ознакомления с полным списком директив доступных в вашей версии PHP, прочитайте комментарии вашего php.ini. Кроме того, вы можете найти полезной » последнюю версию php.ini из Git.
Пример #2 Пример php.ini
; любой текст в строке после точки с запятой (;) без кавычек игнорируется [php] ; маркеры разделов (текст в квадратных скобках) также игнорируется ; Могут быть установлены следующие логические значения: ; true, on, yes ; или false, off, no, none register_globals = off track_errors = yes ; вы можете заключать строки в двойные кавычки include_path = ".:/usr/local/lib/php" ; обратный слеш обрабатывается так же, как любые другие символы include_path = ".;c:\php\lib"
Возможно обращаться к существующим ini-переменным из
ini-файлов. Пример: open_basedir = ${open_basedir}
":/new/dir".
Существует возможность сконфигурировать PHP для сканирования директорий в поисках .ini-файлов после считывания php.ini. Это можно сделать на моменте компиляции, указав опцию --with-config-file-scan-dir. Сканирование директорий может быть переопределено во время исполнения установкой переменной среды PHP_INI_SCAN_DIR.
Можно сканировать несколько директорий, разделяя их разделителем,
используемом в вашей операционной системе (; в Windows, NetWare
и RISC OS; : на всех остальных платформах; в PHP есть
константа PATH_SEPARATOR, которую можно использовать)
Если PHP_INI_SCAN_DIR пуста, то PHP также будет
сканировать директорию, заданную на этапе компиляции с помощью
--with-config-file-scan-dir.
В каждой директории PHP сканирует все файлы заканчивающиеся на .ini
в алфавитном порядке. Список всех загруженных файлов в том порядке,
в котором они были загружены, доступен с помощью функции
php_ini_scanned_files(), либо при запуске PHP с опцией --ini.
Допустим, что PHP сконфигурирован с --with-config-file-scan-dir=/etc/php.d, и разделитель путей :... $ php PHP загрузит все файлы /etc/php.d/*.ini как конфигурационные. $ PHP_INI_SCAN_DIR=/usr/local/etc/php.d php PHP загрузит все файлы /usr/local/etc/php.d/*.ini как конфигурационные. $ PHP_INI_SCAN_DIR=:/usr/local/etc/php.d php PHP загрузит все файлы /etc/php.d/*.ini, а потом /usr/local/etc/php.d/*.ini как конфигурационные. $ PHP_INI_SCAN_DIR=/usr/local/etc/php.d: php PHP загрузит все файлы /usr/local/etc/php.d/*.ini, а потом /etc/php.d/*.ini как конфигурационные.
Включена поддержка INI-файлов в стиле .htaccess на уровне каталога. Эти файлы обрабатываются только CGI/FastCGI SAPI. Эта функция делает ненужным модуль PECL htscanner. Если вы используете PHP как модуль Apache, то для достижения того же эффекта, пользуйтесь файлами .htaccess.
В дополнение к основному файлу php.ini, PHP ищет INI-файлы в каждой директории, начиная с директории запрошенного PHP-файла и продолжает поиск до корневой директории (установленной в $_SERVER['DOCUMENT_ROOT']). Если PHP-файл находится вне корневой директории, то сканируется только его директория.
Только INI-настройки с
режимами PHP_INI_PERDIR и
PHP_INI_USER будут распознаны в INI-файлах в стиле .user.ini.
Две новых INI-директивы, user_ini.filename и user_ini.cache_ttl, контролируют использование пользовательских INI-файлов.
user_ini.filename устанавливает имя файла, по которому PHP производит поиск
в каждой директории; если установлена пустая строка, то PHP поиск не производит.
По умолчанию .user.ini.
user_ini.cache_ttl устанавливает насколько часто пользовательские INI-файлы будут обновляться. По умолчанию период обновления составляет 300 секунд (5 минут).
Эти режимы определяют, когда и где директива PHP может или не может быть установлена, и каждая директива в руководстве относится к одному из этих режимов. К примеру, некоторые настройки могут быть установлены с помощью PHP-скрипта, использующего ini_set(), тогда как другие могут требовать php.ini или httpd.conf.
К примеру, директива
output_buffering соответствует
PHP_INI_PERDIR, поэтому она не может быть установлена через
ini_set(). Тем не менее, директива
display_errors соответствует
PHP_INI_ALL, поэтому она может быть установлена отовсюду,
включая ini_set().
| Режим | Описание |
|---|---|
PHP_INI_USER |
Значение может быть установлено в пользовательских скриптах (с помощью ini_set()) или в реестре Windows. Значение может быть установлено в .user.ini |
PHP_INI_PERDIR |
Значение может быть установлено в php.ini, .htaccess или httpd.conf |
PHP_INI_SYSTEM |
Значение может быть установлено в php.ini или httpd.conf |
PHP_INI_ALL |
Значение может быть установлено отовсюду |
Когда PHP используется как модуль Apache вы также можете менять настройки конфигурации, используя директивы в файлах конфигурации Apache (например, httpd.conf) и файлах .htaccess. Для этого вам необходимы "AllowOverride Options" или "AllowOverride All" привилегии.
Есть несколько директив Apache, которые позволяют вам
изменить конфигурацию PHP посредством файлов конфигурации Apache.
С директивами PHP_INI_ALL, PHP_INI_PERDIR
и PHP_INI_SYSTEM можно ознакомиться в приложении
Список директив php.ini.
php_value
name
value
Устанавливает значение указанной директивы.
Может использоваться только с директивами типа PHP_INI_ALL и PHP_INI_PERDIR.
Для очистки предыдущих установленных значений используйте значение none.
Замечание: Не используйте
php_valueдля установки логических значений. Вместо этого необходимо использоватьphp_flag(смотрите ниже).
php_flag
name
on|off
Используется для установки директивам логических значений.
Может быть использовано только с директивами типа PHP_INI_ALL и
PHP_INI_PERDIR.
php_admin_value
name
value
Устанавливает значение указанной директивы.
Не может быть использовано в файлах .htaccess.
Директивы любого типа, установленные с помощью php_admin_value
не могут быть переопределены через .htaccess или ini_set().
Чтобы очистить предыдущее значение используйте значение none.
php_admin_flag
name
on|off
Используется для установки директивам логических значений.
Не может быть использовано в файлах .htaccess.
Директивы любого типа, установленные с помощью php_admin_flag
не могут быть переопределены через .htaccess или ini_set().
Пример #1 Пример конфигурации Apache
<IfModule mod_php5.c> php_value include_path ".:/usr/local/lib/php" php_admin_flag engine on </IfModule> <IfModule mod_php4.c> php_value include_path ".:/usr/local/lib/php" php_admin_flag engine on </IfModule>
PHP-константы недоступны вне PHP. К примеру, в
httpd.conf вы не можете использовать константы PHP
такие как E_ALL или E_NOTICE,
чтобы установить директиву error_reporting,
так как они не будут иметь значения и будут приравниваться к 0.
Используйте вместо этого соответствующие значения типа bitmask (битовая маска).
Эти константы могут быть использованы в php.ini
При использовании PHP в Windows значения конфигурации могут быть
изменены на уровне директории посредством реестра Windows.
Значения конфигурации хранятся в ключе реестра
HKLM\SOFTWARE\PHP\Per Directory Values,
в подключах, включающих полный путь. К примеру, значения конфигурации для директории
c:\inetpub\wwwroot могут храниться в ключе
HKLM\SOFTWARE\PHP\Per Directory Values\c\inetpub\wwwroot.
Настройки для директории будут действительны для любых скриптов, запущенных из
этой директории или её поддиректории. Значения ключа должны иметь название
конфигурационной директивы PHP и строковое значение.
PHP-константы в значениях игнорируются.
Однако только значения конфигурации, изменяемые в
PHP_INI_USER могут быть установлены таким образом,
значения же PHP_INI_PERDIR не могут,
потому что эти значения конфигурации перечитываются для каждого запроса.
Независимо от того, как вы запускаете PHP, вы можете изменять некоторые значения во время выполнения ваших скриптов c помощью ini_set(). Для более детальной информации смотрите документацию на странице функции ini_set().
Если вам интересен полный список конфигурационных настроек вашей системы с текущими значениями, то вы можете запустить функцию phpinfo() и просмотреть результирующую страницу. Вы также можете получить доступ к значениям индивидуально сконфигурированных директив в процессе выполнения, используя ini_get() или get_cfg_var().
Все, что находится вне пары открывающегося и закрывающегося тегов, игнорируется интерпретатором PHP, у которого есть возможность обрабатывать файлы со смешанным содержимым. Это позволяет PHP-коду быть встроенным в документы HTML, к примеру, для создания шаблонов.
<p>Это будет проигнорировано PHP и отображено браузером.</p>
<?php echo 'А это будет обработано.'; ?>
<p>Это тоже будет проигнорировано PHP и отображено браузером.</p>Использование структур с условиями
Пример #1 Продвинутое изолирование с использованием условий
<?php if ($expression == true): ?>
Это будет отображено, если выражение истинно.
<?php else: ?>
В ином случае будет отображено это.
<?php endif; ?>При выводе больших блоков текста выход из режима синтаксического разбора PHP обычно более эффективен, чем отправка текста с помощью функций echo или print.
Замечание:
Кроме того, если вы намереваетесь вставлять PHP-код в XML или XHTML, чтобы соответствовать XML стандартам, вам следует использовать форму <?php ?>.
Как в C или Perl, PHP требует окончания инструкций точкой запятой в конце каждой инструкции. Закрывающий тег блока PHP-кода автоматически применяет точку с запятой; т.е. нет необходимости ставить точку с запятой в конце последней строки блока с PHP-кодом. Закрывающий тег блока "поглотит" немедленно следующий за ним переход на новую строку, если таковой будет обнаружен.
Пример #1 Пример, показывающий закрывающий тег, охватывающий завершающую новую строку
<?php echo "Какой-то текст"; ?>
Нет новой строки
<?= "А сейчас, новая строка" ?>Результат выполнения данного примера:
Какой-то текстНет новой строки А сейчас, новая строка
Примеры входа и выхода из парсера PHP:
<?php
echo 'Это тест';
?>
<?php echo 'Это тест' ?>
<?php echo 'Мы опустили последний закрывающий тег';Замечание:
Закрывающий тег PHP-блока в конце файла не является обязательным, и в некоторых случаях его опускание довольно полезно, например, при использовании include или require, так, что нежелательные пробелы не останутся в конце файла и вы всё ещё сможете добавить http-заголовки после подключения к ответу сервера. Это также удобно при использовании буферизации вывода, где также нежелательно иметь пробелы в конце частей ответа, сгенерированного подключаемыми файлами.
PHP поддерживает комментарии в стиле 'C', 'C++' и оболочки Unix (стиль Perl). Например:
<?php
echo "Это тест"; // Это однострочный комментарий в стиле C++
/* Это многострочный комментарий
ещё одна строка комментария */
echo "Это ещё один тест";
echo "Последний тест"; # Это комментарий в стиле оболочки Unix
?>
Однострочные комментарии идут только до конца строки или текущего
блока PHP-кода, в зависимости от того, что идёт перед ними.
Это означает, что HTML-код после // ... ?>
или # ... ?> БУДЕТ напечатан: ?> завершает
режим PHP и возвращает режим HTML, а // или
# не могут повлиять на это.
<h1>Это <?php # echo "простой";?> пример</h1>
<p>Заголовок вверху выведет 'Это пример'.</p>
'C'-комментарии заканчиваются при первой же обнаруженной последовательности
*/. Убедитесь, что вы не вкладываете друг в друга
'C'-комментарии. Очень легко допустить эту ошибку при комментировании
большого блока кода.
<?php
/*
echo "Это тест"; /* Этот комментарий вызовет проблему */
*/
?>У каждого выражения в PHP один из следующих встроенных типов в зависимости от его значения:
PHP – динамически типизированный язык, что означает, что по умолчанию нет необходимости указывать тип переменной, так как он будет определён во время выполнения. Однако можно статически типизировать некоторые аспекты языка, используя декларации типов.
Типы ограничивают тип операций, которые могут быть выполнены над ними. Однако, если выражение/переменная используется в операции, которую не поддерживает её тип, PHP попытается преобразовать значение в тип, который поддерживает операцию. Этот процесс зависит от контекста, в котором используется значение. Для получения дополнительной информации смотрите раздел Манипуляции с типами.
Таблицы сравнения типов также могут быть полезны, поскольку в них представлены различные примеры сравнения значений разных типов.
Замечание: Можно заставить выражение оцениваться с определённым типом, используя приведение типов. Переменная также может быть приведена к определённому типу с помощью функции settype().
Чтобы проверить значение и тип выражения,
используйте функцию var_dump().
Чтобы получить тип выражения,
используйте функцию get_debug_type().
Однако, чтобы проверить, является ли выражение определённым типом, используйте функции
is_type.
<?php
$a_bool = true; // логическое значение
$a_str = "foo"; // строка
$a_str2 = 'foo'; // строка
$an_int = 12; // целое число
echo get_debug_type($a_bool), "\n";
echo get_debug_type($a_str), "\n";
// Если это целое число, увеличить на четыре
if (is_int($an_int)) {
$an_int += 4;
}
var_dump($an_int);
// Если $a_bool - это строка, вывести её
if (is_string($a_bool)) {
echo "Строка: $a_bool";
}
?>Результат выполнения данного примера в PHP 8:
bool string int(16)
Замечание: До PHP 8.0.0, где функция get_debug_type() недоступна, вместо неё можно использовать функцию gettype(). Однако она не использует канонические имена типов.
В PHP используется система номинальных типов с сильным поведенческим отношением подтипизации. Отношение подтипизации проверяется во время компиляции, в то время как верификация типов проверяется динамически во время выполнения.
Система типов PHP поддерживает различные базовые типы, которые могут быть объединены вместе для создания более сложных типов. Некоторые из этих типов могут быть записаны как объявление типов.
Некоторые базовые типы являются встроенными типами, которые тесно интегрированы с языком и не могут быть воспроизведены с помощью типов, определённых пользователем.
Список базовых типов:
Можно объединять простые типы в составные типы. PHP позволяет объединять типы следующими способами:
Пересечение типов принимает значения, удовлетворяющие не одному,
а нескольким объявлениям типов классов.
Отдельные типы, образующие пересечение типов, соединяются символом &.
Поэтому пересечение типов, состоящее из типов T, U и V,
будет записано как T&U&V.
Объединение типов принимает значения нескольких различных типов, а не одного.
Отдельные типы, образующие объединение типов, соединяются символом |.
Поэтому объединение типов, состоящее из типов T, U и V,
будет записано как T|U|V.
Если один из типов является пересечением типов,
то для записи в DNF его нужно заключить в скобки: T|(X&Y).
PHP поддерживает два псевдонима типов: mixed и
iterable, которые соответствуют
объединению типов
object|resource|array|string|float|int|bool|null
и Traversable|array соответственно.
Замечание: PHP не поддерживает определяемые пользователем псевдонимы типов.
Тип null - это единичный тип PHP, то есть он имеет только одно значение: null.
Неопределённые и unset() переменные преобразуются в значение null.
Существует только одно значение типа null - регистронезависимая
константа null.
<?php
$var = NULL;
?>null
Данная функциональность объявлена УСТАРЕВШЕЙ, начиная с PHP 7.2.0 и была УДАЛЕНА в версии PHP 8.0.0. Использовать эту функцию крайне не рекомендуется.
Приведение переменной к null с использованием (unset) $var
не удаляет переменную и её значение.
Данное выражение только возвращает null
У логического типа (bool) только два значения,
которые используются для выражения истинностного значения.
Он может быть либо true, либо false.
Для указания bool, используйте константы true или
false. Они обе регистронезависимы.
<?php
$foo = True; // присвоить $foo значение TRUE
?>Обычно, некоторый оператор возвращает значение типа bool, которое потом передаётся управляющей конструкции.
<?php
// == это оператор, который проверяет
// эквивалентность и возвращает boolean
if ($action == "show_version") {
echo "Версия 1.23";
}
// это необязательно...
if ($show_separators == TRUE) {
echo "<hr>\n";
}
// ... потому что следующее имеет тот же самый смысл:
if ($show_separators) {
echo "<hr>\n";
}
?>
Для явного преобразования в bool, используйте
приведение (bool).
Обычно в этом нет необходимости, поскольку при использовании значения в логическом контексте
оно автоматически интерпретируется как значение логического типа (bool).
Дополнительную информацию смотрите на странице манипуляции с типами.
При преобразовании в bool, следующие значения рассматриваются как
false:
false
0 (ноль)
0.0 (ноль) и -0.0 (минус ноль)
"" и
строка "0"
Все остальные значения считаются true
(включая resource
и NAN).
-1 рассматривается как true, как и любое другое ненулевое
(отрицательное или положительное) число!
<?php
var_dump((bool) ""); // bool(false)
var_dump((bool) "0"); // bool(false)
var_dump((bool) 1); // bool(true)
var_dump((bool) -2); // bool(true)
var_dump((bool) "foo"); // bool(true)
var_dump((bool) 2.3e5); // bool(true)
var_dump((bool) array(12)); // bool(true)
var_dump((bool) array()); // bool(false)
var_dump((bool) "false"); // bool(true)
?>int - это число из множества ℤ = {..., -2, -1, 0, 1, 2, ...}.
Целые числа (int) могут быть указаны в десятичной (основание 10), шестнадцатеричной (основание 16), восьмеричной (основание 8) или двоичной (основание 2) системе счисления. Для задания отрицательных целых (int) используется оператор отрицания
Для записи в восьмеричной системе счисления, необходимо поставить перед числом 0 (ноль).
Начиная с PHP 8.1.0, восьмеричной нотации также может предшествовать 0o или 0O.
Для записи в шестнадцатеричной системе счисления, необходимо поставить перед числом 0x.
Для записи в двоичной системе счисления, необходимо поставить перед числом 0b
Начиная с PHP 7.4.0, целочисленные литералы могут содержать подчёркивания (_) между цифрами для лучшей читаемости литералов. Эти подчёркивания удаляются сканером PHP.
Пример #1 Целые числа
<?php
$a = 1234; // десятичное число
$a = 0123; // восьмеричное число (эквивалентно 83 в десятичной системе)
$a = 0o123; // восьмеричное число (начиная с PHP 8.1.0)
$a = 0x1A; // шестнадцатеричное число (эквивалентно 26 в десятичной системе)
$a = 0b11111111; // двоичное число (эквивалентно 255 в десятичной системе)
$a = 1_234_567; // десятичное число (с PHP 7.4.0)
?>
Формально, структура целых чисел int принята в PHP 8.1.0
(ранее не допускались восьмеричные префиксы 0o или 0O,
а до PHP 7.4.0 не допускалось подчёркивание):
десятичные : [1-9][0-9]*(_[0-9]+)*
| 0
шестнадцатеричные : 0[xX][0-9a-fA-F]+(_[0-9a-fA-F]+)*
восьмеричные : 0[oO]?[0-7]+(_[0-7]+)*
двоичные : 0[bB][01]+(_[01]+)*
целые : десятичные
| шестнадцатеричные
| восьмеричные
| двоичные
Размер типа int зависит от платформы, хотя, как правило,
максимальное значение примерно равно 2 миллиардам (это 32-битное знаковое).
64-битные платформы обычно имеют максимальное значение около 9E18.
PHP не поддерживает беззнаковые целые числа (int).
Размер int может быть определён
с помощью константы PHP_INT_SIZE, максимальное значение -
с помощью константы PHP_INT_MAX,
а с помощью константы PHP_INT_MIN можно
определить минимальное значение.
Если PHP обнаружил, что число превышает размер типа int, он будет интерпретировать его в качестве float. Аналогично, если результат операции лежит за границами типа int, он будет преобразован в float.
Пример #2 Переполнение целых на 32-битных системах
<?php
$large_number = 2147483647;
var_dump($large_number); // int(2147483647)
$large_number = 2147483648;
var_dump($large_number); // float(2147483648)
$million = 1000000;
$large_number = 50000 * $million;
var_dump($large_number); // float(50000000000)
?>Пример #3 Переполнение целых на 64-битных системах
<?php
$large_number = 9223372036854775807;
var_dump($large_number); // int(9223372036854775807)
$large_number = 9223372036854775808;
var_dump($large_number); // float(9.2233720368548E+18)
$million = 1000000;
$large_number = 50000000000000 * $million;
var_dump($large_number); // float(5.0E+19)
?>
В PHP нет оператора деления целых чисел (int),
для этого используйте функцию intdiv()>.
Результатом 1/2 будет float 0.5.
Если привести значение к int, оно будет округлено вниз, то есть
будет отброшена дробная часть числа.
Для большего контроля над округлением используйте функцию round().
<?php
var_dump(25/7); // float(3.5714285714286)
var_dump((int) (25/7)); // int(3)
var_dump(round(25/7)); // float(4)
?>
Для явного преобразования в int, используйте приведение
(int) или (integer). Однако,
в большинстве случаев, в приведении типа нет необходимости, так как значение
будет автоматически преобразовано, если оператор, функция или управляющая структура
требует аргумент типа int. Значение также может быть преобразовано в
int с помощью функции intval().
Если resource преобразуется в int, то результатом будет уникальный номер ресурса, привязанный к resource во время исполнения PHP программы.
Смотрите также: Манипуляции с типами.
false преобразуется в 0 (ноль), а true - в
1 (единицу).
При преобразовании из float в int, число будет округлено в сторону нуля. Начиная с PHP 8.1.0, при неявном преобразовании неинтегрального числа с плавающей точкой (float) в целое число (int), которое теряет точность, выдаётся уведомление об устаревании.
<?php
function foo($value): int {
return $value;
}
var_dump(foo(8.1)); // "Deprecated: Implicit conversion from float 8.1 to int loses precision" начиная с PHP 8.1.0
var_dump(foo(8.1)); // 8 до PHP 8.1.0
var_dump(foo(8.0)); // 8 в обоих случаях
var_dump((int)8.1); // 8 в обоих случаях
var_dump(intval(8.1)); // 8 в обоих случаях
?>
Если число с плавающей точкой превышает размеры int (обычно
+/- 2.15e+9 = 2^31 на 32-битных системах и
+/- 9.22e+18 = 2^63 на 64-битных системах, результат будет неопределённым,
так как float не имеет достаточной точности, чтобы вернуть верный результат в виде целого числа (int).
В этом случае не будет выведено ни предупреждения, ни даже замечания!
Замечание:
Значения NaN и Infinity при приведении к int становятся равными нулю, вместо неопределённого значения в зависимости от платформы.
Никогда не приводите неизвестную дробь к int, так как это иногда может дать неожиданные результаты.
<?php
echo (int) ( (0.1+0.7) * 10 ); // выводит 7!
?>Смотрите более подробно: предупреждение о точности чисел с плавающей точкой.
Если строка
содержит число
или ведущую числовую последовательность, тогда она будет преобразована в соответствующее целое число,
в противном случае она преобразуется в ноль (0).
Значение null всегда преобразуется в ноль (0).
Для других типов поведение преобразования в int не определено. Не полагайтесь на любое наблюдаемое поведение, так как оно может измениться без предупреждения.
Числа с плавающей точкой или числа с плавающей запятой (также известные как "float", "double" или "real") могут быть определены следующими синтаксисами:
<?php
$a = 1.234;
$b = 1.2e3;
$c = 7E-10;
$d = 1_234.567; // начиная с PHP 7.4.0
?>Формально, начиная с PHP 7.4.0 (ранее подчёркивание не разрешалось):
LNUM [0-9]+(_[0-9]+)*
DNUM ([0-9]*(_[0-9]+)*[\.]{LNUM}) | ({LNUM}[\.][0-9]*(_[0-9]+)*)
EXPONENT_DNUM (({LNUM} | {DNUM}) [eE][+-]? {LNUM})
Размер числа с плавающей точкой зависит от платформы, хотя максимум, как правило, составляет 1.8e308 с точностью около 14 десятичных цифр (64-битный формат IEEE).
Числа с плавающей точкой имеют ограниченную точность. Хотя это зависит от операционной системы, в PHP обычно используется формат двойной точности IEEE 754, дающий максимальную относительную ошибку округления порядка 1.11e-16. Неэлементарные арифметические операции могут давать большие ошибки, и, разумеется, необходимо принимать во внимание распространение ошибок при совместном использовании нескольких операций.
Кроме того, рациональные числа, которые могут быть точно представлены
в виде чисел с плавающей точкой с основанием 10, например,
0.1 или 0.7, не имеют
точного внутреннего представления в качестве чисел с плавающей точкой
с основанием 2, вне зависимости от размера мантиссы.
Поэтому они и не могут быть преобразованы в их внутреннюю двоичную форму
без небольшой потери точности. Это может привести к неожиданным результатам:
например, floor((0.1+0.7)*10) скорее всего вернёт
7 вместо ожидаемого 8, так как
результат внутреннего представления будет чем-то вроде
7.9999999999999991118....
Так что никогда не доверяйте точности чисел с плавающей точкой до последней цифры и не проверяйте напрямую их равенство. Если вам действительно необходима высокая точность, используйте математические функции произвольной точности и gmp-функции.
"Простое" объяснение можно найти в » руководстве по числам с плавающей точкой, которое также называется "Why don’t my numbers add up?" ("Почему мои числа не складываются?")
Если строка
содержит число
или ведущую числовую последовательность, тогда она будет преобразована в соответствующее значение с плавающей точкой,
в противном случае она преобразуется в ноль (0).
Для значений других типов преобразование выполняется путём преобразования значения сначала в целое число (int), а затем в число с плавающей точкой ( float ). Смотрите Преобразование в целое число для получения дополнительной информации.
Замечание:
Поскольку определённые типы имеют неопределённое поведение при преобразовании в целое число (int), то же самое происходит и при преобразовании в число с плавающей точкой (float).
Как указано выше, проверять числа с плавающей точкой на равенство проблематично из-за их внутреннего представления. Тем не менее, существуют способы для их сравнения, которые работают несмотря на все эти ограничения.
Для сравнения чисел с плавающей точкой используется верхняя граница относительной ошибки при округлении. Эта величина называется машинной эпсилон или единицей округления (unit roundoff) и представляет собой самую маленькую допустимую разницу при расчётах.
$a и $b равны до 5-ти знаков после точки.
<?php
$a = 1.23456789;
$b = 1.23456780;
$epsilon = 0.00001;
if (abs($a - $b) < $epsilon) {
echo "true";
}
?>
Некоторые числовые операции могут возвращать значение, представляемое
константой NAN. Данный результат означает неопределённое
или непредставимое значение в операциях с плавающей точкой. Любое строгое
или нестрогое сравнение данного значения с другим значением, кроме true, включая его
самого, возвратит false.
Так как NAN представляет собой неограниченное количество
различных значений, то NAN не следует сравнивать с
другими значениями, включая её саму. Вместо этого, для определения её наличия
необходимо использовать функцию is_nan().
Строка (тип string) - это набор символов, где символ - это то же самое, что и байт. Это значит, что PHP поддерживает ровно 256 различных символов, а также то, что в PHP нет встроенной поддержки Unicode. Смотрите также подробности реализации строкового типа.
Замечание: В 32-битных системах и в более ранних версиях PHP, строки (string) не могут быть более 2 ГБ (2147483647 байт).
Строка может быть определена четырьмя различными способами:
Простейший способ определить строку - это заключить её в одинарные кавычки
(символ ').
Чтобы использовать одинарную кавычку внутри строки, проэкранируйте её обратным слешем
(\). Если необходимо написать сам обратный слеш, продублируйте его
(\\). Все остальные случаи применения обратного слеша будут
интерпретированы как обычные символы: это означает, что если вы попытаетесь
использовать другие управляющие последовательности, такие как \r или
\n, они будут выведены как есть вместо какого-либо особого поведения.
Замечание: В отличие от синтаксиса двойных кавычек и heredoc, переменные и управляющие последовательности для специальных символов, заключённых в одинарные кавычки, не обрабатываются.
<?php
echo 'это простая строка';
echo 'Также вы можете вставлять в строки
символ новой строки вот так,
это нормально';
// Выводит: Однажды Арнольд сказал: "I'll be back"
echo 'Однажды Арнольд сказал: "I\'ll be back"';
// Выводит: Вы удалили C:\*.*?
echo 'Вы удалили C:\\*.*?';
// Выводит: Вы удалили C:\*.*?
echo 'Вы удалили C:\*.*?';
// Выводит: Это не будет развёрнуто: \n новая строка
echo 'Это не будет развёрнуто: \n новая строка';
// Выводит: Переменные $expand также $either не разворачиваются
echo 'Переменные $expand также $either не разворачиваются';
?>Если строка заключена в двойные кавычки ("), PHP распознает следующие управляющие последовательности специальных символов:
| Последовательность | Значение |
|---|---|
\n |
новая строка (LF или 0x0A (10) в ASCII) |
\r |
возврат каретки (CR или 0x0D (13) в ASCII) |
\t |
горизонтальная табуляция (HT или 0x09 (9) в ASCII) |
\v |
вертикальная табуляция (VT или 0x0B (11) в ASCII) |
\e |
escape-знак (ESC или 0x1B (27) в ASCII) |
\f |
подача страницы (FF или 0x0C (12) в ASCII) |
\\ |
обратная косая черта |
\$ |
знак доллара |
\" |
двойная кавычка |
\[0-7]{1,3} |
последовательность символов, соответствующая регулярному выражению символа в восьмеричной системе счисления, который молча переполняется, чтобы поместиться в байт (т.е. "\400" === "\000") |
\x[0-9A-Fa-f]{1,2} |
последовательность символов, соответствующая регулярному выражению символа в шестнадцатеричной системе счисления |
\u{[0-9A-Fa-f]+} |
последовательность символов, соответствующая регулярному выражению символа Unicode, которая отображается в строка в представлении UTF-8 |
Как и в строке, заключённой в одинарные кавычки, экранирование любого другого символа выведет также и сам символ экранирования.
Но самым важным свойством строк в двойных кавычках является обработка переменных. Смотрите более подробно обработку строк.
Третий способ определения строк - это использование heredoc-синтаксиса:
<<<. После этого оператора необходимо указать идентификатор,
затем перевод строки. После этого идёт сама строка, а потом этот же идентификатор,
закрывающий вставку.
Закрывающий идентификатор может иметь отступ с помощью пробела или табуляции, и в этом случае отступ будет удалён из всех строк в строке документа. До PHP 7.3.0 закрывающий идентификатор должен был находиться в самом начале новой строки.
Кроме того, закрывающий идентификатор должен соответствовать тем же правилам именования, что и любая другая метка в PHP: он должен содержать только буквенно-цифровые символы и подчёркивания и должен начинаться с нецифрового символа или символа подчёркивания.
Пример #1 Базовый пример использования Heredoc в PHP 7.3.0
<?php
// без отступов
echo <<<END
a
b
c
\n
END;
// 4 отступа
echo <<<END
a
b
c
END;Результат выполнения данного примера в PHP 7.3:
a
b
c
a
b
c
Если закрывающий идентификатор смещён дальше, чем любая строка тела, будет выброшено ParseError:
Пример #2 Закрывающий идентификатор не должен иметь отступ больше, чем любая строка тела
<?php
echo <<<END
a
b
c
END;Результат выполнения данного примера в PHP 7.3:
PHP Parse error: Invalid body indentation level (expecting an indentation level of at least 3) in example.php on line 4
Если у закрывающего идентификатора есть отступ, табуляции также могут использоваться, однако табуляции и пробелы не должны смешиваться в отношении отступа закрывающего идентификатора и отступа тела (вплоть до закрывающего идентификатора). В любом из этих случаев будет выброшено ParseError. Эти ограничения на пробелы были включены, потому что смешивание табуляции и пробелов для отступов вредно для разбора.
Пример #3 Другой отступ для закрывающего идентификатора тела (пробелов)
<?php
// Весь следующий код не работает.
// Другой отступ для закрывающего идентификатора (табов) тела (пробелов)
{
echo <<<END
a
END;
}
// смешивание пробелов и табуляции в теле
{
echo <<<END
a
END;
}
// смешивание пробелов и табуляции в закрывающем идентификаторе
{
echo <<<END
a
END;
}Результат выполнения данного примера в PHP 7.3:
PHP Parse error: Invalid indentation - tabs and spaces cannot be mixed in example.php line 8
За закрывающим идентификатором основной строки не обязательно ставить точку с запятой или новую строку. Например, начиная с PHP 7.3.0 разрешён следующий код:
Пример #4 Продолжение выражения после закрывающего идентификатора
<?php
$values = [<<<END
a
b
c
END, 'd e f'];
var_dump($values);Результат выполнения данного примера в PHP 7.3:
array(2) {
[0] =>
string(11) "a
b
c"
[1] =>
string(5) "d e f"
}
Если закрывающий идентификатор был найден в начале строки, то независимо от того, был ли он частью другого слова, его можно рассматривать как закрывающий идентификатор и выбросить ParseError.
Пример #5 Закрывающий идентификатор в теле текста имеет тенденцию вызывать ParseError
<?php
$values = [<<<END
a
b
END ING
END, 'd e f'];Результат выполнения данного примера в PHP 7.3:
PHP Parse error: syntax error, unexpected identifier "ING", expecting "]" in example.php on line 6
Чтобы избежать этой проблемы, безопасно следуйте простому правилу: не выбирайте закрывающий идентификатор, который появляется в теле текста.
До PHP 7.3.0 очень важно отметить, что строка с закрывающим идентификатором не должна содержать
других символов, за исключением точки с запятой (;). Это означает,
что идентификатор не должен вводиться с отступом и что не
может быть никаких пробелов или знаков табуляции до или после точки с запятой. Важно
также понимать, что первым символом перед закрывающим идентификатором должен быть
символ новой строки, определённый в вашей операционной системе. Например, в UNIX
системах, включая macOS, это \n. После закрывающего
идентификатора также сразу должна начинаться новая строка.
Если это правило нарушено и закрывающий идентификатор не является "чистым", считается, что закрывающий идентификатор отсутствует и PHP продолжит его поиск дальше. Если в этом случае верный закрывающий идентификатор так и не будет найден, то это вызовет ошибку парсинга с номером строки в конце скрипта.
Пример #6 Пример неправильного синтаксиса, до PHP 7.3.0
<?php
class foo {
public $bar = <<<EOT
bar
EOT;
// отступ перед закрывающим идентификатором недопустим
}
?>Пример #7 Пример правильного синтаксиса, даже до PHP 7.3.0
<?php
class foo {
public $bar = <<<EOT
bar
EOT;
}
?>Heredoc, содержащий переменные, не может использоваться для инициализации свойств класса.
Heredoc-текст ведёт себя так же, как и строка в двойных кавычках, при этом их не имея. Это означает, что вам нет необходимости экранировать кавычки в heredoc, но вы по-прежнему можете использовать вышеперечисленные управляющие последовательности. Переменные обрабатываются, но с применением сложных переменных внутри heredoc нужно быть также внимательным, как и при работе со строками.
Пример #8 Пример определения heredoc-строки
<?php
$str = <<<EOD
Пример строки,
охватывающей несколько строк,
с использованием heredoc-синтаксиса.
EOD;
/* Более сложный пример с переменными. */
class foo
{
var $foo;
var $bar;
function __construct()
{
$this->foo = 'Foo';
$this->bar = array('Bar1', 'Bar2', 'Bar3');
}
}
$foo = new foo();
$name = 'Имярек';
echo <<<EOT
Меня зовут "$name". Я печатаю $foo->foo.
Теперь я вывожу {$foo->bar[1]}.
Это должно вывести заглавную букву 'A': \x41
EOT;
?>Результат выполнения данного примера:
Меня зовут "Имярек". Я печатаю Foo. Теперь, я вывожу Bar2. Это должно вывести заглавную букву 'A': A
Также возможно использовать heredoc-синтаксис для передачи данных через аргументы функции:
Пример #9 Пример применения heredoc в аргументах
<?php
var_dump(array(<<<EOD
foobar!
EOD
));
?>Можно инициализировать статические переменные и свойства/константы класса с помощью синтаксиса heredoc:
Пример #10 Использование heredoc для инциализации статических переменных
<?php
// Статические переменные
function foo()
{
static $bar = <<<LABEL
Здесь ничего нет...
LABEL;
}
// Константы/свойства класса
class foo
{
const BAR = <<<FOOBAR
Пример использования константы
FOOBAR;
public $baz = <<<FOOBAR
Пример использования поля
FOOBAR;
}
?>Можно также окружать идентификатор Heredoc двойными кавычками:
Пример #11 Использование двойных кавычек в heredoc
<?php
echo <<<"FOOBAR"
Привет, мир!
FOOBAR;
?>
Nowdoc - это то же самое для строк в одинарных кавычках, что и heredoc для строк в
двойных кавычках. Nowdoc похож на heredoc, но внутри него
не осуществляется никаких подстановок. Эта конструкция
идеальна для внедрения PHP-кода или других больших блоков текста без необходимости
его экранирования. В этом он немного похож на SGML-конструкцию
<![CDATA[ ]]> тем, что объявляет блок текста,
не предназначенный для обработки.
Nowdoc указывается той же последовательностью <<<,
что используется в heredoc, но последующий за ней идентификатор заключается
в одинарные кавычки, например, <<<'EOT'.
Все условия, действующие для идентификаторов heredoc также действительны
и для nowdoc, особенно те, что относятся к закрывающему идентификатору.
Пример #12 Пример использования nowdoc
<?php
echo <<<'EOD'
Пример текста,
занимающего несколько строк,
с помощью синтаксиса nowdoc. Обратные слеши всегда обрабатываются буквально,
например, \\ и \'.
EOD;Результат выполнения данного примера:
Пример текста, занимающего несколько строк, с помощью синтаксиса nowdoc. Обратные слеши всегда обрабатываются буквально, например, \\ и \'.
Пример #13 Nowdoc пример цитирования строки с переменными
<?php
/* Более сложный пример с переменными. */
class foo
{
public $foo;
public $bar;
function __construct()
{
$this->foo = 'Foo';
$this->bar = array('Bar1', 'Bar2', 'Bar3');
}
}
$foo = new foo();
$name = 'Имярек';
echo <<<'EOT'
Меня зовут "$name". Я печатаю $foo->foo.
Теперь я печатаю {$foo->bar[1]}.
Это не должно вывести заглавную 'A': \x41
EOT;
?>Результат выполнения данного примера:
Меня зовут "$name". Я печатаю $foo->foo.
Теперь я печатаю {$foo->bar[1]}.
Это не должно вывести заглавную 'A': \x41Пример #14 Пример использования статичных данных
<?php
class foo {
public $bar = <<<'EOT'
bar
EOT;
}
?>Если строка указывается в двойных кавычках, либо при помощи heredoc, переменные внутри неё обрабатываются.
Существует два типа синтаксиса: простой и сложный. Простой синтаксис более лёгок и удобен. Он даёт возможность обработки переменной, значения массива (array) или свойства объекта (object) с минимумом усилий.
Сложный синтаксис может быть определён по фигурным скобкам, окружающим выражение.
Если интерпретатор встречает знак доллара ($), он захватывает так
много символов, сколько возможно, чтобы сформировать правильное имя переменной. Если
вы хотите точно определить конец имени, заключайте имя переменной в фигурные скобки.
<?php
$juice = "apple";
echo "He drank some $juice juice.".PHP_EOL;
// Некорректно. 's' - верный символ для имени переменной, но переменная имеет имя $juice.
echo "He drank some juice made of $juices.";
// Корректно. Строго указан конец имени переменной с помощью скобок:
echo "He drank some juice made of ${juice}s.";
?>Результат выполнения данного примера:
He drank some apple juice. He drank some juice made of . He drank some juice made of apples.
Аналогично могут быть обработаны элемент массива (array) или свойство
объекта (object). В индексах массива закрывающая квадратная скобка
(]) обозначает конец определения индекса. Для свойств объекта
применяются те же правила, что и для простых переменных.
Пример #15 Пример простого синтаксиса
<?php
$juices = array("apple", "orange", "koolaid1" => "purple");
echo "He drank some $juices[0] juice.".PHP_EOL;
echo "He drank some $juices[1] juice.".PHP_EOL;
echo "He drank some $juices[koolaid1] juice.".PHP_EOL;
class people {
public $john = "John Smith";
public $jane = "Jane Smith";
public $robert = "Robert Paulsen";
public $smith = "Smith";
}
$people = new people();
echo "$people->john drank some $juices[0] juice.".PHP_EOL;
echo "$people->john then said hello to $people->jane.".PHP_EOL;
echo "$people->john's wife greeted $people->robert.".PHP_EOL;
echo "$people->robert greeted the two $people->smiths."; // Не сработает
?>Результат выполнения данного примера:
He drank some apple juice. He drank some orange juice. He drank some purple juice. John Smith drank some apple juice. John Smith then said hello to Jane Smith. John Smith's wife greeted Robert Paulsen. Robert Paulsen greeted the two .
В PHP 7.1.0 добавлена поддержка отрицательных числовых индексов.
Пример #16 Отрицательные числовые индексы
<?php
$string = 'string';
echo "Символ с индексом -2 равен $string[-2].", PHP_EOL;
$string[-3] = 'o';
echo "Изменение символа на позиции -3 на 'o' даёт следующую строку: $string.", PHP_EOL;
?>Результат выполнения данного примера:
Символ с индексом -2 равен n. Изменение символа на позиции -3 на 'o' даёт следующую строку: strong
Для чего-либо более сложного, используйте сложный синтаксис.
Он называется сложным не потому, что труден в понимании, а потому что позволяет использовать сложные выражения.
Любая скалярная переменная, элемент массива или свойство объекта, отображаемое в
строку, может быть представлена в строке этим синтаксисом. Выражение записывается так же,
как и вне строки, а затем заключается в { и }.
Поскольку { не может быть экранирован, этот синтаксис будет
распознаваться только когда $ следует непосредственно за {.
Используйте {\$, чтобы напечатать {$.
Несколько поясняющих примеров:
<?php
// Показываем все ошибки
error_reporting(E_ALL);
$great = 'здорово';
// Не работает, выводит: Это { здорово}
echo "Это { $great}";
// Работает, выводит: Это здорово
echo "Это {$great}";
// Работает
echo "Этот квадрат шириной {$square->width}00 сантиметров.";
// Работает, ключи, заключённые в кавычки, работают только с синтаксисом фигурных скобок
echo "Это работает: {$arr['key']}";
// Работает
echo "Это работает: {$arr[4][3]}";
// Это неверно по той же причине, что и $foo[bar] вне
// строки. Другими словами, это по-прежнему будет работать,
// но поскольку PHP сначала ищет константу foo, это вызовет
// ошибку уровня E_NOTICE (неопределённая константа).
echo "Это неправильно: {$arr[foo][3]}";
// Работает. При использовании многомерных массивов внутри
// строк всегда используйте фигурные скобки
echo "Это работает: {$arr['foo'][3]}";
// Работает.
echo "Это работает: " . $arr['foo'][3];
echo "Это тоже работает: {$obj->values[3]->name}";
echo "Это значение переменной по имени $name: {${$name}}";
echo "Это значение переменной по имени, которое возвращает функция getName(): {${getName()}}";
echo "Это значение переменной по имени, которое возвращает \$object->getName(): {${$object->getName()}}";
// Не работает, выводит: Это то, что возвращает getName(): {getName()}
echo "Это то, что возвращает getName(): {getName()}";
// Не работает, выводит: C:\folder\{fantastic}.txt
echo "C:\folder\{$great}.txt"
// Работает, выводит: C:\folder\fantastic.txt
echo "C:\\folder\\{$great}.txt"
?>С помощью этого синтаксиса также возможен доступ к свойствам объекта внутри строк.
<?php
class foo {
var $bar = 'I am bar.';
}
$foo = new foo();
$bar = 'bar';
$baz = array('foo', 'bar', 'baz', 'quux');
echo "{$foo->$bar}\n";
echo "{$foo->{$baz[1]}}\n";
?>Результат выполнения данного примера:
I am bar. I am bar.
Замечание:
Значение, к которому осуществляется доступ из функций, вызовов методов, статических переменных класса и констант класса внутри
{$}, будет интерпретироваться как имя переменной в области, в которой определена строка. Использование одинарных фигурных скобок ({}) не будет работать для доступа к значениям функций, методов, констант классов или статических переменных класса.
<?php
// Показываем все ошибки
error_reporting(E_ALL);
class beers {
const softdrink = 'rootbeer';
public static $ale = 'ipa';
}
$rootbeer = 'A & W';
$ipa = 'Alexander Keith\'s';
// Это работает, выводит: Я бы хотел A & W
echo "Я бы хотел {${beers::softdrink}}\n";
// Это тоже работает, выводит: Я бы хотел Alexander Keith's
echo "Я бы хотел {${beers::$ale}}\n";
?>Символы в строках можно использовать и модифицировать, определив их смещение относительно начала строки, начиная с нуля, в квадратных скобках после строки, например, $str[42]. Думайте о строке для этой цели, как о массиве символов. Если нужно получить или заменить более 1 символа, можно использовать функции substr() и substr_replace().
Замечание: Начиная с PHP 7.1.0, поддерживаются отрицательные значения смещения. Они задают смещение с конца строки. Ранее отрицательные смещение вызывали ошибку уровня
E_NOTICEпри чтении (возвращая пустую строку) либоE_WARNINGпри записи (оставляя строку без изменений).
Замечание: До PHP 8.0.0 для доступа к символу в строке (string) также можно было использовать фигурные скобки, например, $str{42}, для той же цели. Синтаксис фигурных скобок устарел в PHP 7.4.0 и больше не поддерживается в PHP 8.0.0.
Попытка записи в смещение за границами строки дополнит строку
пробелами до этого смещения. Нецелые типы будет преобразованы в целые.
Неверный тип смещения вызовет ошибку уровня E_WARNING.
Используется только первый символ присваемой строки.
Начиная с PHP 7.1.0, присвоение пустой строки вызовет фатальную ошибку. Ранее
в таком случае присваивался нулевой байт (NULL).
Строки в PHP внутренне представляют из себя массивы байт. Как результат, доступ или изменение строки по смещению небезопасно с точки зрения многобайтной кодировки, и должно выполняться только со строками в однобайтных кодировках, таких как, например, ISO-8859-1.
Замечание: Начиная с PHP 7.1.0, использование пустого индекса вызывает фатальную ошибку, ранее в подобном случае строка преобразовывалась в массив без предупреждения.
Пример #17 Несколько примеров строк
<?php
// Получение первого символа строки
$str = 'This is a test.';
$first = $str[0];
// Получение третьего символа строки
$third = $str[2];
// Получение последнего символа строки
$str = 'This is still a test.';
$last = $str[strlen($str)-1];
// Изменение последнего символа строки
$str = 'Look at the sea';
$str[strlen($str)-1] = 'e';
?>Смещение в строке должно задаваться либо целым числом, либо строкой, содержащей цифры, иначе будет выдаваться предупреждение.
Пример #18 Пример недопустимого смещения строки
<?php
$str = 'abc';
var_dump($str['1']);
var_dump(isset($str['1']));
var_dump($str['1.0']);
var_dump(isset($str['1.0']));
var_dump($str['x']);
var_dump(isset($str['x']));
var_dump($str['1x']);
var_dump(isset($str['1x']));
?>Результат выполнения данного примера:
string(1) "b" bool(true) Warning: Illegal string offset '1.0' in /tmp/t.php on line 7 string(1) "b" bool(false) Warning: Illegal string offset 'x' in /tmp/t.php on line 9 string(1) "a" bool(false) string(1) "b" bool(false)
Замечание:
Попытка доступа к переменным других типов (исключая массивы или объекты, реализующие определённые интерфейсы) с помощью
[]или{}молча вернётnull.
Замечание:
Доступ к символам в строковых литералах можно получить с помощью синтаксиса
[]или{}.
Замечание:
Доступ к символам в строковых литералах с использованием синтаксиса
{}объявлен устаревшим в PHP 7.4. Функционал удалён в PHP 8.0.
Строки могут быть объединены при помощи оператора '.' (точка). Обратите внимание, оператор сложения '+' здесь не работает. Дополнительную информацию смотрите в разделе Строковые операторы.
Для модификации строк существует множество полезных функций.
Основные функции описаны в разделе строковых функций, а для расширенного поиска и замены - функции Perl-совместимых регулярных выражений.
Также существуют функции для работы с URL, и функции шифрования/дешифрования строк (Sodium и Hash).
Наконец, смотрите также функции символьных типов.
Значение может быть преобразовано в строку с помощью приведения
(string), либо функции strval().
В выражениях, где необходима строка, преобразование происходит автоматически.
Это происходит, когда вы используете функции echo
или print, либо когда значение переменной сравнивается
со строкой. Прочтение разделов руководства Типы и Манипуляции с типами сделает
следующее более понятным. Смотрите также settype().
Значение bool true преобразуется в строку
"1", а значение false преобразуется в
"" (пустую строку). Это позволяет преобразовывать значения
в обе стороны - из булева типа в строковый и наоборот.
Целое (int) или число с плавающей точкой
(float) преобразуется в строку, представленную числом,
состоящим из его цифр (включая показатель степени для чисел с плавающей
точкой). Числа с плавающей точкой могут быть преобразованы с помощью
экспоненциального представления (4.1E+6).
Замечание:
Начиная с PHP 8.0.0, символом десятичной точки всегда является точка ("
."). До PHP 8.0.0 символ десятичной точки определялся в локали скрипта (категория LC_NUMERIC). Смотрите функцию setlocale()
Массивы всегда преобразуются в строку "Array",
так что вы не можете отобразить содержимое массива (array),
используя echo или print,
чтобы узнать, что он содержит. Чтобы просмотреть отдельный элемент, используйте
что-нибудь вроде echo $arr['foo']. Смотрите
ниже советы о том, как отобразить/просмотреть все содержимое.
Для преобразования переменной типа "Object" в тип string
используется магический метод
__toString.
Тип ресурс (resource) всегда преобразуется в строку (string) вида
"Resource id #1", где 1 является
номером ресурса привязанного к resource во время выполнения.
И хотя не стоит точно полагаться на эту строку, которая может быть изменена в будущем,
она всегда будет уникальной для текущего запуска скрипта (т.е. веб-запроса или
CLI-процесса) и не может использоваться повторно для другого ресурса.
Если вы хотите получить тип ресурса, используйте get_resource_type().
Значение null всегда преобразуется в пустую строку.
Как вы могли видеть выше, прямое преобразование в строку массивов, объектов или ресурсов не даёт никакой полезной информации о самих значениях, кроме их типов. Более подходящий способ вывода значений для отладки - использовать функции print_r() и var_dump().
Большинство значений в PHP может быть преобразовано в строку для постоянного хранения. Этот метод называется сериализацией и может быть выполнен при помощи функции serialize().
Строковый тип (string) в PHP реализован в виде массива
байт и целого числа, содержащего длину буфера. Он не содержит никакой
информации о способе преобразования этих байт в символы, предоставляя
эту задачу программисту. Нет никаких ограничений на содержимое строки,
например, байт со значением 0 ("NUL"-байт) может
располагаться где угодно (однако, стоит учитывать, что некоторые функции,
как сказано в этом руководстве, не являются "бинарно-безопасными",
т.е. они могут передавать строки библиотекам, которые игнорируют
данные после NUL-байта).
Данная природа строкового типа объясняет почему в PHP нет отдельного типа "byte" - строки играют эту роль. Функции, возвращающие нетекстовые данные - например, произвольный поток данных, считываемый из сетевого сокета - тем не менее возвращают строки.
Принимая во внимание тот факт, что PHP не диктует определённую кодировку
для строк, можно задать вопрос, как в таком случае кодируются строковые
литералы. Например, строка "á" эквивалентна
"\xE1" (ISO-8859-1), "\xC3\xA1"
(UTF-8, форма нормализации C), "\x61\xCC\x81"
(UTF-8, форма нормализации D) или какому-либо другому возможному
представлению? Ответом является следующее: строка будет закодирована тем
образом, которым она записана в файле скрипта. Таким образом, если
скрипт записан в кодировке ISO-8859-1, то и строка будет закодирована в
ISO-8859-1 и т.д. Однако, это правило не применяется при включённом
режиме Zend Multibyte: в этом случае скрипт может быть записан в любой
кодировке (которая указывается ясно или определяется автоматически),
а затем конвертируются в определённую внутреннюю кодировку, которая и будет
впоследствии использована для строковых литералов.
Учтите, что на кодировку скрипта (или на внутреннюю кодировку, если
включён режим Zend Multibyte) накладываются некоторые ограничения:
практически всегда данная кодировка должна быть надмножеством ASCII,
например, UTF-8 или ISO-8859-1. Учтите также, что кодировки, зависящие
от состояния, где одни и те же значения байт могут быть использованы
в начальном и не начальном состоянии сдвига, могут вызвать проблемы.
Разумеется, чтобы приносить пользу, строковые функции должны сделать некоторые предположения о кодировке строки. К несчастью, среди PHP-функций довольно большое разнообразие подходов к этому вопросу:
u).
В конечном счёте, написание корректных программ, работающих с Unicode, означает осторожное избегание функций, которые не работают с Unicode и, скорее всего, испортят данные, и использование вместо них корректных функций, обычно из модулей intl и mbstring. Однако, использование функций, способных работать с Unicode, является самым началом. Вне зависимости от тех функций, которые предоставляет язык, необходимо знать спецификацию самого Unicode. Например, если программа предполагает существование в языке только строчных и заглавных букв, то она делает большую ошибку.
В PHP, строка (string) считается числовой, если её можно интерпретировать как целое (int) число или как число с плавающей точкой (float).
Формально с PHP 8.0.0:
WHITESPACES \s*
LNUM [0-9]+
DNUM ([0-9]*)[\.]{LNUM}) | ({LNUM}[\.][0-9]*)
EXPONENT_DNUM (({LNUM} | {DNUM}) [eE][+-]? {LNUM})
INT_NUM_STRING {WHITESPACES} [+-]? {LNUM} {WHITESPACES}
FLOAT_NUM_STRING {WHITESPACES} [+-]? ({DNUM} | {EXPONENT_DNUM}) {WHITESPACES}
NUM_STRING ({INT_NUM_STRING} | {FLOAT_NUM_STRING})
В PHP также присутствует концепция префиксной числовой строки. Это строка, которая начинается как числовая и продолжается любыми другими символами.
Замечание:
Любая строка, содержащая букву
E(без учёта регистра), ограниченную цифрами, будет восприниматься как число, выраженное в научной нотации. Это может привести к неожиданным результатам.<?php
var_dump("0D1" == "000"); // false, "0D1" не является научной нотацией
var_dump("0E1" == "000"); // true, "0E1" - это 0 * (10 ^ 1) или 0
var_dump("2E1" == "020"); // true, "2E1" - это 2 * (10 ^ 1) или 20
?>
Когда строку необходимо использовать в качестве числа (например арифметические операции, декларация целочисленного типа, и т.д.), используется следующий алгоритм действий:
PHP_INT_MAX), то она приводится к типу int.
Иначе она приводится к типу float.
PHP_INT_MAX), то она приводится к типу int.
Иначе она приводится к типу float.
Также, в этом случае, выдаётся ошибка уровня E_WARNING.
До PHP 8.0.0, строка считалась числовой только в случае, если она начиналась с пробельных символов. Если она завершалась пробельными символами - она считалась префиксной числовой.
До PHP 8.0.0, когда строку необходимо использовать как число, использовался тот же алгоритм, что и описан выше, но с некоторыми отличиями:
E_NOTICE, а не E_WARNING.
E_WARNING,
а сама строка приводилась к числу 0.
E_NOTICE,
ни E_WARNING.
<?php
$foo = 1 + "10.5"; // $foo считается за число с плавающей точкой (11.5)
$foo = 1 + "-1.3e3"; // $foo считается за число с плавающей точкой (-1299)
$foo = 1 + "bob-1.3e3"; // TypeError начиная с PHP 8.0.0. В более ранних версиях $foo считалось за целое число (1)
$foo = 1 + "bob3"; // TypeError начиная с PHP 8.0.0, В более ранних версиях $foo считалось за целое число (1)
$foo = 1 + "10 Small Pigs"; // $foo - целое (11). В PHP 8.0.0 создаётся ошибка уровня E_WARNING, а в более ранних версиях уровня E_NOTICE
$foo = 4 + "10.2 Little Piggies"; // $foo - число с плавающей точкой (14.2). В PHP 8.0.0 создаётся ошибка уровня E_WARNING, а в более ранних версиях уровня E_NOTICE
$foo = "10.0 pigs " + 1; // $foo - число с плавающей точкой (11). В PHP 8.0.0 создаётся ошибка уровня E_WARNING, а в более ранних версиях уровня E_NOTICE
$foo = "10.0 pigs " + 1.0; // $foo - число с плавающей точкой (11). В PHP 8.0.0 создаётся ошибка уровня E_WARNING, а в более ранних версиях уровня E_NOTICE
?>На самом деле массив в PHP - это упорядоченное отображение, которое устанавливает соответствие между значением и ключом. Этот тип оптимизирован в нескольких направлениях, поэтому вы можете использовать его как собственно массив, список (вектор), хеш-таблицу (являющуюся реализацией карты), словарь, коллекцию, стек, очередь и, возможно, что-то ещё. Так как значением массива может быть другой массив PHP, можно также создавать деревья и многомерные массивы.
Объяснение этих структур данных выходит за рамки данного справочного руководства, но вы найдёте как минимум один пример по каждой из них. За дополнительной информацией вы можете обратиться к соответствующей литературе по этой обширной теме.
Массив (тип array) может быть создан языковой конструкцией array().
В качестве параметров она принимает любое количество разделённых запятыми пар
key => value
(ключ => значение).
array(
key => value,
key2 => value2,
key3 => value3,
...
)
Запятая после последнего элемента массива необязательна и может быть опущена.
Обычно это делается для однострочных массивов, то есть array(1, 2)
предпочтительней array(1, 2, ). Для многострочных массивов с другой
стороны обычно используется завершающая запятая, так как позволяет легче добавлять
новые элементы в конец массива.
Замечание:
Существует короткий синтаксис массива, который заменяет
array()на[].
Пример #1 Простой массив
<?php
$array = array(
"foo" => "bar",
"bar" => "foo",
);
// Использование синтаксиса короткого массива
$array = [
"foo" => "bar",
"bar" => "foo",
];
?>key может быть либо типа int, либо типа string. value может быть любого типа.
Дополнительно с ключом key будут сделаны следующие преобразования:
+) будут преобразованы к типу int.
Например, ключ со значением "8" будет в действительности сохранён со
значением 8. С другой стороны, значение "08" не
будет преобразовано, так как оно не является корректным десятичным целым.
8.7 будет в действительности сохранён со значением 8.
true будет сохранён со значением
1 и ключ со значением false будет сохранён со
значением 0.
null будет в действительности сохранён со значением
"".
Недопустимый тип смещения (Illegal offset type).
Если несколько элементов в объявлении массива используют одинаковый ключ, то только последний будет использоваться, а все другие будут перезаписаны.
Пример #2 Пример преобразования типов и перезаписи элементов
<?php
$array = array(
1 => "a",
"1" => "b",
1.5 => "c",
true => "d",
);
var_dump($array);
?>Результат выполнения данного примера:
array(1) {
[1]=>
string(1) "d"
}
Так как все ключи в вышеприведённом примере преобразуются к 1,
значение будет перезаписано на каждый новый элемент и останется только последнее
присвоенное значение "d".
Массивы в PHP могут содержать ключи типов int и string одновременно, так как PHP не делает различия между индексированными и ассоциативными массивами.
Пример #3 Смешанные ключи типов int и string
<?php
$array = array(
"foo" => "bar",
"bar" => "foo",
100 => -100,
-100 => 100,
);
var_dump($array);
?>Результат выполнения данного примера:
array(4) {
["foo"]=>
string(3) "bar"
["bar"]=>
string(3) "foo"
[100]=>
int(-100)
[-100]=>
int(100)
}
Параметр key является необязательным. Если он не указан, PHP будет использовать предыдущее наибольшее значение ключа типа int, увеличенное на 1.
Пример #4 Индексированные массивы без ключа
<?php
$array = array("foo", "bar", "hallo", "world");
var_dump($array);
?>Результат выполнения данного примера:
array(4) {
[0]=>
string(3) "foo"
[1]=>
string(3) "bar"
[2]=>
string(5) "hallo"
[3]=>
string(5) "world"
}
Возможно указать ключ только для некоторых элементов и пропустить для других:
Пример #5 Ключи для некоторых элементов
<?php
$array = array(
"a",
"b",
6 => "c",
"d",
);
var_dump($array);
?>Результат выполнения данного примера:
array(4) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
[6]=>
string(1) "c"
[7]=>
string(1) "d"
}
Как вы видите последнее значение "d" было присвоено ключу
7. Это произошло потому, что самое большое значение ключа целого
типа перед этим было 6.
Пример #6 Расширенный пример преобразования типов и перезаписи элементов
<?php
$array = array(
1 => 'a',
'1' => 'b', // значение "b" перезапишет значение "a"
1.5 => 'c', // значение "c" перезапишет значение "b"
-1 => 'd',
'01' => 'e', // поскольку это не целочисленная строка, она НЕ перезапишет ключ для 1
'1.5' => 'f', // поскольку это не целочисленная строка, она НЕ перезапишет ключ для 1
true => 'g', // значение "g" перезапишет значение "c"
false => 'h',
'' => 'i',
null => 'j', // значение "j" перезапишет значение "i"
'k', // значение "k" присваивается ключу 2. Потому что самый большой целочисленный ключ до этого был 1
2 => 'l', // значение "l" перезапишет значение "k"
);
var_dump($array);
?>Результат выполнения данного примера:
array(7) {
[1]=>
string(1) "g"
[-1]=>
string(1) "d"
["01"]=>
string(1) "e"
["1.5"]=>
string(1) "f"
[0]=>
string(1) "h"
[""]=>
string(1) "j"
[2]=>
string(1) "l"
}
Этот пример включает все вариации преобразования ключей и перезаписи элементов
Доступ к элементам массива может быть осуществлён с помощью синтаксиса array[key].
Пример #7 Доступ к элементам массива
<?php
$array = array(
"foo" => "bar",
42 => 24,
"multi" => array(
"dimensional" => array(
"array" => "foo"
)
)
);
var_dump($array["foo"]);
var_dump($array[42]);
var_dump($array["multi"]["dimensional"]["array"]);
?>Результат выполнения данного примера:
string(3) "bar" int(24) string(3) "foo"
Замечание:
До PHP 8.0.0 квадратные и фигурные скобки могли использоваться взаимозаменяемо для доступа к элементам массива (например, в примере выше
$array[42]и$array{42}делали то же самое). Синтаксис фигурных скобок устарел в PHP 7.4.0 и больше не поддерживается в PHP 8.0.0.
Пример #8 Разыменование массива
<?php
function getArray() {
return array(1, 2, 3);
}
$secondElement = getArray()[1];
?>Замечание:
Попытка доступа к неопределённому ключу в массиве - это то же самое, что и попытка доступа к любой другой неопределённой переменной: будет сгенерирована ошибка уровня
E_WARNING(ошибка уровняE_NOTICEдо PHP 8.0.0), и результат будетnull.
Замечание:
Попытка разыменовать не массив, а скалярное значение, не являющееся строкой (string), отдаст
null, в то время как разыменовывание строки (string) трактует её как индексированный массив. При такой попытке до PHP 7.4.0 не выдаётся сообщение об ошибке. Начиная с PHP 7.4.0, выдаётся ошибкаE_NOTICE; с PHP 8.0.0 выдаётся ошибкаE_WARNING.
Существующий массив может быть изменён путём явной установкой значений в нем.
Это выполняется присвоением значений массиву (array) с указанием в
скобках ключа. Кроме того, ключ можно опустить, в результате получится пустая пара скобок ([]).
$arr[key] = value;
$arr[] = value;
// key может быть int или string
// value может быть любым значением любого типа
Если массив $arr ещё не существует или для него
задано значение null или false, он будет создан.
Таким образом, это ещё один способ определить массив array. Однако такой
способ применять не рекомендуется, так как если переменная $arr
уже содержит некоторое значение (например, значение типа string из
переменной запроса), то это значение останется на месте и [] может на
самом деле означать доступ к символу в
строке. Лучше инициализировать переменную путём явного присваивания значения.
Замечание: Начиная с PHP 7.1.0, используя в оператор "пустой индекс" на строке, приведёт к фатальной ошибке. Ранее, в этом случае, строка молча преобразовывалась в массив.
Замечание: Начиная с PHP 8.1.0, создание нового массива с помощью значения
falseустарело. Создание нового массива изnullи неопределённого значения по-прежнему разрешено.
Для изменения определённого значения просто присвойте новое значение элементу, используя его ключ. Если вы хотите удалить пару ключ/значение, вам необходимо использовать функцию unset().
<?php
$arr = array(5 => 1, 12 => 2);
$arr[] = 56; // В этом месте скрипта это
// то же самое, что и $arr[13] = 56;
$arr["x"] = 42; // Это добавляет к массиву новый
// элемент с ключом "x"
unset($arr[5]); // Это удаляет элемент из массива
unset($arr); // Это удаляет массив полностью
?>Замечание:
Как уже говорилось выше, если ключ не был указан, то будет взят максимальный из существующих целочисленных (int) индексов, и новым ключом будет это максимальное значение (в крайнем случае 0) плюс 1. Если целочисленных (int) индексов ещё нет, то ключом будет
0(ноль).Учтите, что максимальное целое значение ключа не обязательно существует в массиве в данный момент. Оно могло просто существовать в массиве какое-то время, с тех пор как он был переиндексирован в последний раз. Следующий пример это иллюстрирует:
<?php
// Создаём простой массив.
$array = array(1, 2, 3, 4, 5);
print_r($array);
// Теперь удаляем каждый элемент, но сам массив оставляем нетронутым:
foreach ($array as $i => $value) {
unset($array[$i]);
}
print_r($array);
// Добавляем элемент (обратите внимание, что новым ключом будет 5, вместо 0).
$array[] = 6;
print_r($array);
// Переиндексация:
$array = array_values($array);
$array[] = 7;
print_r($array);
?>Результат выполнения данного примера:
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 ) Array ( ) Array ( [5] => 6 ) Array ( [0] => 6 [1] => 7 )
Массивы могут быть деструктурированы с помощью языковых конструкций [] (начиная с PHP 7.1.0)
или list(). Эти конструкции могут быть использованы для деструктуризации массива на отдельные переменные.
<?php
$source_array = ['foo', 'bar', 'baz'];
[$foo, $bar, $baz] = $source_array;
echo $foo; // выведет "foo"
echo $bar; // выведет "bar"
echo $baz; // выведет "baz"
?>Деструктуризация массива может быть использована в конструкции foreach для деструктуризации многомерного массива во время итерации по нему.
<?php
$source_array = [
[1, 'John'],
[2, 'Jane'],
];
foreach ($source_array as [$id, $name]) {
// логика работы с $id и $name
}
?>
Элементы массива будут игнорироваться, если переменная не указана.
Деструктуризация массива всегда начинается с индекса 0.
<?php
$source_array = ['foo', 'bar', 'baz'];
// Присваивание элементу с индексом 2 переменной $baz
[, , $baz] = $source_array;
echo $baz; // выведет "baz"
?>Начиная с PHP 7.1.0, ассоциативные массивы также могут быть деструктурированы. Это позволяет легче выбирать нужный элемент в массивах с числовым индексом, так как индекс может быть указан явно.
<?php
$source_array = ['foo' => 1, 'bar' => 2, 'baz' => 3];
// Присваивание элементу с индексом 'baz' переменной $three
['baz' => $three] = $source_array;
echo $three; // выведет 3
$source_array = ['foo', 'bar', 'baz'];
// Присваивание элементу с индексом 2 переменной $baz
[2 => $baz] = $source_array;
echo $baz; // выведет "baz"
?>Деструктуризация массива может быть использована для простой замены двух переменных местами.
<?php
$a = 1;
$b = 2;
[$b, $a] = [$a, $b];
echo $a; // выведет 2
echo $b; // выведет 1
?>Замечание:
Оператор
...не поддерживается в присваиваниях.
Замечание:
Попытка получить доступ к ключу массива, который не был определён, аналогична обращению к любой другой неопределённой переменной: будет выдано сообщение об ошибке уровня
E_WARNING(ошибка уровняE_NOTICEдо PHP 8.0.0), а результатом будетnull.
Для работы с массивами существует достаточное количество полезных функций. Смотрите раздел функции для работы с массивами.
Замечание:
Функция unset() позволяет удалять ключи массива. Обратите внимание, что массив НЕ будет переиндексирован. Если вы действительно хотите поведения в стиле "удалить и сдвинуть", можно переиндексировать массив используя array_values().
<?php
$a = array(1 => 'один', 2 => 'два', 3 => 'три');
unset($a[2]);
/* даст массив, представленный так:
$a = array(1 => 'один', 3 => 'три');
а НЕ так:
$a = array(1 => 'один', 2 => 'три');
*/
$b = array_values($a);
// Теперь $b это array(0 => 'один', 1 => 'три')
?>
Управляющая конструкция foreach существует специально для массивов. Она предоставляет возможность легко пройтись по массиву.
$foo[bar] неверно?
Всегда заключайте в кавычки строковый литерал в индексе ассоциативного массива.
К примеру, пишите $foo['bar'], а не
$foo[bar]. Но почему? Часто в старых скриптах можно встретить
следующий синтаксис:
<?php
$foo[bar] = 'враг';
echo $foo[bar];
// и т.д.
?>
Это неверно, хотя и работает. Причина в том, что этот код содержит неопределённую
константу (bar), а не строку ('bar' - обратите внимание
на кавычки). Это работает, потому что PHP автоматически преобразует
"голую строку" (не заключённую в кавычки строку,
которая не соответствует ни одному из известных символов языка) в строку
со значением этой "голой строки". Например, если константа с именем bar
не определена, то PHP заменит bar на
строку 'bar' и использует её.
Резервный вариант для обработки неопределённой константы как пустой строки вызывает ошибку уровня E_NOTICE.
Начиная с PHP 7.2.0 поведение объявлено устаревшим и вызывает ошибку уровня E_WARNING.
Начиная с PHP 8.0.0, удалено и выбрасывает исключение Error.
Замечание: Это не означает, что нужно всегда заключать ключ в кавычки. Нет необходимости заключать в кавычки константы или переменные, поскольку это помешает PHP обрабатывать их.
<?php
error_reporting(E_ALL);
ini_set('display_errors', true);
ini_set('html_errors', false);
// Простой массив:
$array = array(1, 2);
$count = count($array);
for ($i = 0; $i < $count; $i++) {
echo "\nПроверяем $i: \n";
echo "Плохо: " . $array['$i'] . "\n";
echo "Хорошо: " . $array[$i] . "\n";
echo "Плохо: {$array['$i']}\n";
echo "Хорошо: {$array[$i]}\n";
}
?>Результат выполнения данного примера:
Проверяем 0: Notice: Undefined index: $i in /path/to/script.html on line 9 Плохо: Хорошо: 1 Notice: Undefined index: $i in /path/to/script.html on line 11 Плохо: Хорошо: 1 Проверяем 1: Notice: Undefined index: $i in /path/to/script.html on line 9 Плохо: Хорошо: 2 Notice: Undefined index: $i in /path/to/script.html on line 11 Плохо: Хорошо: 2
Дополнительные примеры, демонстрирующие этот факт:
<?php
// Показываем все ошибки
error_reporting(E_ALL);
$arr = array('fruit' => 'apple', 'veggie' => 'carrot');
// Верно
print $arr['fruit']; // apple
print $arr['veggie']; // carrot
// Неверно. Это работает, но из-за неопределённой константы с
// именем fruit также вызывает ошибку PHP уровня E_NOTICE
//
// Notice: Use of undefined constant fruit - assumed 'fruit' in...
print $arr[fruit]; // apple
// Давайте определим константу, чтобы продемонстрировать, что
// происходит. Мы присвоим константе с именем fruit значение 'veggie'.
define('fruit', 'veggie');
// Теперь обратите внимание на разницу
print $arr['fruit']; // apple
print $arr[fruit]; // carrot
// Внутри строки это нормально. Внутри строк константы не
// рассматриваются, так что ошибки E_NOTICE здесь не произойдёт
print "Hello $arr[fruit]"; // Hello apple
// С одним исключением: фигурные скобки вокруг массивов внутри
// строк позволяют константам там находиться
print "Hello {$arr[fruit]}"; // Hello carrot
print "Hello {$arr['fruit']}"; // Hello apple
// Это не будет работать и вызовет ошибку обработки, такую как:
// Parse error: parse error, expecting T_STRING' or T_VARIABLE' or T_NUM_STRING'
// Это, конечно, также действует и с суперглобальными переменными в строках
print "Hello $arr['fruit']";
print "Hello $_GET['foo']";
// Ещё одна возможность - конкатенация
print "Hello " . $arr['fruit']; // Hello apple
?>
Если вы переведёте error_reporting
в режим отображения ошибок уровня
E_NOTICE (например, такой как
E_ALL), вы сразу увидите эти ошибки. По
умолчанию
error_reporting установлена их не отображать.
Как указано в разделе синтаксис,
внутри квадратных скобок ('['
и ']') должно быть выражение. Это означает, что можно писать вот так:
<?php
echo $arr[somefunc($bar)];
?>Это пример использования возвращаемого функцией значения в качестве индекса массива. PHP известны также и константы:
<?php
$error_descriptions[E_ERROR] = "Произошла фатальная ошибка";
$error_descriptions[E_WARNING] = "PHP сообщает о предупреждении";
$error_descriptions[E_NOTICE] = "Это лишь неофициальное замечание";
?>
Обратите внимание, что E_ERROR - это такой же
верный идентификатор, как и bar в первом примере.
Но последний пример по сути эквивалентен такой записи:
<?php
$error_descriptions[1] = "Произошла фатальная ошибка";
$error_descriptions[2] = "PHP сообщает о предупреждении";
$error_descriptions[8] = "Это лишь неофициальное замечание";
?>
поскольку E_ERROR соответствует 1 и т.д.
Когда-нибудь в будущем команда разработчиков PHP возможно пожелает
добавить ещё одну константу или ключевое слово, либо константа из
другого кода может вмешаться и тогда у вас могут
возникнуть проблемы. Например, вы уже не можете использовать таким
образом слова empty и
default, поскольку они являются
зарезервированными ключевыми словами.
Замечание: Повторим, внутри строки (string), заключённой в двойные кавычки, корректно не окружать индексы массива кавычками, поэтому
"$foo[bar]"является верной записью. Более подробно почему - смотрите вышеприведённые примеры, а также раздел по обработке переменных в строках.
Для любого из типов int, float,
string, bool и resource,
преобразование значения в массив даёт результатом массив с
одним элементом (с индексом 0), являющимся скалярным значением, с
которого вы начали. Другими словами, (array)$scalarValue
- это точно то же самое, что и array($scalarValue).
Если вы преобразуете в массив объект (object), вы
получите в качестве элементов массива свойства (переменные-члены)
этого объекта. Ключами будут имена переменных-членов, с некоторыми примечательными
исключениями: целочисленные свойства станут недоступны;
к закрытым полям класса (private) спереди будет дописано имя класса;
к защищённым полям класса (protected) спереди будет добавлен символ '*'.
Эти добавленные значения с обоих сторон также имеют NUL байты.
Неинициализированные типизированные свойства
автоматически отбрасываются.
<?php
class A {
private $B;
protected $C;
public $D;
function __construct()
{
$this->{1} = null;
}
}
var_export((array) new A());
?>Результат выполнения данного примера:
array ( '' . "\0" . 'A' . "\0" . 'B' => NULL, '' . "\0" . '*' . "\0" . 'C' => NULL, 'D' => NULL, 1 => NULL, )
Это может вызвать несколько неожиданное поведение:
<?php
class A {
private $A; // Это станет '\0A\0A'
}
class B extends A {
private $A; // Это станет '\0B\0A'
public $AA; // Это станет 'AA'
}
var_dump((array) new B());
?>Результат выполнения данного примера:
array(3) {
["BA"]=>
NULL
["AA"]=>
NULL
["AA"]=>
NULL
}
Вышеприведённый код покажет 2 ключа с именем 'AA', хотя один из них на самом деле имеет имя '\0A\0A'.
Если вы преобразуете в массив значение null, вы получите
пустой массив.
Массивы можно сравнивать при помощи функции array_diff() и операторов массивов.
Массив с префиксом ... будет распакован во время определения массива.
Только массивы и объекты, которые реализуют интерфейс Traversable, могут быть распакованы.
Распаковка массива с помощью ... доступна, начиная с PHP 7.4.0.
Массив можно распаковывать несколько раз и добавлять обычные элементы до или после оператора ...:
Пример #9 Простая распаковка массива
<?php
// Использование короткого синтаксиса массива.
// Также работает с синтаксисом array().
$arr1 = [1, 2, 3];
$arr2 = [...$arr1]; // [1, 2, 3]
$arr3 = [0, ...$arr1]; // [0, 1, 2, 3]
$arr4 = [...$arr1, ...$arr2, 111]; // [1, 2, 3, 1, 2, 3, 111]
$arr5 = [...$arr1, ...$arr1]; // [1, 2, 3, 1, 2, 3]
function getArr() {
return ['a', 'b'];
}
$arr6 = [...getArr(), 'c' => 'd']; // ['a', 'b', 'c' => 'd']
?>
Распаковка массива с помощью оператора ... следует семантике функции array_merge().
То есть более поздние строковые ключи перезаписывают более ранние, а целочисленные ключи перенумеровываются:
Пример #10 Распаковка массива с дублирующим ключом
<?php
// строковый ключ
$arr1 = ["a" => 1];
$arr2 = ["a" => 2];
$arr3 = ["a" => 0, ...$arr1, ...$arr2];
var_dump($arr3); // ["a" => 2]
// целочисленный ключ
$arr4 = [1, 2, 3];
$arr5 = [4, 5, 6];
$arr6 = [...$arr4, ...$arr5];
var_dump($arr6); // [1, 2, 3, 4, 5, 6]
// Который [0 => 1, 1 => 2, 2 => 3, 3 => 4, 4 => 5, 5 => 6]
// где исходные целочисленные ключи не были сохранены.
?>Замечание:
Ключи, которые не являются ни целыми числами, ни строками, вызывают ошибку TypeError. Такие ключи могут быть сгенерированы только объектом Traversable.
Замечание:
До PHP 8.1 распаковка массива со строковым ключом не поддерживалась:
<?php
$arr1 = [1, 2, 3];
$arr2 = ['a' => 4];
$arr3 = [...$arr1, ...$arr2];
// Ошибка: невозможно распаковать массив со строковыми ключами в example.php:5
$arr4 = [1, 2, 3];
$arr5 = [4, 5];
$arr6 = [...$arr4, ...$arr5]; // работает. [1, 2, 3, 4, 5]
?>
Тип массив в PHP является очень гибким, вот несколько примеров:
<?php
// это
$a = array( 'color' => 'red',
'taste' => 'sweet',
'shape' => 'round',
'name' => 'apple',
4 // ключом будет 0
);
$b = array('a', 'b', 'c');
// . . .полностью соответствует
$a = array();
$a['color'] = 'red';
$a['taste'] = 'sweet';
$a['shape'] = 'round';
$a['name'] = 'apple';
$a[] = 4; // ключом будет 0
$b = array();
$b[] = 'a';
$b[] = 'b';
$b[] = 'c';
// после выполнения этого кода, $a будет массивом
// array('color' => 'red', 'taste' => 'sweet', 'shape' => 'round',
// 'name' => 'apple', 0 => 4), а $b будет
// array(0 => 'a', 1 => 'b', 2 => 'c'), или просто array('a', 'b', 'c').
?>Пример #11 Использование array()
<?php
// Массив как карта (свойств)
$map = array( 'version' => 4,
'OS' => 'Linux',
'lang' => 'english',
'short_tags' => true
);
// исключительно числовые ключи
$array = array( 7,
8,
0,
156,
-10
);
// это то же самое, что и array(0 => 7, 1 => 8, ...)
$switching = array( 10, // ключ = 0
5 => 6,
3 => 7,
'a' => 4,
11, // ключ = 6 (максимальным числовым индексом было 5)
'8' => 2, // ключ = 8 (число!)
'02' => 77, // ключ = '02'
0 => 12 // значение 10 будет перезаписано на 12
);
// пустой массив
$empty = array();
?>Пример #12 Коллекция
<?php
$colors = array('red', 'blue', 'green', 'yellow');
foreach ($colors as $color) {
echo "Вам нравится $color?\n";
}
?>Результат выполнения данного примера:
Вам нравится red? Вам нравится blue? Вам нравится green? Вам нравится yellow?
Изменение значений массива напрямую возможно путём передачи их по ссылке.
Пример #13 Изменение элемента в цикле
<?php
foreach ($colors as &$color) {
$color = strtoupper($color);
}
unset($color); /* это нужно для того, чтобы последующие записи в
$color не меняли последний элемент массива */
print_r($colors);
?>Результат выполнения данного примера:
Array
(
[0] => RED
[1] => BLUE
[2] => GREEN
[3] => YELLOW
)
Следующий пример создаёт массив, начинающийся с единицы.
Пример #14 Индекс, начинающийся с единицы
<?php
$firstquarter = array(1 => 'Январь', 'Февраль', 'Март');
print_r($firstquarter);
?>Результат выполнения данного примера:
Array
(
[1] => 'Январь'
[2] => 'Февраль'
[3] => 'Март'
)
Пример #15 Заполнение массива
<?php
// заполняем массив всеми элементами из директории
$handle = opendir('.');
while (false !== ($file = readdir($handle))) {
$files[] = $file;
}
closedir($handle);
?>Массивы упорядочены. Вы можете изменять порядок элементов, используя различные функции сортировки. Для дополнительной информации смотрите раздел функции для работы с массивами. Вы можете подсчитать количество элементов в массиве с помощью функции count().
Пример #16 Сортировка массива
<?php
sort($files);
print_r($files);
?>Поскольку значение массива может быть чем угодно, им также может быть другой массив. Таким образом вы можете создавать рекурсивные и многомерные массивы.
Пример #17 Рекурсивные и многомерные массивы
<?php
$fruits = array ( "fruits" => array ( "a" => "апельсин",
"b" => "банан",
"c" => "яблоко"
),
"numbers" => array ( 1,
2,
3,
4,
5,
6
),
"holes" => array ( "первая",
5 => "вторая",
"третья"
)
);
// Несколько примеров доступа к значениям предыдущего массива
echo $fruits["holes"][5]; // напечатает "вторая"
echo $fruits["fruits"]["a"]; // напечатает "апельсин"
unset($fruits["holes"][0]); // удалит "первая"
// Создаст новый многомерный массив
$juices["apple"]["green"] = "good";
?>Обратите внимание, что при присваивании массива всегда происходит копирование значения. Чтобы скопировать массив по ссылке, вам нужно использовать оператор ссылки.
<?php
$arr1 = array(2, 3);
$arr2 = $arr1;
$arr2[] = 4; // $arr2 изменился,
// $arr1 всё ещё array(2, 3)
$arr3 = &$arr1;
$arr3[] = 4; // теперь $arr1 и $arr3 одинаковы
?>
Для создания нового объекта, используйте выражение
new, создающее в переменной экземпляр класса:
<?php
class foo
{
function do_foo()
{
echo "Код foo.";
}
}
$bar = new foo;
$bar->do_foo();
?>Полное рассмотрение производится в разделе Классы и Объекты.
Если object преобразуется в object, объект не изменится.
Если значение другого типа преобразуется в
object, создаётся новый экземпляр встроенного класса stdClass.
Если значение было null, новый экземпляр будет пустым.
Массивы преобразуются в object с именами полей, названными согласно ключам
массива и соответствующими им значениям.
Обратите внимание, что в этом случае до PHP
7.2.0 числовые ключи не будут
доступны, пока не проитерировать объект.
<?php
$obj = (object) array('1' => 'foo');
var_dump(isset($obj->{'1'})); // выводит 'bool(true)', начиная с PHP 7.2.0; 'bool(false)' ранее
var_dump(key($obj)); // выводит 'string(1) "1"', начиная с PHP 7.2.0; 'int(1)' ранее
?>
При преобразовании любого другого значения, оно будет помещено в
поле с именем scalar соответствующему типу.
<?php
$obj = (object) 'привет';
echo $obj->scalar; // выведет 'привет'
?>(PHP 8 >= 8.1.0)
Перечисления - это ограничивающий слой над классами и константами классов, предназначенный для предоставления способа определения закрытого набора возможных значений для типа.
<?php
enum Suit
{
case Hearts;
case Diamonds;
case Clubs;
case Spades;
}
function do_stuff(Suit $s)
{
// ...
}
do_stuff(Suit::Spades);
?>Полное описание смотрите в главе о перечислениях.
Если перечисление (enum) преобразуется в объект (object),
оно не изменяется. Если перечисление (enum) преобразуется в массив (array),
то создаётся массив с одним ключом name (для простых перечислений)
или массив с двумя ключами name и value (для типизированных перечислений).
Все остальные приведения типов приведут к ошибке.
Resource - это специальная переменная, содержащая ссылку на внешний ресурс. Ресурсы создаются и используются специальными функциями. Полный перечень этих функций и соответствующих типов ресурсов (resource) смотрите в приложении.
Смотрите также описание функции get_resource_type().
Поскольку тип resource содержит специальные указатели на открытые файлы, соединения с базой данных, области изображения и тому подобное, преобразование в этот тип не имеет смысла.
Благодаря системе подсчёта ссылок, введённой в Zend Engine, определение отсутствия ссылок на ресурс происходит автоматически, после чего он освобождается сборщиком мусора. Поэтому очень редко требуется освобождать память вручную.
Замечание: Постоянные соединения с базами данных являются исключением из этого правила. Они не уничтожаются сборщиком мусора. Подробнее смотрите в разделе о постоянных соединениях.
Callback-функции могут быть обозначены объявлением типа callable.
Некоторые функции, такие как call_user_func() или usort(), принимают определённые пользователем callback-функции в качестве параметра. Callback-функции могут быть как простыми функциями, так и методами объектов, включая статические методы классов.
В PHP функции передаются по имени в виде строки. Можно использовать любые встроенные, либо созданные пользователем функции, за исключением конструкций языка, таких как: array(), echo, empty(), eval(), exit(), isset(), list(), print или unset().
Метод созданного объекта (object) передаётся как массив, содержащий объект по индексу 0 и имя метода по индексу 1. Доступ к закрытым и защищённым методам разрешён изнутри класса.
Статические методы класса также могут быть вызваны без создания экземпляра
объекта класса путём передачи имени класса вместо объекта в элементе массива с
индексом 0 или выполнения 'ClassName::methodName'.
Помимо обычных пользовательских функций, в качестве callback-функции можно передавать анонимные функции и стрелочные функции.
Замечание:
Начиная с PHP 8.1.0, у Callback-функций как объектов первого класса та же семантика, что и у этого метода.
Как правило, любой объект, реализующий __invoke(), также может быть передан в параметр callback.
Пример #1 Пример callback-функции
<?php
// Пример callback-функции
function my_callback_function() {
echo 'Привет, мир!';
}
// Пример callback-метода
class MyClass {
static function myCallbackMethod() {
echo 'Привет, мир!';
}
}
// Тип 1: Простой callback
call_user_func('my_callback_function');
// Тип 2: Вызов статического метода класса
call_user_func(array('MyClass', 'myCallbackMethod'));
// Тип 3: Вызов метода класса
$obj = new MyClass();
call_user_func(array($obj, 'myCallbackMethod'));
// Тип 4: Вызов статического метода класса
call_user_func('MyClass::myCallbackMethod');
// Тип 5: Вызов относительного статического метода
class A {
public static function who() {
echo "A\n";
}
}
class B extends A {
public static function who() {
echo "B\n";
}
}
call_user_func(array('B', 'parent::who')); // A, устарело, начиная с PHP 8.2.0
// Тип 6: Объекты, реализующие __invoke, могут быть использованы как callback
class C {
public function __invoke($name) {
echo 'Привет ', $name, "\n";
}
}
$c = new C();
call_user_func($c, 'PHP!');
?>
Пример #2 Пример callback-функции с использованием замыкания
<?php
// Наше замыкание
$double = function($a) {
return $a * 2;
};
// Диапазон чисел
$numbers = range(1, 5);
// Использование замыкания в качестве callback-функции
// для удвоения каждого элемента в нашем диапазоне
$new_numbers = array_map($double, $numbers);
print implode(' ', $new_numbers);
?>Результат выполнения данного примера:
2 4 6 8 10
Замечание:
Callback-функции, зарегистрированные такими функциями как call_user_func() и call_user_func_array(), не будут вызваны при наличии не пойманного исключения, брошенного в предыдущей callback-функции.
Тип mixed принимает любое значение.
Он эквивалентен объединённому типу
object|resource|array|string|float|int|bool|null.
Доступно, начиная с PHP 8.0.0.
mixed - это, говоря языком теории типов, высший тип. Это означает, что все остальные типы являются его подтипами.
void - это объявление типа только для возвращаемого значения, указывающее на то, что функция не возвращает значение, но функция всё равно может завершиться. Поэтому он не может быть частью объявления объединённых типов. Доступно, начиная с PHP 7.1.0.
Замечание: Даже если тип возвращаемого значения функции void, она всё равно вернёт значение и это значение всегда будет
null.
never - это объявление типа только для возвращаемого значения, указывающий на то, что функция не завершается. Это означает, что она либо вызывает exit(), либо выбрасывает исключение, либо является бесконечным циклом. Поэтому он не может быть частью объявления объединённых типов. Доступно, начиная с PHP 8.1.0.
never - это, говоря языком теории типов, нижний тип. Это означает, что он является подтипом любого другого типа и может заменить любой другой тип возвращаемого значения при наследовании.
Эти объявления типов можно использовать только внутри классов.
Значение должно быть instanceof того же класса,
что и класс, в котором используется объявление типа.
Значение должно быть instanceof родителем класса,
в котором используется объявление типа.
static - это тип только для возвращаемого значения,
который требует, чтобы возвращаемое значение было instanceof того же класса,
что и класс, в котором вызывается метод.
Доступен, начиная с PHP 8.0.0.
Литералы - это типы, которые проверяют не только тип значения, но и само значение. PHP поддерживает два литерала: false, начиная с PHP 8.0.0 и true, начиная с PHP 8.2.0.
До PHP 8.2.0 тип false можно было использовать только как часть объединённого типа.
Замечание: Невозможно определить пользовательские литералы. Вместо этого используйте перечисления.
Iterable - это встроенный во время компиляции псевдотип для array|Traversable.
С момента своего появления в PHP 7.1.0 и до PHP 8.2.0, тип iterable был встроенным псевдо-типом,
который действовал как вышеупомянутый псевдотип и мог быть использован в качестве объявления типа.
Тип iterable можно использовать в foreach и с конструкцией yield from
внутри генератора.
Замечание:
Функции, объявляющие iterable в качестве типа возвращаемого значения, также могут быть генераторами.
Пример #1 Пример использования типа возвращаемого значения iterable
<?php
function gen(): iterable {
yield 1;
yield 2;
yield 3;
}
?>
Объявления типов могут использоваться для аргументов функций, возвращаемых значений и, начиная с PHP 7.4.0, для свойств класса. Они используются во время исполнения для проверки, что значение имеет точно тот тип, который для них указан. В противном случае будет выброшено исключение TypeError.
Все типы, которые поддерживает PHP, за исключением ресурсов (resource), могут быть использованы в объявлении типов в пользовательском коде. На этой странице приведён журнал изменений доступности различных типов и документация по их использованию в объявлениях типов.
Замечание:
Когда класс реализует метод интерфейса или повторно реализует метод, который уже был определён родительским классом, он должен быть совместим с вышеупомянутым определением. Метод является совместимым, если он следует правилам вариантности.
| Версия | Описание |
|---|---|
| 8.2.0 | Добавлена поддержка типов DNF. |
| 8.2.0 | Добавлена поддержка типа true. |
| 8.2.0 | Типы null и false теперь можно использовать автономно. |
| 8.1.0 | Добавлена поддержка пересечений типов. |
| 8.1.0 | Возврат по ссылке из функции с типом возвращаемого значения void устарел. |
| 8.1.0 | Добавлена поддержка типа возвращаемого значения never. |
| 8.0.0 | Добавлена поддержка типа возвращаемого значения mixed. |
| 8.0.0 | Добавлена поддержка типа возвращаемого значения static. |
| 8.0.0 | Добавлена поддержка объединения типов. |
| 7.4.0 | Добавлена поддержка типизации свойств классов. |
| 7.2.0 | Добавлена поддержка типа возвращаемого значения object. |
| 7.1.0 | Добавлена поддержка типа возвращаемого значения iterable. |
| 7.1.0 | Добавлена поддержка типа возвращаемого значения void. |
| 7.1.0 | Добавлена поддержка типа возвращаемого значения nullable. |
У основных типов прямолинейное поведение с некоторыми незначительными оговорками, которые описаны в этом разделе.
Псевдонимы имён для скалярных типов (bool, int, float, string) не поддерживаются.
Вместо этого они рассматриваются как имена классов или интерфейсов.
К примеру, при использовании в качестве типа boolean, ожидается,
что значение представляет собой instanceof класса или интерфейса
boolean, а не значение типа bool:
<?php
function test(boolean $param) {}
test(true);
?>Результат выполнения данного примера в PHP 8:
Warning: "boolean" will be interpreted as a class name. Did you mean "bool"? Write "\boolean" to suppress this warning in /in/9YrUX on line 2
Fatal error: Uncaught TypeError: test(): Argument #1 ($param) must be of type boolean, bool given, called in - on line 3 and defined in -:2
Stack trace:
#0 -(3): test(true)
#1 {main}
thrown in - on line 2
Замечание:
Возврат по ссылке из функции void устарел начиная с PHP 8.1.0, поскольку такая функция противоречива. Ранее при её вызове выдавалась ошибка уровня
E_NOTICE: Только ссылки на переменные должны возвращаться по ссылке.<?php
function &test(): void {}
?>
Этот тип не может использоваться в качестве объявления типа свойства класса.
Замечание: Невозможно указать сигнатуру функции.
Если у параметра, передаваемого по ссылке, объявляется тип возвращаемого значения, тип переменной проверяется только при входе в функцию, в начале вызова, но не при возврате функции. Это значит, что функция может изменить тип ссылки на переменную.
Пример #1 Типизированные параметры, передаваемые по ссылке
<?php
function array_baz(array &$param)
{
$param = 1;
}
$var = [];
array_baz($var);
var_dump($var);
array_baz($var);
?>Результатом выполнения данного примера будет что-то подобное:
int(1)
Fatal error: Uncaught TypeError: array_baz(): Argument #1 ($param) must be of type array, int given, called in - on line 9 and defined in -:2
Stack trace:
#0 -(9): array_baz(1)
#1 {main}
thrown in - on line 2
На объявления составных типов распространяется пара ограничений и во время компиляции будет выполняться проверка избыточности для предотвращения простых ошибок.
До PHP 8.2.0 и появления типов DNF было невозможно комбинировать пересечение типов с объединением типов.
Невозможно объединить два типа false и true с помощью объединения типов. Вместо этого используйте bool.
До PHP 8.2.0, поскольку false и null не могли использоваться как отдельные типы,
объединение типов, состоящее только из этих типов, было недопустимо.
К ним относятся следующие типы: false, false|null
и ?false.
Объявление одного базового типа может быть помечено как nullable путём префиксации типа
вопросительным знаком (?).
Таким образом, ?T и T|null идентичны.
Замечание: Этот синтаксис поддерживается начиная с PHP 7.1.0 и предшествует поддержке объединения типов.
Замечание:
Также можно добиться nullable аргументов, указав
nullзначением по умолчанию. Это не рекомендуется, поскольку если значение по умолчанию будет изменено в дочернем классе, возникнет нарушение совместимости типов, так как в объявление типа нужно будет добавить тип null.Пример #2 Старый способ указания nullable аргументов
<?php
class C {}
function f(C $c = null) {
var_dump($c);
}
f(new C);
f(null);
?>Результат выполнения данного примера:
object(C)#1 (0) { } NULL
Чтобы отловить простые ошибки в объявлениях составных типов, избыточные типы, которые могут быть обнаружены без выполнения загрузки класса, приведут к ошибке времени компиляции. К ним относятся:
int|string|INT или Countable&Traversable&COUNTABLE
приведут к ошибке.
Замечание: Это не гарантирует, что тип является "минимальным", поскольку для этого пришлось бы загрузить все используемые типы классов.
Например, если A и B являются псевдонимами классов,
то A|B остаётся корректным объединением типов,
даже если его можно свести либо к A, либо к B.
Аналогично, если класс B extends A {}, то A|B также является
корректным объединением типов, даже если его можно свести к просто A.
<?php
function foo(): int|INT {} // Запрещено
function foo(): bool|false {} // Запрещено
function foo(): int&Traversable {} // Запрещено
function foo(): self&Traversable {} // Запрещено
use A as B;
function foo(): A|B {} // Запрещено ("use" является частью разрешения имён)
function foo(): A&B {} // Запрещено ("use" является частью разрешения имён)
class_alias('X', 'Y');
function foo(): X|Y {} // Разрешено (избыточность известна только во время выполнения)
function foo(): X&Y {} // Разрешено (избыточность известна только во время выполнения)
?>Пример #3 Пример объявления типа класса
<?php
class C {}
class D extends C {}
// Не наследует C.
class E {}
function f(C $c) {
echo get_class($c)."\n";
}
f(new C);
f(new D);
f(new E);
?>Результат выполнения данного примера в PHP 8:
C
D
Fatal error: Uncaught TypeError: f(): Argument #1 ($c) must be of type C, E given, called in /in/gLonb on line 14 and defined in /in/gLonb:8
Stack trace:
#0 -(14): f(Object(E))
#1 {main}
thrown in - on line 8
Пример #4 Пример объявления типа интерфейса
<?php
interface I { public function f(); }
class C implements I { public function f() {} }
// Не реализует I.
class E {}
function f(I $i) {
echo get_class($i)."\n";
}
f(new C);
f(new E);
?>Результат выполнения данного примера в PHP 8:
C
Fatal error: Uncaught TypeError: f(): Argument #1 ($i) must be of type I, E given, called in - on line 13 and defined in -:8
Stack trace:
#0 -(13): f(Object(E))
#1 {main}
thrown in - on line 8
Пример #5 Пример объявления типа возвращаемого значения
<?php
function sum($a, $b): float {
return $a + $b;
}
// Обратите внимание, что будет возвращено значение float.
var_dump(sum(1, 2));
?>Результат выполнения данного примера:
float(3)
Пример #6 Возвращение объекта
<?php
class C {}
function getC(): C {
return new C;
}
var_dump(getC());
?>Результат выполнения данного примера:
object(C)#1 (0) {
}
Пример #7 Объявление аргумента с типом Nullable
<?php
class C {}
function f(?C $c) {
var_dump($c);
}
f(new C);
f(null);
?>Результат выполнения данного примера:
object(C)#1 (0) {
}
NULL
Пример #8 Объявление типа возвращаемого значения Nullable
<?php
function get_item(): ?string {
if (isset($_GET['item'])) {
return $_GET['item'];
} else {
return null;
}
}
?>Пример #9 Объявление типа свойства класса
<?php
class User {
public static string $foo = 'foo';
public int $id;
public string $username;
public function __construct(int $id, string $username) {
$this->id = $id;
$this->username = $username;
}
}
?>По умолчанию, PHP будет преобразовывать значения неправильного типа в ожидаемые. К примеру, если в функцию передать параметр типа int в аргумент, объявленный как string, то он преобразуется в string.
Можно включить режим строгой типизации на уровне файла. В этом режиме, тип значения должен строго соответствовать объявленному, иначе будет выброшено исключение TypeError. Единственным исключением из этого правила является передача значения типа int туда, где ожидается float.
На вызовы из внутренних функций, действие strict_types не распространяется.
Для включения строгой типизации используется оператор declare с объявлением
strict_types:
Замечание:
Строгая типизация применяется к вызовам функций, сделанным изнутри файла с включённой строгой типизацией, а не к функциям, объявленным в этом файле. Если из файла без включённой строгой типизации вызывается функция, которая была определена в файле со строгой типизацией, то будут использованы его предпочтения по типизации - т.е. правила строгой типизации будут проигнорированы и для значений будет применяться приведение типов.
Замечание:
Строгая типизация определяется только для объявлений скалярных типов.
Пример #10 Строгая типизация для значений аргументов
<?php
declare(strict_types=1);
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1.5, 2.5));
?>Результат выполнения данного примера в PHP 8:
int(3)
Fatal error: Uncaught TypeError: sum(): Argument #1 ($a) must be of type int, float given, called in - on line 9 and defined in -:4
Stack trace:
#0 -(9): sum(1.5, 2.5)
#1 {main}
thrown in - on line 4
Пример #11 Приведение типов для значений аргументов
<?php
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
// Переданные значения будут приведены к целым числам: обратите внимание на вывод ниже!
var_dump(sum(1.5, 2.5));
?>Результат выполнения данного примера:
int(3) int(3)
Пример #12 Строгая типизация для возвращаемых значений
<?php
declare(strict_types=1);
function sum($a, $b): int {
return $a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1, 2.5));
?>Результат выполнения данного примера:
int(3)
Fatal error: Uncaught TypeError: sum(): Return value must be of type int, float returned in -:5
Stack trace:
#0 -(9): sum(1, 2.5)
#1 {main}
thrown in - on line 5
PHP не требует явного определения типа при объявлении переменной. В этом случае тип переменной определяется значением, которое она хранит. То есть, если переменной $var присваивается значение типа строка (string), то $var изменит тип на строку (string). Если после этого переменной $var будет присвоено значение типа целое число (int), то она изменит тип на целое число (int).
В определённых контекстах PHP может попытаться автоматически преобразовать тип значения в другой. Существуют следующие различные контексты:
Замечание: Когда значение нужно интерпретировать как другой тип, само значение не меняет тип.
Чтобы принудительно установить тип переменной, смотрите раздел Приведение типа. Чтобы изменить тип переменной, смотрите описание функции settype().
Контекст при использовании арифметического оператора.
В данном контексте, если один из операндов является числом с плавающей точкой (float) (или не интерпретируется как целое число (int)), оба операнда интерпретируются как число с плавающей точкой (float) и результатом будет число с плавающей точкой (float). В противном случае операнды будут интерпретированы как целое число (int) и результатом также будет целое число (int). Начиная с PHP 8.0.0, если один из операндов не может быть интерпретирован, выбрасывается ошибка TypeError.
Контекст при использовании функций echo, print, интерполяции строк или строкового оператора конкатенации.
В данном контексте значение будет интерпретироваться как строка (string).
Если значение не может быть интерпретировано, выбрасывается ошибка TypeError.
До версии PHP 7.4.0 выдавалась ошибка уровня E_RECOVERABLE_ERROR.
Контекст при использовании условных операторов, тернарного оператора или логического оператора.
В данном контексте значение будет интерпретироваться как логическое значение (bool).
Контекст при использовании побитовых операторов.
В данном контексте, если у всех операндов тип строка (string), результат также будет строкой (string). В противном случае операнды будут интерпретированы как целое число (int) и результат также будет целым числом (int). Начиная с PHP 8.0.0, если один из операндов не может быть интерпретирован, то будет выброшена ошибка TypeError.
Контекст при использовании оператора сравнения.
Преобразования типов, которые происходят в этом контексте, объясняются в таблице сравнения различных типов раздела Операторы сравнения.
Контекст, когда значение передаётся типизированному параметру, свойству или возвращается из функции, в которой объявлен тип возвращаемого значения.
В этом контексте значение должно быть значением данного типа. Существуют два исключения, первое: если тип значения – целое число (int), а объявленный тип - число с плавающей точкой (float), то целое число преобразуется в число с плавающей точкой. Второй: если объявленный тип является скалярным типом, значение преобразуется в скалярный тип и режим строгой типизации активен (по умолчанию), значение может быть преобразовано в допустимое скалярное значение. Описание такого поведения смотрите ниже.
Встроенные функции автоматически подставляют null к скалярным типам,
это поведение УСТАРЕЛО в PHP 8.1.0.
При выключенном strict_types, объявления скалярных типов
подвергаются ограниченному неявному приведению типов.
Если точный тип значения не является частью объединения,
то целевой тип выбирается в следующем порядке предпочтения:
В качестве исключения, если значение является строкой,
а целое число (int) и число с плавающей точкой (float) являются частью объединения,
предпочтительный тип определяется существующей семантикой числовой строки.
Например, для "42" выбирается целое число (int),
а для "42.0" выбирается число с плавающей точкой (float).
Замечание:
Типы, не входящие в приведённый выше список предпочтений, не являются объектами для неявного приведения. В частности, не происходит неявного приведения к типам null, false и true.
Пример #1 Пример принудительного включения типов в состав объединения
<?php
// int|string
42 --> 42 // точный тип
"42" --> "42" // точный тип
new ObjectWithToString --> "Результат __toString()"
// объект не совместим с int, переход к string
42.0 --> 42 // float совместимый с int
42.1 --> 42 // float совместимый с int
1e100 --> "1.0E+100" // float слишком велик для типа int, переход к string
INF --> "INF" // float слишком велик для типа int, переход к string
true --> 1 // bool совместимый с int
[] --> TypeError // массив не совместим с int или string
// int|float|bool
"45" --> 45 // int числовая строка
"45.0" --> 45.0 // float числовая строка
"45X" --> true // не числовая строка, переход к bool
"" --> false // не числовая строка, переход к bool
"X" --> true // не числовая строка, переход к bool
[] --> TypeError // массив не совместимый с int, float или bool
?>Приведение типа преобразует значение к выбранному типу, записывая тип в круглых скобках перед преобразуемым значением.
<?php
$foo = 10; // $foo - это целое число
$bar = (bool) $foo; // $bar - это логическое значение
?>Допускаются следующие приведения типов:
(int) - приведение типа к целому числу (int)(bool) - приведение типа к логическому значению (bool)(float) - приведение типа к числу с плавающей точкой (float)(string) - приведение типа к строке (string)(array) - приведение типа к массиву (array)(object) - приведение типа к объекту (object)(unset) - приведение типа к NULLЗамечание:
(integer)является псевдонимом приведения типа(int).(boolean)является псевдонимом приведения типа(bool).(binary)является псевдонимом приведения типа(string).(double)и(real)являются псевдонимами приведения типа(float). Эти приведения не используют каноническое имя типа и не рекомендуются.
Псевдоним приведения типа (real) устарел, начиная с PHP 8.0.0.
Приведение типа (unset) устарело, начиная с версии PHP 7.2.0.
Обратите внимание, что приведение (unset) равносильно присвоению переменной или вызову значения NULL.
Приведение (unset) удалено в PHP 8.0.0.
Приведение типа (binary) и префикс b существуют для прямой поддержки.
В настоящее время (binary) и (string) идентичны, однако это может измениться и на это не следует полагаться.
Замечание:
Пробелы игнорируются в круглых скобках при приведении типа. Таким образом, следующие два приведения типов эквивалентны:
<?php
$foo = (int) $bar;
$foo = ( int ) $bar;
?>
Приведение строк (string) и переменных к бинарным строкам (string):
<?php
$binary = (binary) $string;
$binary = b"binary string";
?>Замечание: Вместо приведения переменной к типу строка (string) можно также заключить переменную в двойные кавычки.
<?php
$foo = 10; // $foo является целым числом
$str = "$foo"; // $str является строкой
$fst = (string) $foo; // $fst также является строкой
// Выводит, что "они одинаковые"
if ($fst === $str) {
echo "они одинаковые";
}
?>
Может быть неочевидно, что именно произойдёт при преобразовании между определёнными типами. Для получения дополнительной информации смотрите эти разделы:
Замечание: Поскольку PHP поддерживает индексацию в строках (string) с помощью смещения, используя тот же синтаксис, что и индексация в массивах (array), следующий пример справедлив для всех версий PHP:
Дополнительную информацию смотрите в разделе Доступ к символу в строке и его изменение.<?php
$a = 'car'; // $a является строкой
$a[0] = 'b'; // $a по-прежнему является строкой
echo $a; // bar
?>
Переменные в PHP представлены знаком доллара с последующим именем переменной. Имя переменной чувствительно к регистру.
Имена переменных соответствуют тем же правилам, что и
остальные наименования в PHP. Правильное имя переменной должно
начинаться с буквы или символа подчёркивания и состоять из
букв, цифр и символов подчёркивания в любом количестве.
Это можно отобразить регулярным выражением:
^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$
Замечание: Под буквами здесь подразумеваются символы a-z, A-Z и байты от 128 до 255 (
0x80-0xff).
Замечание:
$this- это специальная переменная, которой нельзя ничего присваивать. До PHP 7.1.0 было возможно косвенное присвоение (например, с использованием переменных переменных).
Смотрите также Руководство по именованию.
Для информации о функциях работы с переменными обращайтесь к разделу функций работы с переменными.
<?php
$var = 'Боб';
$Var = 'Джо';
echo "$var, $Var"; // выведет "Боб, Джо"
$4site = 'ещё нет'; // неверно; начинается с цифры
$_4site = 'ещё нет'; // верно; начинается с символа подчёркивания
$täyte = 'mansikka'; // верно; 'ä' это (Расширенный) ASCII 228.
?>По умолчанию переменные всегда присваиваются по значению. То есть, когда вы присваиваете выражение переменной, все значение оригинального выражения копируется в эту переменную. Это означает, к примеру, что после того как одной переменной присвоено значение другой, изменение одной из них не влияет на другую. Дополнительную информацию об этом способе присвоения смотрите в разделе Выражения.
PHP также предлагает иной способ присвоения значений переменным: присвоение по ссылке. Это означает, что новая переменная просто ссылается (иначе говоря, "становится псевдонимом" или "указывает") на оригинальную переменную. Изменения в новой переменной отражаются на оригинале, и наоборот.
Для присвоения по ссылке, просто добавьте амперсанд (&) к
началу имени присваиваемой (исходной) переменной. Например,
следующий фрагмент кода дважды выводит 'Меня зовут Боб':
<?php
$foo = 'Боб'; // Присваивает $foo значение 'Боб'
$bar = &$foo; // Ссылка на $foo через $bar.
$bar = "Меня зовут $bar"; // Изменение $bar...
echo $bar;
echo $foo; // меняет и $foo.
?>Важно отметить, что по ссылке могут быть присвоены только именованные переменные.
<?php
$foo = 25;
$bar = &$foo; // Это верное присвоение.
$bar = &(24 * 7); // Неверно; ссылка на неименованное выражение.
function test()
{
return 25;
}
$bar = &test(); // Неверно.
?>
Хорошей практикой считается инициализировать переменные, хотя в PHP
это и не является обязательным требованием. Неинициализированные переменные
принимают значение по умолчанию в зависимости от их типа, который
определяется из контекста их первого использования: булевы
принимают значение false, целые числа и числа с плавающей точкой -
ноль, строки (например, при использовании в echo)
- пустую строку, а массивы становятся пустыми массивами.
Пример #1 Значения по умолчанию в неинициализированных переменных
<?php
// Неустановленная И не имеющая ссылок (то есть без контекста использования) переменная; выведет NULL
var_dump($unset_var);
// Булевое применение; выведет 'false' (Подробнее по этому синтаксису смотрите раздел о тернарном операторе)
echo $unset_bool ? "true\n" : "false\n";
// Строковое использование; выведет 'string(3) "abc"'
$unset_str .= 'abc';
var_dump($unset_str);
// Целочисленное использование; выведет 'int(25)'
$unset_int += 25; // 0 + 25 => 25
var_dump($unset_int);
// Использование в качестве числа с плавающей точкой (float); выведет 'float(1.25)'
$unset_float += 1.25;
var_dump($unset_float);
// Использование в качестве массива; выведет array(1) { [3]=> string(3) "def" }
$unset_arr[3] = "def"; // array() + array(3 => "def") => array(3 => "def")
var_dump($unset_arr);
// Использование в качестве объекта; создаёт новый объект stdClass (смотрите http://www.php.net/manual/ru/reserved.classes.php)
// Выведет: object(stdClass)#1 (1) { ["foo"]=> string(3) "bar" }
$unset_obj->foo = 'bar';
var_dump($unset_obj);
?>
Полагаться на значения по умолчанию неинициализированных переменных
довольно проблематично при включении файла в другой файл,
использующий переменную с таким же именем.
В случае работы с неинициализированной переменной вызывается ошибка уровня
E_WARNING (до PHP 8.0.0 выбрасывалась ошибка уровня E_NOTICE),
за исключением случая добавления элементов в неинициализированный массив.
Для обнаружения инициализации переменной может быть использована
языковая конструкция isset().
Любому запускаемому скрипту PHP предоставляет большое количество предопределённых переменных. Однако многие из этих переменных не могут быть полностью задокументированы, поскольку они зависят от запускающего скрипт сервера, его версии и настроек, а также других факторов. Некоторые из этих переменных недоступны, когда PHP запущен из командной строки. Смотрите список зарезервированных предопределённых переменных для получения дополнительной информации.
PHP предоставляет дополнительный набор предопределённых массивов, содержащих переменные сервера (если они доступны), окружения и пользовательского ввода. Эти массивы являются особыми, поскольку они становятся глобальными автоматически - то есть, автоматически доступны в любой области видимости. По этой причине они также известны как 'автоглобальные' или 'суперглобальные' переменные. (В PHP нет механизма определяемых пользователем суперглобальных переменных.) Смотрите список суперглобальных переменных для получения дополнительной информации.
Замечание: Переменные переменных
Суперглобальные переменные не могут быть переменными переменных внутри функций или методов класса.
Если некоторые из переменных в variables_order не установлены, соответствующие им предопределённые массивы также останутся пустыми.
Область видимости переменной - это контекст, в котором эта переменная определена. В большинстве случаев все переменные PHP имеют только одну область видимости. Эта единая область видимости охватывает также включаемые (include) и требуемые (require) файлы. Например:
<?php
$a = 1;
include 'b.inc';
?>Здесь переменная $a будет доступна внутри включённого скрипта b.inc. Однако определение (тело) пользовательской функции задаёт локальную область видимости данной функции. Любая используемая внутри функции переменная по умолчанию ограничена локальной областью видимости функции. Например:
<?php
$a = 1; /* глобальная область видимости */
function test()
{
echo $a; /* ссылка на переменную в локальной области видимости */
}
test();
?>Этот скрипт не сгенерирует никакого вывода, поскольку выражение echo указывает на локальную версию переменной $a, а в пределах этой области видимости ей не было присвоено значение. Возможно вы заметили, что это немного отличается от языка C в том, что глобальные переменные в C автоматически доступны функциям, если только они не были перезаписаны локальным определением. Это может вызвать некоторые проблемы, поскольку люди могут нечаянно изменить глобальную переменную. В PHP, если глобальная переменная будет использоваться внутри функции, она должна быть объявлена глобальной внутри определения функции.
global
Сначала пример использования global:
Пример #1 Использование global
<?php
$a = 1;
$b = 2;
function Sum()
{
global $a, $b;
$b = $a + $b;
}
Sum();
echo $b;
?>
Вышеприведённый скрипт выведет 3. После определения
$a и $b внутри функции как
global все ссылки на любую из этих переменных будут указывать на
их глобальную версию. Не существует никаких ограничений на
количество глобальных переменных, которые могут обрабатываться
функцией.
Второй способ доступа к переменным глобальной области видимости - использование специального, определяемого PHP массива $GLOBALS. Предыдущий пример может быть переписан так:
Пример #2 Использование $GLOBALS вместо global
<?php
$a = 1;
$b = 2;
function Sum()
{
$GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b'];
}
Sum();
echo $b;
?>$GLOBALS - это ассоциативный массив, ключом которого является имя, а значением - содержимое глобальной переменной. Обратите внимание, что $GLOBALS существует в любой области видимости, это объясняется тем, что $GLOBALS является суперглобальным. Ниже приведён пример, демонстрирующий возможности суперглобальных переменных:
Пример #3 Суперглобальные переменные и область видимости
<?php
function test_superglobal()
{
echo $_POST['name'];
}
?>Замечание:
Использование ключевого слова
globalвне функции не является ошибкой. Оно может быть использовано в файле, который включается внутри функции.
static) переменныхДругой важной особенностью области видимости переменной является статическая переменная. Статическая переменная существует только в локальной области видимости функции, но не теряет своего значения, когда выполнение программы выходит из этой области видимости. Рассмотрим следующий пример:
Пример #4 Демонстрация необходимости статических переменных
<?php
function test()
{
$a = 0;
echo $a;
$a++;
}
?>
Эта функция довольно бесполезна, поскольку при каждом вызове она
устанавливает $a в 0 и
выводит 0. Инкремент переменной $a++
здесь не играет роли, так как при выходе из функции переменная
$a исчезает. Чтобы написать полезную
функцию подсчёта, которая не будет терять текущего значения счётчика,
переменная $a объявляется как static:
Пример #5 Пример использования статических переменных
<?php
function test()
{
static $a = 0;
echo $a;
$a++;
}
?>
Теперь $a будет проинициализирована только при
первом вызове функции, а каждый вызов функции test()
будет выводить значение $a и инкрементировать его.
Статические переменные также дают возможность работать с рекурсивными функциями. Рекурсивной является функция, вызывающая саму себя. При написании рекурсивной функции нужно быть внимательным, поскольку есть вероятность сделать рекурсию бесконечной. Вы должны убедиться, что существует адекватный способ завершения рекурсии. Следующая простая функция рекурсивно считает до 10, используя для определения момента остановки статическую переменную $count:
Пример #6 Статические переменные и рекурсивные функции
<?php
function test()
{
static $count = 0;
$count++;
echo $count;
if ($count < 10) {
test();
}
$count--;
}
?>Статическим переменным можно присвоить значения, являющиеся результатом выражения, но нельзя использовать для этого функцию, так это вызовет ошибку разбора.
Пример #7 Объявление статических переменных
<?php
function foo() {
static $int = 0; // верно
static $int = 1+2; // верно
static $int = sqrt(121); // неверно (поскольку это функция)
$int++;
echo $int;
}
?>Начиная с PHP 8.1.0, когда метод, использующий статические переменные, наследуется (но не переопределяется), унаследованный метод теперь будет использовать статические переменные совместно с родительским методом. Это означает, что статические переменные в методах теперь ведут себя так же, как статические свойства.
Пример #8 Использование статических переменных в унаследованных методах
<?php
class Foo {
public static function counter() {
static $counter = 0;
$counter++;
return $counter;
}
}
class Bar extends Foo {}
var_dump(Foo::counter()); // int(1)
var_dump(Foo::counter()); // int(2)
var_dump(Bar::counter()); // int(3), до PHP 8.1.0 int(1)
var_dump(Bar::counter()); // int(4), до PHP 8.1.0 int(2)
?>Замечание:
Статические объявления вычисляются во время компиляции скрипта.
global) и статическими (static) переменными
PHP использует модификаторы переменных
static и
global как
ссылки. Например, реальная
глобальная переменная, внедрённая в область видимости функции указанием
ключевого слова global, в действительности создаёт
ссылку на глобальную переменную. Это может привести к неожиданному
поведению, как это показано в следующем примере:
<?php
function test_global_ref() {
global $obj;
$new = new stdClass;
$obj = &$new;
}
function test_global_noref() {
global $obj;
$new = new stdClass;
$obj = $new;
}
test_global_ref();
var_dump($obj);
test_global_noref();
var_dump($obj);
?>Результат выполнения данного примера:
NULL
object(stdClass)#1 (0) {
}
Аналогично ведёт себя и выражение static. Ссылки не
хранятся статично:
<?php
function &get_instance_ref() {
static $obj;
echo 'Статический объект: ';
var_dump($obj);
if (!isset($obj)) {
$new = new stdClass;
// Присвоить ссылку статической переменной
$obj = &$new;
}
if (!isset($obj->property)) {
$obj->property = 1;
} else {
$obj->property++;
}
return $obj;
}
function &get_instance_noref() {
static $obj;
echo 'Статический объект: ';
var_dump($obj);
if (!isset($obj)) {
$new = new stdClass;
// Присвоить объект статической переменной
$obj = $new;
}
if (!isset($obj->property)) {
$obj->property = 1;
} else {
$obj->property++;
}
return $obj;
}
$obj1 = get_instance_ref();
$still_obj1 = get_instance_ref();
echo "\n";
$obj2 = get_instance_noref();
$still_obj2 = get_instance_noref();
?>Результат выполнения данного примера:
Статический объект: NULL
Статический объект: NULL
Статический объект: NULL
Статический объект: object(stdClass)#3 (1) {
["property"]=>
int(1)
}
Этот пример демонстрирует, что при присвоении ссылки статической
переменной она не запоминается, когда вы
вызываете функцию &get_instance_ref() во
второй раз.
Иногда бывает удобно иметь переменными имена переменных. То есть, имя переменной, которое может быть определено и изменено динамически. Обычная переменная определяется примерно таким выражением:
<?php
$a = 'hello';
?>Переменная переменной берет значение переменной и рассматривает его как имя переменной. В вышеприведённом примере hello может быть использовано как имя переменной при помощи двух знаков доллара. То есть:
<?php
$$a = 'world';
?>Теперь в дереве символов PHP определены и содержатся две переменные: $a, содержащая "hello" и $hello, содержащая "world". Таким образом, выражение
<?php
echo "$a {$$a}";
?>выведет то же, что и
<?php
echo "$a $hello";
?>то есть, они оба выведут: hello world.
Для того чтобы использовать переменные переменных с массивами, вы должны решить проблему двусмысленности. То есть, если вы напишете $$a[1], обработчику необходимо знать, хотите ли вы использовать $a[1] в качестве переменной, либо вам нужна как переменная $$a, а затем её индекс [1]. Синтаксис для разрешения этой двусмысленности таков: ${$a[1]} для первого случая и ${$a}[1] для второго.
К свойствам класса также можно получить доступ динамически. Переменное имя свойства будет разрешено в том контексте, в котором произойдёт вызов к нему. Например, в случае выражения $foo->$bar, локальная область видимости будет просканирована на наличие переменной $bar, значение которой будет использовано в качестве имени свойства объекта $foo. Это также работает и в том случае, если $bar осуществляет доступ к элементу массива.
Фигурные скобки могут также использоваться, чтобы чётко разграничить имя свойства. Они наиболее полезны при получении доступа к значениям внутри свойства, которое содержит массив, когда имя свойства состоит из нескольких частей, либо когда имя свойства содержит символы, которые иначе не действительны (например, из функции json_decode() или из SimpleXML).
Пример #1 Пример переменного имени свойства
<?php
class foo {
var $bar = 'I am bar.';
var $arr = array('I am A.', 'I am B.', 'I am C.');
var $r = 'I am r.';
}
$foo = new foo();
$bar = 'bar';
$baz = array('foo', 'bar', 'baz', 'quux');
echo $foo->$bar . "\n";
echo $foo->{$baz[1]} . "\n";
$start = 'b';
$end = 'ar';
echo $foo->{$start . $end} . "\n";
$arr = 'arr';
echo $foo->{$arr[1]} . "\n";
?>Результат выполнения данного примера:
Обратите внимание, что переменные переменных не могут
использоваться с
суперглобальными массивами
PHP. Переменная $this также является особой, на неё
нельзя ссылаться динамически.
Когда происходит отправка данных формы PHP-скрипту, информация из этой формы автоматически становится доступной ему. Существует несколько способов получения этой информации, например:
Пример #1 Простая HTML-форма
<form action="foo.php" method="post">
Имя: <input type="text" name="username" /><br />
Email: <input type="text" name="email" /><br />
<input type="submit" name="submit" value="Отправь меня!" />
</form>
Есть только два способа получить доступ к данным из форм HTML. Доступные сейчас способы приведены ниже:
Пример #2 Доступ к данным из простой HTML-формы, отправленной через POST
<?php
echo $_POST['username'];
echo $_REQUEST['username'];
?>
GET-форма используется аналогично, за исключением того, что вместо
POST, вам нужно будет использовать соответствующую предопределённую
переменную GET. GET относится также к QUERY_STRING
(информация в URL после '?'). Так, например,
http://www.example.com/test.php?id=3 содержит
GET-данные, доступные как $_GET['id']. Смотрите
также $_REQUEST.
Замечание:
Точки и пробелы в именах переменных преобразуется в знаки подчёркивания. Например,
<input name="a.b" />станет$_REQUEST["a_b"].
PHP также понимает массивы в контексте переменных формы (смотрите соответствующие ЧАВО). К примеру, вы можете сгруппировать связанные переменные вместе или использовать эту возможность для получения значений списка множественного выбора select. Например, давайте отправим форму самой себе, а после отправки отобразим данные:
Пример #3 Более сложные переменные формы
<?php
if ($_POST) {
echo '<pre>';
echo htmlspecialchars(print_r($_POST, true));
echo '</pre>';
}
?>
<form action="" method="post">
Имя: <input type="text" name="personal[name]" /><br />
Email: <input type="text" name="personal[email]" /><br />
Пиво: <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="submit" value="Отправь меня!" />
</form>Замечание: Если внешнее имя переменной начинается с корректного синтаксиса массива, завершающие символы молча игнорируются. Например,
<input name="foo[bar]baz">станет$_REQUEST['foo']['bar'].
При отправке формы вместо стандартной кнопки можно использовать изображение с помощью тега такого вида:
<input type="image" src="image.gif" name="sub" />
Когда пользователь щёлкнет где-нибудь на изображении, соответствующая форма будет передана на сервер с двумя дополнительными переменными - sub_x и sub_y. Они содержат координаты нажатия пользователя на изображение. Опытные программисты могут заметить, что на самом деле имена переменных, отправленных браузером, содержат точку, а не подчёркивание, но PHP автоматически преобразует точку в подчёркивание.
PHP прозрачно поддерживает HTTP cookies как определено в » RFC 6265. Cookies - это механизм для хранения данных в удалённом браузере и, таким образом, отслеживания и идентификации вернувшихся пользователей. Вы можете установить cookies, используя функцию setcookie(). Cookies являются частью HTTP-заголовка, поэтому функция SetCookie должна вызываться до того, как браузеру будет отправлен какой бы то ни было вывод. Это то же ограничение, что и для функции header(). Данные, хранящиеся в cookie, доступны в соответствующих массивах данных cookie, таких как $_COOKIE и $_REQUEST. Подробности и примеры смотрите в справочной странице setcookie().
Замечание: Начиная с PHP 7.2.34, 7.3.23 и 7.4.11, соответственно, имена входящих cookie больше не декодируются из URL-закодированной строки из соображений безопасности.
Если вы хотите присвоить множество значений одной переменной cookie, вы можете присвоить их как массив. Например:
<?php
setcookie("MyCookie[foo]", 'Testing 1', time()+3600);
setcookie("MyCookie[bar]", 'Testing 2', time()+3600);
?>Это создаст две разные cookie, хотя в вашем скрипте MyCookie будет теперь одним массивом. Если вы хотите установить именно одну cookie со множеством значений, сначала рассмотрите возможность использования к значениям такие функции, как serialize() или explode().
Обратите внимание, что cookie заменит предыдущую cookie с тем же именем в вашем браузере, если только путь или домен не отличаются. Так, для приложения корзины покупок вы, возможно, захотите сохранить счётчик. То есть:
Пример #4 Пример использования setcookie()
<?php
if (isset($_COOKIE['count'])) {
$count = $_COOKIE['count'] + 1;
} else {
$count = 1;
}
setcookie('count', $count, time()+3600);
setcookie("Cart[$count]", $item, time()+3600);
?>Как правило, PHP не меняет передаваемых скрипту имён переменных. Однако следует отметить, что точка не является корректным символом в имени переменной PHP. Поэтому рассмотрим такую запись:
<?php
$varname.ext; /* неверное имя переменной */
?>По этой причине важно отметить, что PHP будет автоматически заменять любые точки в именах, приходящих переменных на символы подчёркивания.
Поскольку PHP определяет типы переменных и преобразует их (как правило) по мере необходимости, не всегда очевидно, какой тип имеет данная переменная в любой момент времени. PHP содержит несколько функций, позволяющих определить тип переменной, таких как: gettype(), is_array(), is_float(), is_int(), is_object() и is_string(). Смотрите также раздел Типы.
HTTP является текстовым протоколом, и большинство, если не всё, содержимое, которое приходит в суперглобальные массивы, например, $_POST и $_GET, останется в виде строк. PHP не будет преобразовывать значения в определённый тип. В приведённом ниже примере $_GET["var1"] будет содержать строку "null", а $_GET["var2"] - строку "123".
/index.php?var1=null&var2=123
| Версия | Описание |
|---|---|
| 7.2.34, 7.3.23, 7.4.11 | имена входящих cookie больше не декодируются из URL-закодированной строки из соображений безопасности. |
Константа - это идентификатор (имя) для простого значения. Как следует из названия, это значение не может измениться в ходе выполнения скрипта (кроме магических констант, которые на самом деле не являются константами). Константы чувствительны к регистру. По принятому соглашению, имена констант всегда пишутся в верхнем регистре.
Замечание:
До PHP 8.0.0 константы, определённые с помощью функции define(), могли быть нечувствительными к регистру.
Имя константы должно соответствовать тем же правилам именования, что
и другие имена в PHP. Правильное имя начинается с буквы или символа подчёркивания,
за которым следует любое количество букв, цифр и символов подчёркивания. Регулярное выражение для проверки правильности
имени константы выглядит так:
^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$
Возможно определить константы с помощью функции define() зарезервированными или даже некорректными именами, значения которых могут быть получены только с помощью constant(). Однако, делать это не рекомендуется.
Смотрите также Руководство по именованию.
Пример #1 Правильные и неправильные имена констант
<?php
// Правильные имена констант
define("FOO", "что-то");
define("FOO2", "что-то ещё");
define("FOO_BAR", "что-то большее");
// Неправильные имена констант
define("2FOO", "что-то");
// Это верное объявление, но лучше его не использовать:
// PHP однажды может зарегистрировать волшебную константу,
// которая нарушит работу скрипта
define("__FOO__", "что-то");
?>Замечание: Понятие "буквы" здесь - это символы a-z, A-Z, и другие символы с ASCII-кодами от 128 до 255 (0x80-0xff).
Как и superglobals, константы доступны из любой области видимости. Константы можно использовать из любого места скрипта независимо от области видимости. Подробную информацию об областях видимости можно найти здесь.
Замечание: Начиная с PHP 7.1.0, константе класса можно объявлять видимость защищённая или закрытая, делая её доступной только в иерархической области видимости класса, в котором она определена.
Константа может быть определена с помощью ключевого слова const
или с помощью функции define().
В то время как define() позволяет
задать константу через выражение, конструкция const ограничена
как описано в следующем параграфе. После того, как константа определена, её значение
не может быть изменено или аннулировано.
При использовании ключевого слова const допускаются
только скалярные выражения (bool, int, float и string) и константы array,
содержащие только скалярные выражения.
Можно определить константы с типом resource, но не рекомендуется,
так как это может привести к неожиданным результатам.
Получить значение константы можно, указав её имя. В отличие от переменных,
вам не нужно предварять имя константы символом
$.
Также можно использовать функцию constant() для
получения значения константы, если вы формируете имя константы динамически.
Используйте функцию get_defined_constants() для получения
списка всех определённых констант.
Замечание: Константы и (глобальные) переменные находятся в разных пространствах имён. Это означает, что, например,
trueи $TRUE в целом отличаются.
Если используется неопределённая константа, выбрасывается Error.
До PHP 8.0.0 неопределённые константы интерпретировались как простое слово string, то есть (CONSTANT vs "CONSTANT").
Этот резервный вариант объявлен устаревшим с PHP 7.2.0, при этом будет
сгенерирована ошибка уровня E_WARNING.
До PHP 7.2.0 вместо этого выдавалась ошибка уровня E_NOTICE.
Смотрите также главу руководства, которая разъясняет, почему
$foo[bar] - это неправильно (если bar не является константой).
Это не относится к (полностью) определённым константам,
которые всегда будут выбрасывать Error, если они не определены.
Замечание: Чтобы проверить, установлена ли константа, используйте функцию defined().
Различия между константами и переменными:
$);
Пример #1 Определение констант
<?php
define("CONSTANT", "Здравствуй, мир.");
echo CONSTANT; // выводит "Здравствуй, мир."
echo Constant; // Выбросит ошибку: Неопределённая константа "Constant"
// До PHP 8.0.0 выводит "Constant" и выдаёт предупреждение.
?>
Пример #2 Определение констант с помощью ключевого слова const
<?php
// Простое скалярное значение
const CONSTANT = 'Здравствуй, мир.';
echo CONSTANT;
// Скалярное выражение
const ANOTHER_CONST = CONSTANT . ' Прощай, мир.';
echo ANOTHER_CONST;
const ANIMALS = array('dog', 'cat', 'bird');
echo ANIMALS[1]; // выводит "cat"
// Массивы в константе
define('ANIMALS', array(
'dog',
'cat',
'bird'
));
echo ANIMALS[1]; // выводит "cat"
?>Замечание:
В отличие от определения констант с помощью функции define(), константы, объявленные с помощью ключевого слова
constдолжны быть объявлены в самой верхней области видимости, потому что они определяются при компилировании скрипта. Это означает, что их нельзя объявлять внутри функций, циклов, выраженийifи блоковtry/catch.
PHP предоставляет большой список предопределённых констант для каждого выполняемого скрипта. Многие из этих констант определяются различными модулями и будут присутствовать только в том случае, если эти модули доступны в результате динамической загрузки или в результате статической сборки.
Есть девять магических констант, которые меняют своё значение в
зависимости от контекста, в котором они используются.
Например, значение __LINE__ зависит от строки в скрипте,
на которой эта константа указана. Все магические константы разрешаются во
время компиляции, в отличие от обычных констант, которые разрешаются во
время выполнения. Специальные константы нечувствительны
к регистру и их список приведён ниже:
| Имя | Описание |
|---|---|
__LINE__ |
Текущий номер строки в файле. |
__FILE__ |
Полный путь и имя текущего файла с развёрнутыми симлинками. Если используется внутри подключаемого файла, то возвращается имя данного файла. |
__DIR__ |
Директория файла. Если используется внутри подключаемого файла,
то возвращается директория этого файла. Это эквивалентно вызову
dirname(__FILE__). Возвращаемое имя директории
не оканчивается на слеш, за исключением корневой директории.
|
__FUNCTION__ |
Имя функции или {closure} в случае анонимной функции.
|
__CLASS__ |
Имя класса. Это имя содержит название пространства имён, в котором класс был объявлен
(например, Foo\Bar).
При использовании в методах трейтов __CLASS__ является именем
класса, в котором эти методы используется.
|
__TRAIT__ |
Имя трейта. Это имя содержит название пространства имён, в котором трейт
был объявлен (например, Foo\Bar).
|
__METHOD__ |
Имя метода класса. |
__NAMESPACE__ |
Имя текущего пространства имён. |
ClassName::class |
Полное имя класса. |
Выражения - это самые важные строительные элементы PHP. Почти всё, что вы пишете в PHP, является выражением. Самое простое и точное определение выражения - "все что угодно, имеющее значение".
Основными формами выражений являются константы и переменные. Если
вы записываете $a = 5, вы присваиваете 5 переменной
$a. 5, очевидно, имеет значение 5 или, другими словами,
5 - это выражение со значением 5 (в данном случае 5 - это целочисленная
константа).
После этого присвоения вы ожидаете, что значением $a
также является 5, поэтому, если вы написали $b = $a,
вы полагаете, что работать это будет так же, как
если бы вы написали $b = 5. Другими словами,
$a это также выражение со значением 5. Если всё работает
верно, то именно так и произойдёт.
Немного более сложными примерами выражений являются функции. Например, рассмотрим следующую функцию:
<?php
function foo ()
{
return 5;
}
?>
Исходя из того, что вы хорошо знакомы с концепцией функций (если нет,
то прочитайте главу о функциях), вы
полагаете, что запись $c = foo() абсолютно
эквивалентна записи $c = 5, и вы правы. Функции -
это выражения, значением которых является то, что возвращает функция.
Поскольку foo() возвращает 5, значением выражения
'foo()' является 5.
Как правило, функции возвращают не просто статическое значение, а
что-то вычисляют.
Разумеется, значения в PHP не обязаны быть целочисленными, и очень часто ими не являются. PHP поддерживает четыре типа скалярных значений: целочисленные (int), с плавающей точкой (float), строковые значения (string) и булевы (bool) значения (скалярными являются значения, которые вы не можете 'разбить' на меньшие части, в отличие, например, от массивов). PHP поддерживает также два комбинированных (не скалярных) типа: массивы и объекты. Любое значение такого типа может присваиваться переменной или возвращаться функцией.
Однако PHP, как и многие другие языки, понимает гораздо больше выражений.
PHP - это язык, ориентированный на выражения и рассматривающий почти все как
выражение. Вернёмся к примеру, с которым мы уже имели дело:
$a = 5. Легко заметить, что здесь присутствуют два значения
- значение целочисленной константы 5 и значение переменной $a,
также принимающей значение 5. Но на самом деле здесь присутствует и ещё одно
значение - значение самого присвоения. Само присвоение вычисляется в
присвоенное значение, в данном случае - в 5. На практике это означает, что
$a = 5, независимо от того, что оно делает, является
выражением со значением 5. Таким образом, запись $b = ($a = 5)
равносильна записи $a = 5; $b = 5; (точка с запятой обозначает конец выражения).
Поскольку операции присвоения анализируются справа налево, вы также
можете написать $b = $a = 5.
Другой хороший пример ориентированности на выражения - префиксный и
постфиксный инкремент и декремент. Пользователи PHP и многих
других языков возможно уже знакомы с формой записи variable++
и variable--. Это
операторы инкремента и декремента. Также как и C, PHP
поддерживает два типа инкремента - префиксный и постфиксный. Они
оба инкрементируют значение переменной и эффект их действия на неё
одинаков. Разница состоит в значении выражения инкремента.
Префиксный инкремент, записываемый как ++$variable,
вычисляется в инкрементированное значение (PHP инкрементирует переменную до того
как прочесть её значение, отсюда название 'пре-инкремент').
Постфиксный инкремент, записываемый как $variable++,
вычисляется в первоначальное значение переменной $variable до её приращения
(PHP инкрементирует переменную после прочтения её значения, отсюда
название 'пост-инкремент').
Очень распространённым типом выражений являются выражения сравнения.
Результатом вычислений являются false (ложь)
или true (истина). PHP поддерживает операции сравнения > (больше), >= (больше
либо равно), == (равно), != (не равно), < (меньше) и <=
(меньше либо равно). Он также поддерживает операторы строгого
равенства: === (равно и одного типа) и !== (не равно или не одного
типа). Чаще всего эти выражения используются в операторах условного выполнения,
таких как if.
Последний пример выражений, который мы здесь рассмотрим, это
смешанные выражения операции и присвоения. Вы уже знаете, что если
вы хотите увеличить $a на 1, вы можете просто написать
$a++ или ++$a. Но что, если вы
хотите прибавить больше, чем единицу, например, 3? Вы могли бы написать
$a++ много раз, однако, очевидно это не очень
рациональный и удобный способ. Гораздо более распространённой практикой
является запись вида $a = $a + 3.
$a + 3 вычисляется в значение $a плюс
3 и снова присваивается $a, увеличивая в результате
$a на 3. В PHP, как и в некоторых других языках, таких как C,
вы можете записать это более коротким образом, что увеличит очевидность смысла
и быстроту понимания кода по прошествии времени. Прибавить 3 к текущему значению
$a можно с помощью записи $a += 3.
Это означает дословно "взять значение $a, прибавить к
нему 3 и снова присвоить его переменной $a". Кроме
большей понятности и краткости, это быстрее работает. Значением
$a += 3, как и обычного присвоения, является присвоенное
значение. Обратите внимание, что это НЕ 3, а суммированное значение
$a плюс 3 (то, что было присвоено $a).
Таким образом может использоваться любой бинарный оператор, например,
$a -= 5 (вычесть 5 из значения $a),
$b *= 7 (умножить значение $b на 7)
и т.д.
Существует ещё одно выражение, которое может выглядеть необычно, если вы не встречали его в других языках - тернарный условный оператор:
<?php
$first ? $second : $third
?>
Если значением первого подвыражения является true (не ноль),
то выполняется второе подвыражение, которое и будет результатом
условного выражения. В противном случае будет выполнено третье
подвыражение и его значение будет результатом.
Следующий пример должен помочь вам немного улучшить понимание префиксного и постфиксного инкремента и выражений:
<?php
function double($i)
{
return $i*2;
}
$b = $a = 5; /* присвоить значение пять переменным $a и $b */
$c = $a++; /* постфиксный инкремент, присвоить значение $a
(5) переменной $c */
$e = $d = ++$b; /* префиксный инкремент, присвоить увеличенное
значение $b (6) переменным $d и $e */
/* в этой точке и $d, и $e равны 6 */
$f = double($d++); /* присвоить удвоенное значение $d перед
инкрементом (2*6 = 12) переменной $f */
$g = double(++$e); /* присвоить удвоенное значение $e после
инкремента (2*7 = 14) переменной $g */
$h = $g += 10; /* сначала переменная $g увеличивается на 10,
приобретая, в итоге, значение 24. Затем значение
присвоения (24) присваивается переменной $h,
которая в итоге также становится равной 24. */
?>
Некоторые выражения могут рассматриваться как инструкции. В
данном случае инструкция имеет вид 'expr ;' - выражение с
последующей точкой с запятой. В записи $b = $a = 5;,
$a = 5 - это верное выражение, но само по себе не инструкция.
Тогда как $b = $a = 5; является верной инструкцией.
Последнее, что стоит упомянуть, это истинность значения выражений.
Во многих случаях, как правило, в условных операторах и циклах,
вас может интересовать не конкретное значение выражения, а только
его истинность (значение true или false).
Константы true и false (регистронезависимые) - это два
возможных булевых значения. При необходимости выражение
автоматически преобразуется в булев тип. Подробнее о том, как это
происходит, смотрите в разделе о
приведении типов.
PHP предоставляет полную и мощную реализацию выражений, и их полное документирование выходит за рамки этого руководства. Вышеприведённые примеры должны дать вам представление о том, что они из себя представляют и как вы сами можете создавать полезные выражения. Далее, для обозначения любого верного выражения PHP в этой документации мы будем использовать сокращение expr.
Оператором называется нечто, принимающее одно или более значений (или выражений, если говорить на жаргоне программирования), и вычисляющее новое значение (таким образом, вся конструкция может рассматриваться как выражение).
Операторы можно сгруппировать по количеству принимаемых ими значений. Унарные
операторы принимают только одно значение, например, !
(оператор логического отрицания)
или ++ (инкремент).
Бинарные операторы принимают два значения; это, например, знакомые
всем арифметические операторы
+ (плюс) и - (минус), большинство поддерживаемых в
PHP операторов входят именно в эту категорию. Ну и, наконец, есть всего один
тернарный оператор,
? :, принимающий три значения, обычно его так и называют -- "тернарный
оператор" (хотя, возможно, более точным названием было бы "условный оператор").
Полный список PHP-операторов вы можете найти в разделе "Порядок выполнения операторов". В этом разделе также описан порядок выполнения операторов и их ассоциативность, которые точно определяют, как вычисляются выражения с несколькими разными операторами.
Приоритет оператора определяет, насколько "тесно" он связывает между собой два
выражения. Например, выражение 1 + 5 * 3 вычисляется как
16, а не 18, поскольку оператор умножения ("*") имеет
более высокий приоритет, чем оператор сложения ("+"). Круглые скобки могут
использоваться для принудительного указания порядка выполнения операторов. Например,
выражение (1 + 5) * 3 вычисляется как 18.
Если операторы имеют равный приоритет, то будут ли они выполняться справа налево или
слева направо определяется их ассоциативностью. К примеру, "-" является
лево-ассоциативным оператором. Следовательно 1 - 2 - 3 сгруппируется
как (1 - 2) - 3 и пересчитается в -4. С другой стороны
"=" - право-ассоциативный оператор, так что $a = $b = $c сгруппируется
как $a = ($b = $c).
Неассоциативные операторы с одинаковым приоритетом не могут использоваться совместно.
К примеру 1 < 2 > 1 не будет работать в PHP. Выражение
1 <= 1 == 1, с другой стороны, будет, поскольку ==
имеет более низкий приоритет чем <=.
Ассоциативность имеет смысл только для двоичных (и тернарных) операторов.
Унарные операторы являются префиксными или постфиксными, поэтому это понятие не применимо.
Например, !!$a можно сгруппировать только как !(!$a).
Использование скобок, кроме случаев когда они строго необходимы, может улучшить читаемость кода, группируя явно, а не полагаясь на приоритеты и ассоциативность.
В следующей таблице приведён список операторов, отсортированный по убыванию их приоритетов. Операторы, размещённые в одной строке имеют одинаковый приоритет и порядок их выполнения определяется исходя из их ассоциативности.
| Ассоциативность | Оператор | Дополнительная информация |
|---|---|---|
| (н/а) |
clone
new
|
clone и new |
| правая | ** |
арифметические операторы |
| (н/а) |
+
-
++
--
~
(int)
(float)
(string)
(array)
(object)
(bool)
@
|
арифметические операторы (унарные + и -),
инкремент/декремент,
побитовые операторы,
приведение типов и
оператор управления ошибками
|
| левая | instanceof | типы |
| (н/а) | ! | логические операторы |
| левая |
*
/
%
|
арифметические операторы |
| левая |
+
-
.
|
арифметические операторы (бинарные + и -),
операторы, работающие с массивами и
строковые операторы (. до PHP 8.0.0)
|
| левая |
<<
>>
|
побитовые операторы |
| левая | . |
строковые операторы (начиная с PHP 8.0.0) |
| неассоциативна |
<
<=
>
>=
|
операторы сравнения |
| неассоциативна |
==
!=
===
!==
<>
<=>
|
операторы сравнения |
| левая | & |
побитовые операторы и ссылки |
| левая | ^ |
побитовые операторы |
| левая | | |
побитовые операторы |
| левая | && |
логические операторы |
| левая | || |
логические операторы |
| правая | ?? |
операторы сравнения с null |
| неассоциативна | ? : |
тернарный оператор (лево-ассоциативный до PHP 8.0.0) |
| правая |
=
+=
-=
*=
**=
/=
.=
%=
&=
|=
^=
<<=
>>=
??=
|
операторы присваивания |
| (н/а) | yield from |
yield from |
| (н/а) | yield |
yield |
| (н/а) | print |
|
| левая | and |
логические операторы |
| левая | xor |
логические операторы |
| левая | or |
логические операторы |
Пример #1 Ассоциативность
<?php
$a = 3 * 3 % 5; // (3 * 3) % 5 = 4
// ассоциативность тернарных операторов отличается от C/C++
$a = true ? 0 : true ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2 (до PHP 8.0.0)
$a = 1;
$b = 2;
$a = $b += 3; // $a = ($b += 3) -> $a = 5, $b = 5
?>Приоритет и ассоциативность оператора определяет только то, как группируется выражение, а не порядок его вычисления. Обычно PHP не указывает, в каком порядке вычисляются выражения и кода, который предполагает специфичный порядок вычисления следует избегать, потому, что поведение может меняться в разных версиях PHP или в зависимости от окружающего кода.
Пример #2 Неопределённый порядок вычисления
<?php
$a = 1;
echo $a + $a++; // может вывести как 2 так и 3
$i = 1;
$array[$i] = $i++; // может установить индекс как 1, так 2
?>Пример #3 +, - и . имеют одинаковый приоритет (до PHP 8.0.0)
<?php
$x = 4;
// следующий код может выдать неожиданный результат:
echo "x минус 1 равно " . $x-1 . ", ну я надеюсь\n";
// поскольку он вычисляется таким образом (до PHP 8.0.0):
echo (("x минус один равно " . $x) - 1) . ", ну я надеюсь\n";
// требуемый приоритет следует задать скобками:
echo "x минус 1 равно " . ($x-1) . ", ну я надеюсь\n";
?>Результат выполнения данного примера:
-1, ну я надеюсь -1, ну я надеюсь x минус один равно 3, ну я надеюсь
Замечание:
Несмотря на то, что
=имеет более низкий приоритет, чем большинство других операторов, PHP всё же позволяет делать так:if (!$a = foo()), в этом примере результат выполненияfoo()будет присвоен $a.
| Версия | Описание |
|---|---|
| 8.0.0 |
Объединение строк (.) теперь имеет более низкий приоритет, чем
арифметическое сложение/вычитание (+ и -) и
побитовый сдвиг влево/вправо (<< и >>);
ранее он имел тот же приоритет, что и + и -,
и более высокий приоритет, чем << и >>.
|
| 8.0.0 |
Тернарный оператор (? :) теперь неассоциативен;
ранее он был лево-ассоциативным.
|
| 7.4.0 |
Опираясь на приоритет конкатенации строк (.) относительно
арифметического сложения/вычитания (+ или -) или побитового
сдвига влево/вправо (<< или >>),
т.е. их совместное использование в выражении без скобок не рекомендуется.
|
| 7.4.0 |
Не рекомендуется полагаться на лево-ассоциативность тернарного оператора (? :),
т.е. вложение нескольких тернарных операторов без скобок.
|
Помните школьные основы арифметики? Описанные ниже операторы работают так же.
| Пример | Название | Результат |
|---|---|---|
| +$a | Идентичность | Конвертация $a в int или float, что более подходит. |
| -$a | Отрицание | Смена знака $a. |
| $a + $b | Сложение | Сумма $a и $b. |
| $a - $b | Вычитание | Разность $a и $b. |
| $a * $b | Умножение | Произведение $a и $b. |
| $a / $b | Деление | Частное от деления $a на $b. |
| $a % $b | Деление по модулю | Целочисленный остаток от деления $a на $b. |
| $a ** $b | Возведение в степень | Возведение $a в степень $b. |
Операция деления ("/") возвращает число с плавающей точкой, кроме случая, когда оба значения являются целыми числами (или строками, которые преобразуются в целые числа), которые делятся нацело - в этом случае возвращается целое значение. Для целочисленного деления используйте intdiv().
При делении по модулю операнды преобразуются в целые числа (int) (путём удаления дробной части) до начала операции. Для деления по модулю чисел с плавающей точкой используйте fmod().
Результат операции остатка от деления % будет иметь тот же знак,
что и делимое — то есть, результат $a % $b
будет иметь тот же знак, что и $a. Например:
<?php
echo (5 % 3)."\n"; // выводит 2
echo (5 % -3)."\n"; // выводит 2
echo (-5 % 3)."\n"; // выводит -2
echo (-5 % -3)."\n"; // выводит -2
?>Базовый оператор присваивания обозначается как "=". На первый взгляд может показаться, что это оператор "равно". На самом деле это не так. В действительности оператор присваивания означает, что левый операнд получает значение правого выражения, (то есть устанавливается значением).
Результатом выполнения оператора присваивания является само присвоенное значение.
Таким образом, результат выполнения "$a = 3" будет равен
3. Это позволяет делать трюки наподобие:
<?php
$a = ($b = 4) + 5; // $a теперь равно 9, а $b было присвоено 4.
?>В дополнение к базовому оператору присваивания имеются "комбинированные операторы" для всех бинарных арифметических операций, операций объединения массивов и строковых операций, которые позволяют использовать некоторое значение в выражении, а затем установить его как результат данного выражения. Например:
<?php
$a = 3;
$a += 5; // устанавливает $a в 8, как если бы мы написали: $a = $a + 5;
$b = "Привет";
$b .= "-привет!"; // устанавливает $b в "Привет-привет!", как и $b = $b . "-привет!";
?>Обратите внимание, что присвоение копирует оригинальную переменную в новую (присвоение по значению), таким образом все последующие изменения одной из переменных никак не отразятся на другой. Это также следует учитывать, если вам надо скопировать что-то типа большого массива в длинном цикле.
Исключением из обычного для PHP способа присваивания по значению являются объекты (object), которые присваиваются по ссылке. Принудительно скопировать объекты по значению можно с помощью специального ключевого слова clone.
Присваивание по ссылке также поддерживается, для него используется синтаксис $var = &$othervar;. Присваивание по ссылке означает, что обе переменные указывают на одни и те же данные и никакого копирования не происходит.
Пример #1 Присваивание по ссылке
<?php
$a = 3;
$b = &$a; // $b - это ссылка на $a
print "$a\n"; // печатает 3
print "$b\n"; // печатает 3
$a = 4; // меняем $a
print "$a\n"; // печатает 4
print "$b\n"; // также печатает 4, так как $b является ссылкой на $a,
// а значение переменной $a успело измениться
?>Оператор new автоматически возвращает ссылку, поэтому присвоение результата операции new по ссылке является ошибкой.
<?php
class C {}
$o = &new C;
?>Результат выполнения данного примера:
Parse error: syntax error, unexpected 'new' (T_NEW) in …
Для получения более полной информации о ссылках и их возможностях обратитесь к разделу Подробно о ссылках.
| Пример | Эквивалент | Операция |
|---|---|---|
| $a += $b | $a = $a + $b | Сложение |
| $a -= $b | $a = $a - $b | Вычитание |
| $a *= $b | $a = $a * $b | Умножение |
| $a /= $b | $a = $a / $b | Деление |
| $a %= $b | $a = $a % $b | Модуль |
| $a **= $b | $a = $a ** $b | Возведение в степень |
| Пример | Эквивалент | Операция |
|---|---|---|
| $a &= $b | $a = $a & $b | Побитовое И |
| $a |= $b | $a = $a | $b | Побитовое ИЛИ |
| $a ^= $b | $a = $a ^ $b | Побитовое исключающее ИЛИ (Xor) |
| $a <<= $b | $a = $a << $b | Побитовый сдвиг влево |
| $a >>= $b | $a = $a >> $b | Побитовый сдвиг вправо |
| Пример | Эквивалент | Операция |
|---|---|---|
| $a .= $b | $a = $a . $b | Конкатенация строк |
| $a ??= $b | $a = $a ?? $b | Объединение с Null |
Побитовые операторы позволяют считывать и устанавливать конкретные биты целых чисел.
| Пример | Название | Результат |
|---|---|---|
$a & $b |
И | Устанавливаются только те биты, которые установлены и в $a, и в $b. |
$a | $b |
Или | Устанавливаются те биты, которые установлены в $a или в $b. |
$a ^ $b |
Исключающее или | Устанавливаются только те биты, которые установлены либо только в $a, либо только в $b, но не в обоих одновременно. |
~ $a |
Отрицание | Устанавливаются те биты, которые не установлены в $a, и наоборот. |
$a << $b |
Сдвиг влево | Все биты переменной $a сдвигаются на $b позиций влево (каждая позиция подразумевает "умножение на 2") |
$a >> $b |
Сдвиг вправо | Все биты переменной $a сдвигаются на $b позиций вправо (каждая позиция подразумевает "деление на 2") |
Побитовый сдвиг в PHP - это арифметическая операция. Биты, сдвинутые за границы числа, отбрасываются. Сдвиг влево дополняет число нулями справа, сдвигая в то же время знаковый бит числа влево, что означает что знак операнда не сохраняется. Сдвиг вправо сохраняет копию сдвинутого знакового бита слева, что означает что знак операнда сохраняется.
Используйте скобки для обеспечения необходимого
приоритета операторов.
Например, $a & $b == true сначала проверяет
на равенство, а потом выполняет побитовое и; тогда как
($a & $b) == true сначала выполняет побитовое и,
а потом выполняет проверку на равенство.
Если оба операнда для &, | и
^ строки, то операция будет производиться с кодами ASCII всех
символов строки и в результате вернёт строку. Во всех остальных случаях, оба операнда
будут преобразованы к целому и
результатом будет целое число.
Если операнд для ~ строка, то операция будет производиться с кодами
ASCII всех символов строки и в результате вернёт строку, в ином случае как операнд,
так и результат, будут считаться целыми.
Оба операнда и результат выполнения << и
>> всегда считаются за целое.
Опция настроек PHP error_reporting использует побитовые значения, обеспечивая
реальную демонстрацию удаления значений битов. Чтобы показать все ошибки, кроме
замечаний, инструкции в файле php.ini предлагают использовать:
E_ALL & ~E_NOTICE
Начинаем со значения E_ALL:
00000000000000000111011111111111
Затем берём значение E_NOTICE...
00000000000000000000000000001000
... и инвертируем его с помощью ~:
11111111111111111111111111110111
Наконец, используем побитовое И (&), чтобы установить только те биты,
которые установлены в единицу в обоих значениях:
00000000000000000111011111110111
Другой способ достичь этого - использовать ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR, ^),
чтобы получить только те биты, которые установлены в единицу
либо только в одном, либо только в другом значении:
E_ALL ^ E_NOTICE
Опция error_reporting также может быть использована для демонстрации
установки битов. Показать только ошибки и обрабатываемые ошибки можно
следующим образом:
E_ERROR | E_RECOVERABLE_ERROR
Здесь мы комбинируем E_ERROR
00000000000000000000000000000001
и
00000000000000000001000000000000
с помощью оператора ИЛИ (|),
чтобы получить биты, установленные хотя бы в одном операнде:
00000000000000000001000000000001
Пример #1 Побитовыми операции И, ИЛИ и ИСКЛЮЧАЮЩЕЕ ИЛИ (AND, OR и XOR) над целыми числами
<?php
/*
* Не обращайте внимания на этот верхний раздел кода,
* это просто форматирование для более ясного вывода.
*/
$format = '(%1$2d = %1$04b) = (%2$2d = %2$04b)'
. ' %3$s (%4$2d = %4$04b)' . "\n";
echo <<<EOH
---------- ----------- -- ----------
результат значение оп тест
---------- ----------- -- ----------
EOH;
/*
* Вот сами примеры.
*/
$values = array(0, 1, 2, 4, 8);
$test = 1 + 4;
echo "\n Побитовое И (AND) \n";
foreach ($values as $value) {
$result = $value & $test;
printf($format, $result, $value, '&', $test);
}
echo "\n Побитовое (включающее) ИЛИ (OR) \n";
foreach ($values as $value) {
$result = $value | $test;
printf($format, $result, $value, '|', $test);
}
echo "\n Побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR) \n";
foreach ($values as $value) {
$result = $value ^ $test;
printf($format, $result, $value, '^', $test);
}
?>Результат выполнения данного примера:
---------- ----------- -- ---------- результат значение оп тест ---------- ----------- -- ---------- Побитовое И (AND) ( 0 = 0000) = ( 0 = 0000) & ( 5 = 0101) ( 1 = 0001) = ( 1 = 0001) & ( 5 = 0101) ( 0 = 0000) = ( 2 = 0010) & ( 5 = 0101) ( 4 = 0100) = ( 4 = 0100) & ( 5 = 0101) ( 0 = 0000) = ( 8 = 1000) & ( 5 = 0101) Побитовое (включающее) ИЛИ (OR) ( 5 = 0101) = ( 0 = 0000) | ( 5 = 0101) ( 5 = 0101) = ( 1 = 0001) | ( 5 = 0101) ( 7 = 0111) = ( 2 = 0010) | ( 5 = 0101) ( 5 = 0101) = ( 4 = 0100) | ( 5 = 0101) (13 = 1101) = ( 8 = 1000) | ( 5 = 0101) Побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR) ( 5 = 0101) = ( 0 = 0000) ^ ( 5 = 0101) ( 4 = 0100) = ( 1 = 0001) ^ ( 5 = 0101) ( 7 = 0111) = ( 2 = 0010) ^ ( 5 = 0101) ( 1 = 0001) = ( 4 = 0100) ^ ( 5 = 0101) (13 = 1101) = ( 8 = 1000) ^ ( 5 = 0101)
Пример #2 Побитовая операция ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR) над строками
<?php
echo 12 ^ 9; // Выводит '5'
echo "12" ^ "9"; // Выводит символ Backspace (ascii 8)
// ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8
echo "hallo" ^ "hello"; // Выводит ascii-значения #0 #4 #0 #0 #0
// 'a' ^ 'e' = #4
echo 2 ^ "3"; // Выводит 1
// 2 ^ ((int)"3") == 1
echo "2" ^ 3; // Выводит 1
// ((int)"2") ^ 3 == 1
?>
Пример #3 Побитовый сдвиг над целыми числами
<?php
/*
* Несколько примеров.
*/
echo "\n--- СДВИГ ВПРАВО НАД ПОЛОЖИТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ ---\n";
$val = 4;
$places = 1;
$res = $val >> $places;
p($res, $val, '>>', $places, 'слева была вставлена копия знакового бита');
$val = 4;
$places = 2;
$res = $val >> $places;
p($res, $val, '>>', $places);
$val = 4;
$places = 3;
$res = $val >> $places;
p($res, $val, '>>', $places, 'биты были выдвинуты за правый край');
$val = 4;
$places = 4;
$res = $val >> $places;
p($res, $val, '>>', $places, 'то же, что и выше; нельзя сдвинуть дальше 0');
echo "\n--- СДВИГ ВПРАВО НАД ОТРИЦАТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ ---\n";
$val = -4;
$places = 1;
$res = $val >> $places;
p($res, $val, '>>', $places, 'слева была вставлена копия знакового бита');
$val = -4;
$places = 2;
$res = $val >> $places;
p($res, $val, '>>', $places, 'биты были выдвинуты за правый край');
$val = -4;
$places = 3;
$res = $val >> $places;
p($res, $val, '>>', $places, 'то же, что и выше; нельзя сдвинуть дальше -1');
echo "\n--- СДВИГ ВЛЕВО НАД ПОЛОЖИТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ ---\n";
$val = 4;
$places = 1;
$res = $val << $places;
p($res, $val, '<<', $places, 'правый край был дополнен нулями');
$val = 4;
$places = (PHP_INT_SIZE * 8) - 4;
$res = $val << $places;
p($res, $val, '<<', $places);
$val = 4;
$places = (PHP_INT_SIZE * 8) - 3;
$res = $val << $places;
p($res, $val, '<<', $places, 'знаковые биты были выдвинуты');
$val = 4;
$places = (PHP_INT_SIZE * 8) - 2;
$res = $val << $places;
p($res, $val, '<<', $places, 'биты были выдвинуты за левый край');
echo "\n--- СДВИГ ВЛЕВО НАД ОТРИЦАТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ ---\n";
$val = -4;
$places = 1;
$res = $val << $places;
p($res, $val, '<<', $places, 'правый край был дополнен нулями');
$val = -4;
$places = (PHP_INT_SIZE * 8) - 3;
$res = $val << $places;
p($res, $val, '<<', $places);
$val = -4;
$places = (PHP_INT_SIZE * 8) - 2;
$res = $val << $places;
p($res, $val, '<<', $places, 'биты были выдвинуты за левый край, включая знаковый бит');
/*
* Не обращайте внимания на этот нижний раздел кода,
* это просто форматирование для более ясного вывода.
*/
function p($res, $val, $op, $places, $note = '') {
$format = '%0' . (PHP_INT_SIZE * 8) . "b\n";
printf("Выражение: %d = %d %s %d\n", $res, $val, $op, $places);
echo " Десятичный вид:\n";
printf(" val=%d\n", $val);
printf(" res=%d\n", $res);
echo " Двоичный вид:\n";
printf(' val=' . $format, $val);
printf(' res=' . $format, $res);
if ($note) {
echo " ЗАМЕЧАНИЕ: $note\n";
}
echo "\n";
}
?>Результат выполнения данного примера на 32-битных машинах:
--- СДВИГ ВПРАВО НАД ПОЛОЖИТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ --- Выражение: 2 = 4 >> 1 Десятичный вид: val=4 res=2 Двоичный вид: val=00000000000000000000000000000100 res=00000000000000000000000000000010 ЗАМЕЧАНИЕ: слева была вставлена копия знакового бита Выражение: 1 = 4 >> 2 Десятичный вид: val=4 res=1 Двоичный вид: val=00000000000000000000000000000100 res=00000000000000000000000000000001 Выражение: 0 = 4 >> 3 Десятичный вид: val=4 res=0 Двоичный вид: val=00000000000000000000000000000100 res=00000000000000000000000000000000 ЗАМЕЧАНИЕ: биты были выдвинуты за правый край Выражение: 0 = 4 >> 4 Десятичный вид: val=4 res=0 Двоичный вид: val=00000000000000000000000000000100 res=00000000000000000000000000000000 ЗАМЕЧАНИЕ: то же, что и выше; нельзя сдвинуть дальше 0 --- СДВИГ ВПРАВО НА ОТРИЦАТЕЛЬНЫХ ЦЕЛЫХ ЧИСЛАХ --- Выражение: -2 = -4 >> 1 Десятичный вид: val=-4 res=-2 Двоичный вид: val=11111111111111111111111111111100 res=11111111111111111111111111111110 ЗАМЕЧАНИЕ: слева была вставлена копия знакового бита Выражение: -1 = -4 >> 2 Десятичный вид: val=-4 res=-1 Двоичный вид: val=11111111111111111111111111111100 res=11111111111111111111111111111111 ЗАМЕЧАНИЕ: биты были выдвинуты за правый край Выражение: -1 = -4 >> 3 Десятичный вид: val=-4 res=-1 Двоичный вид: val=11111111111111111111111111111100 res=11111111111111111111111111111111 ЗАМЕЧАНИЕ: то же, что и выше; нельзя сдвинуть дальше -1 --- СДВИГ ВЛЕВО НАД ПОЛОЖИТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ --- Выражение: 8 = 4 << 1 Десятичный вид: val=4 res=8 Двоичный вид: val=00000000000000000000000000000100 res=00000000000000000000000000001000 ЗАМЕЧАНИЕ: правый край был дополнен нулями Выражение: 1073741824 = 4 << 28 Десятичный вид: val=4 res=1073741824 Двоичный вид: val=00000000000000000000000000000100 res=01000000000000000000000000000000 Выражение: -2147483648 = 4 << 29 Десятичный вид: val=4 res=-2147483648 Двоичный вид: val=00000000000000000000000000000100 res=10000000000000000000000000000000 ЗАМЕЧАНИЕ: знаковые биты были выдвинуты Выражение: 0 = 4 << 30 Десятичный вид: val=4 res=0 Двоичный вид: val=00000000000000000000000000000100 res=00000000000000000000000000000000 ЗАМЕЧАНИЕ: биты были выдвинуты за левый край --- СДВИГ ВЛЕВО НАД ОТРИЦАТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ --- Выражение: -8 = -4 << 1 Десятичный вид: val=-4 res=-8 Двоичный вид: val=11111111111111111111111111111100 res=11111111111111111111111111111000 ЗАМЕЧАНИЕ: правый край был дополнен нулями Выражение: -2147483648 = -4 << 29 Десятичный вид: val=-4 res=-2147483648 Двоичный вид: val=11111111111111111111111111111100 res=10000000000000000000000000000000 Выражение: 0 = -4 << 30 Десятичный вид: val=-4 res=0 Двоичный вид: val=11111111111111111111111111111100 res=00000000000000000000000000000000 ЗАМЕЧАНИЕ: биты были выдвинуты за левый край, включая знаковый бит
Результат выполнения данного примера на 64-битных машинах:
--- СДВИГ ВПРАВО НАД ПОЛОЖИТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ --- Выражение: 2 = 4 >> 1 Десятичный вид: val=4 res=2 Двоичный вид: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000010 ЗАМЕЧАНИЕ: слева была вставлена копия знакового бита Выражение: 1 = 4 >> 2 Десятичный вид: val=4 res=1 Двоичный вид: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000001 Выражение: 0 = 4 >> 3 Десятичный вид: val=4 res=0 Двоичный вид: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000000 ЗАМЕЧАНИЕ: биты были выдвинуты за правый край Выражение: 0 = 4 >> 4 Десятичный вид: val=4 res=0 Двоичный вид: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000000 ЗАМЕЧАНИЕ: то же, что и выше; нельзя сдвинуть дальше 0 --- СДВИГ ВПРАВО НАД ОТРИЦАТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ --- Выражение: -2 = -4 >> 1 Десятичный вид: val=-4 res=-2 Двоичный вид: val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111110 ЗАМЕЧАНИЕ: слева была вставлена копия знакового бита Выражение: -1 = -4 >> 2 Десятичный вид: val=-4 res=-1 Двоичный вид: val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111111 ЗАМЕЧАНИЕ: биты были выдвинуты за правый край Выражение: -1 = -4 >> 3 Десятичный вид: val=-4 res=-1 Двоичный вид: val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111111 ЗАМЕЧАНИЕ: то же, что и выше; нельзя сдвинуть дальше -1 --- СДВИГ ВЛЕВО НАД ПОЛОЖИТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ --- Выражение: 8 = 4 << 1 Десятичный вид: val=4 res=8 Двоичный вид: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000001000 ЗАМЕЧАНИЕ: правый край был дополнен нулями Выражение: 4611686018427387904 = 4 << 60 Десятичный вид: val=4 res=4611686018427387904 Двоичный вид: val=0000000000000000000000000000000000000000000000000000000000000100 res=0100000000000000000000000000000000000000000000000000000000000000 Выражение: -9223372036854775808 = 4 << 61 Десятичный вид: val=4 res=-9223372036854775808 Двоичный вид: val=0000000000000000000000000000000000000000000000000000000000000100 res=1000000000000000000000000000000000000000000000000000000000000000 ЗАМЕЧАНИЕ: знаковые биты были выдвинуты Выражение: 0 = 4 << 62 Десятичный вид: val=4 res=0 Двоичный вид: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000000 ЗАМЕЧАНИЕ: биты были выдвинуты за левый край --- СДВИГ ВЛЕВО НАД ОТРИЦАТЕЛЬНЫМИ ЦЕЛЫМИ ЧИСЛАМИ --- Выражение: -8 = -4 << 1 Десятичный вид: val=-4 res=-8 Двоичный вид: val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111000 ЗАМЕЧАНИЕ: правый край был дополнен нулями Выражение: -9223372036854775808 = -4 << 61 Десятичный вид: val=-4 res=-9223372036854775808 Двоичный вид: val=1111111111111111111111111111111111111111111111111111111111111100 res=1000000000000000000000000000000000000000000000000000000000000000 Выражение: 0 = -4 << 62 Десятичный вид: val=-4 res=0 Двоичный вид: val=1111111111111111111111111111111111111111111111111111111111111100 res=0000000000000000000000000000000000000000000000000000000000000000 ЗАМЕЧАНИЕ: биты были выдвинуты за левый край, включая знаковый бит
Используйте функции из модуля gmp для побитовых
операций над числами, большими чем PHP_INT_MAX.
Операторы сравнения, как это видно из их названия, позволяют сравнивать между собой два значения. Возможно вам будет интересно также ознакомиться с разделом Сравнение типов, в котором приведено большое количество соответствующих примеров.
| Пример | Название | Результат |
|---|---|---|
| $a == $b | Равно | true если $a равно $b
после преобразования типов. |
| $a === $b | Тождественно равно |
true если $a равно $b и имеет тот же тип.
|
| $a != $b | Не равно | true если $a не равно $b
после преобразования типов. |
| $a <> $b | Не равно | true если $a не равно $b
после преобразования типов. |
| $a !== $b | Тождественно не равно |
true если $a не равно $b, или они разных типов.
|
| $a < $b | Меньше | true если $a строго меньше $b. |
| $a > $b | Больше | true если $a строго больше $b. |
| $a <= $b | Меньше или равно | true если $a меньше или равно $b. |
| $a >= $b | Больше или равно | true если $a больше или равно $b. |
| $a <=> $b | Космический корабль (spaceship) | Число типа int меньше, больше или равное нулю, когда $a соответственно меньше, больше или равно $b. |
В случае, если оба операнда являются
строками, содержащими числа
или один операнд является числом, а другой - строкой, содержащей числа,
то сравнение выполняется численно.
Эти правила также применяются к оператору switch.
Преобразование типа не происходит при сравнении
=== или !==, поскольку это включает сравнение
типа, а также значения.
До PHP 8.0.0, если строка (string) сравнивалась с числом или строкой, содержащей число, то строка (string) преобразовывалось в число перед выполнением сравнения. Это могло привести к неожиданным результатам, что можно увидеть на следующем примере:
<?php
var_dump(0 == "a");
var_dump("1" == "01");
var_dump("10" == "1e1");
var_dump(100 == "1e2");
switch ("a") {
case 0:
echo "0";
break;
case "a":
echo "a";
break;
}
?>Результат выполнения данного примера в PHP 7:
bool(true) bool(true) bool(true) bool(true) 0
Результат выполнения данного примера в PHP 8:
bool(false) bool(true) bool(true) bool(true) a
<?php
// Целые числа
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
// Числа с плавающей точкой
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
// Строки
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
echo "a" <=> "aa"; // -1
echo "zz" <=> "aa"; // 1
// Массивы
echo [] <=> []; // 0
echo [1, 2, 3] <=> [1, 2, 3]; // 0
echo [1, 2, 3] <=> []; // 1
echo [1, 2, 3] <=> [1, 2, 1]; // 1
echo [1, 2, 3] <=> [1, 2, 4]; // -1
// Объекты
$a = (object) ["a" => "b"];
$b = (object) ["a" => "b"];
echo $a <=> $b; // 0
$a = (object) ["a" => "b"];
$b = (object) ["a" => "c"];
echo $a <=> $b; // -1
$a = (object) ["a" => "c"];
$b = (object) ["a" => "b"];
echo $a <=> $b; // 1
// сравниваются не только значения; ключи также должны совпадать
$a = (object) ["a" => "b"];
$b = (object) ["b" => "b"];
echo $a <=> $b; // 1
?>Для различных типов сравнение происходит в соответствии со следующей таблицей (по порядку).
| Тип операнда 1 | Тип операнда 2 | Результат |
|---|---|---|
| null или string | string | null преобразуется в "", числовое или лексическое сравнение |
| bool или null | что угодно | Преобразуется в тип bool, false < true |
| object | object | Встроенные классы могут определять свои собственные правила сравнения, объекты разных классов не сравниваются, про сравнение объектов одного класса смотрите Сравнение объекта |
| string, resource, int или float | string, resource, int или float | Строки и ресурсы переводятся в числа, обычная математика |
| array | array | Массивы с меньшим числом элементов считаются меньше, если ключ из первого операнда не найден во втором операнде - массивы не могут сравниваться, иначе идёт сравнение соответствующих значений (смотрите пример ниже) |
| array | что угодно | тип array всегда больше |
| object | что угодно | тип object всегда больше |
Пример #1 Сравнение boolean/null
<?php
// Логические значения и null всегда сравниваются как логические
var_dump(1 == TRUE); // TRUE - то же, что и (bool)1 == TRUE
var_dump(0 == FALSE); // TRUE - то же, что и (bool)0 == FALSE
var_dump(100 < TRUE); // FALSE - то же, что и (bool)100 < TRUE
var_dump(-10 < FALSE);// FALSE - то же, что и (bool)-10 < FALSE
var_dump(min(-100, -10, NULL, 10, 100)); // NULL - (bool)NULL < (bool)-100 это FALSE < TRUE
?>
Пример #2 Алгоритм сравнения обычных массивов
<?php
// Массивы сравниваются таким образом с помощью стандартных операторов сравнения, а также оператора spaceship.
function standard_array_compare($op1, $op2)
{
if (count($op1) < count($op2)) {
return -1; // $op1 < $op2
} elseif (count($op1) > count($op2)) {
return 1; // $op1 > $op2
}
foreach ($op1 as $key => $val) {
if (!array_key_exists($key, $op2)) {
return 1;
} elseif ($val < $op2[$key]) {
return -1;
} elseif ($val > $op2[$key]) {
return 1;
}
}
return 0; // $op1 == $op2
}
?>Из-за особого внутреннего представления типа float, не нужно проверять на равенство два числа с плавающей точкой (float).
Для более подробной информации смотрите документацию по типу float.
Замечание: Помните, что жонглирование типами в PHP не всегда очевидно при сравнении значений разных типов, особенно при сравнении целых чисел (int) с логическими значениями (bool) или целых чисел (int) со строками (string). Поэтому в большинстве случаев рекомендуется использовать сравнения
===и!==, а не==и!=.
В то время как сравнение тождества (=== и !==)
можно применять к произвольным значениям, другие операторы сравнения следует применять только к сравнимым значениям.
Результат сравнения несравнимых значений не определён и на него не следует полагаться.
Ещё одним условным оператором является тернарный оператор "?:".
Пример #3 Присваивание значения по умолчанию
<?php
// Пример использования тернарного оператора
$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];
// Приведённый выше код аналогичен следующему блоку с использованием if/else
if (empty($_POST['action'])) {
$action = 'default';
} else {
$action = $_POST['action'];
}
?>(expr1) ? (expr2) : (expr3)
интерпретируется как expr2, если
expr1 имеет значение true, или как
expr3, если
expr1 имеет значение false.
Также стало возможным не писать среднюю часть
тернарного оператора. Выражение expr1 ?: expr3 оценивается
как результат expr1, если результат выражения expr1 оценивается как true
и expr3 в противном случае.
Выражение expr1 в этом случае оценивается только один раз.
Замечание: Обратите внимание, что тернарный оператор является выражением и трактуется не как переменная, а как результат выражения. Это важно знать, если вы хотите вернуть переменную по ссылке. Выражение
return $var == 42 ? $a : $b;не будет работать в функции, возвращающей значение по ссылке, а в более поздних версиях PHP также будет выдано предупреждение.
Замечание:
Рекомендуется избегать "нагромождения" тернарных выражений. Поведение PHP неочевидно при использовании более чем одного тернарного оператора без скобок в одном выражении по сравнению с другими языками. Действительно, до PHP 8.0.0 троичные выражения оценивались лево-ассоциативными, а не право-ассоциативными, как в большинстве других языков программирования. Использование лево-ассоциативности устарело в PHP 7.4.0. Начиная с PHP 8.0.0, тернарный оператор неассоциативен.
Пример #4 Неочевидное поведение тернарного оператора
<?php
// на первый взгляд, следующий код должен вывести 'true'
echo (true ? 'true' : false ? 't' : 'f');
// однако, он выводит 't' до PHP 8.0.0
// это потому, что тернарные выражения левоассоциативны
// это намного более очевидная версия вышеприведённого кода
echo ((true ? 'true' : false) ? 't' : 'f');
// здесь видно, что первое выражение вычисляется в 'true', которое
// в свою очередь вычисляется в (bool)true, таким образом возвращая истинную ветвь
// второго тернарного выражения.
?>
Замечание:
Цепочка коротких тернарных операторов (
?:) стабильна и ведёт себя разумно. Она будет оценивать первый аргумент, который оценивается как не ложное значение. Обратите внимание, что неопределённые значения все равно вызовут предупреждение.Пример #5 Цепочка коротких тернарных операторов
<?php
echo 0 ?: 1 ?: 2 ?: 3, PHP_EOL; //1
echo 0 ?: 0 ?: 2 ?: 3, PHP_EOL; //2
echo 0 ?: 0 ?: 0 ?: 3, PHP_EOL; //3
?>
Другим полезным сокращённым оператором является оператор "??" (null coalescing).
Пример #6 Присваивание значения по умолчанию
<?php
// Пример использования оператора
$action = $_POST['action'] ?? 'default';
// Пример выше аналогичен следующему коду
if (isset($_POST['action'])) {
$action = $_POST['action'];
} else {
$action = 'default';
}
?>(expr1) ?? (expr2) вычисляется так:
expr2, если expr1 равен
null и expr1 в противном случае.
На практике, этот оператор не вызывает предупреждения или ошибки, если левый операнд не существует, как и isset(). Это очень полезно для ключей массива.
Замечание: Пожалуйста помните, что этот оператор является выражением, и он приравнивается к выражению, а не значению переменной. Это может быть важным, если вы хотите вернуть значение по ссылке. Выражение
return $foo ?? $bar;в функции возвращающей ссылку будет не работать, а выводить предупреждение.
Замечание:
У оператора null coalescing низкий приоритет. Это означает, что при смешивании его с другими операторами (такими как конкатенация строк или арифметические операторы), скорее всего, потребуются круглые скобки.
<?php
// Вызывает предупреждение о том, что $name не определено.
print 'Mr. ' . $name ?? 'Anonymous';
// Выведет "Mr. Anonymous"
print 'Mr. ' . ($name ?? 'Anonymous');
?>
Замечание:
Обратите внимание, что этот оператор позволяет использовать простую вложенность:
Пример #7 Вложенный оператор null coalescing
<?php
$foo = null;
$bar = null;
$baz = 1;
$qux = 2;
echo $foo ?? $bar ?? $baz ?? $qux; // выведет 1
?>
PHP поддерживает один оператор управления ошибками: знак @.
В случае, если он предшествует какому-либо выражению в PHP-коде, любые
сообщения об ошибках, генерируемые этим выражением, будут подавлены.
Если пользовательская функция обработчика ошибок установлена с помощью set_error_handler(), она всё равно будет вызываться, даже если диагностика была подавлена.
До версии PHP 8.0.0 функция error_reporting(), вызываемая внутри пользовательского обработчика ошибок,
всегда возвращала 0, если ошибка была подавлена оператором @.
Начиная с PHP 8.0.0, она возвращает значение E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR | E_PARSE.
Любое сообщение об ошибке, сгенерированное выражением, доступно
в элементе массива "message", возвращаемого error_get_last().
Результат этой функции будет меняться при каждой ошибке, поэтому его необходимо проверить заранее.
<?php
// Преднамеренная ошибка при работе с файлами
$my_file = @file ('non_existent_file') or
die ("Ошибка при открытии файла: сообщение об ошибке было таким: '" . error_get_last()['message'] . "'");
// работает для любых выражений, а не только для функций
$value = @$cache[$key];
// В случае если ключа $key нет, сообщение об ошибке (notice) не будет отображено
?>Замечание: Оператор
@работает только с выражениями. Есть простое правило: если что-то возвращает значение, значит вы можете использовать перед ним оператор@. Например, вы можете использовать@перед именем переменной, произвольной функцией или вызовом include и так далее. В то же время вы не можете использовать этот оператор перед определением функции или класса, условными конструкциями, такими какif, foreach и т.д.
До PHP 8.0.0 оператор @ мог подавлять критические ошибки, которые прерывали выполнение скрипта.
Например, добавление @ к вызову несуществующей функции,
в случае, если она недоступна или написана неправильно, дальнейшая
работа скрипта приведёт к прерыванию выполнения скрипта без каких-либо уведомлений.
PHP поддерживает один оператор исполнения: обратные кавычки (``). Обратите внимание, что это не одинарные кавычки! PHP попытается выполнить строку, заключённую в обратные кавычки, как консольную команду, и вернёт полученный вывод (то есть он не просто выводится на экран, а, например, может быть присвоен переменной). Использование обратных кавычек аналогично использованию функции shell_exec().
<?php
$output = `ls -al`;
echo "<pre>$output</pre>";
?>Замечание:
Обратные кавычки недоступны, в случае, если отключена функция shell_exec().
Замечание:
В отличие от некоторых других языков, обратные кавычки не будут работать внутри строк в двойных кавычках.
PHP поддерживает префиксные и постфиксные операторы инкремента и декремента в стиле C.
Замечание: Операторы инкремента/декремента влияют только на числа и строки. Массивы, объекты, булевы значения и ресурсы не будут изменены. Декремент
nullтакже не даст никакого эффекта, однако инкремент даст значение1.
| Пример | Название | Действие |
|---|---|---|
| ++$a | Префиксный инкремент | Увеличивает $a на единицу, затем возвращает значение $a. |
| $a++ | Постфиксный инкремент | Возвращает значение $a, затем увеличивает $a на единицу. |
| --$a | Префиксный декремент | Уменьшает $a на единицу, затем возвращает значение $a. |
| $a-- | Постфиксный декремент | Возвращает значение $a, затем уменьшает $a на единицу. |
Приведём пример простого скрипта:
<?php
echo "<h3>Постфиксный инкремент</h3>";
$a = 5;
echo "Должно быть 5: " . $a++ . "<br />\n";
echo "Должно быть 6: " . $a . "<br />\n";
echo "<h3>Префиксный инкремент</h3>";
$a = 5;
echo "Должно быть 6: " . ++$a . "<br />\n";
echo "Должно быть 6: " . $a . "<br />\n";
echo "<h3>Постфиксный декремент</h3>";
$a = 5;
echo "Должно быть 5: " . $a-- . "<br />\n";
echo "Должно быть 4: " . $a . "<br />\n";
echo "<h3>Префиксный декремент</h3>";
$a = 5;
echo "Должно быть 4: " . --$a . "<br />\n";
echo "Должно быть 4: " . $a . "<br />\n";
?>
PHP следует соглашениям Perl (в отличие от С) касательно выполнения
арифметических операций с символьными переменными. Например, в PHP и Perl
$a = 'Z'; $a++; присвоит $a
значение 'AA', в то время как в C
a = 'Z'; a++; присвоит a
значение '[' (ASCII-значение
'Z' равно 90, а ASCII-значение
'[' равно 91). Следует учесть, что к
символьным переменным можно применять операцию инкремента,
в то время как операцию декремента применять нельзя, кроме того,
поддерживаются только ASCII-символы (a-z, A-Z и 0-9).
Попытка инкремента/декремента других символьных переменных не
будет иметь никакого эффекта, исходная строка останется
неизменной.
Пример #1 Арифметические операции с символьными переменными
<?php
echo '== Буквенные строки ==' . PHP_EOL;
$s = 'W';
for ($n=0; $n<6; $n++) {
echo ++$s . PHP_EOL;
}
// Буквенно-цифровые строки ведут себя по-разному
echo '== Буквенно-цифровые строки ==' . PHP_EOL;
$d = 'A8';
for ($n=0; $n<6; $n++) {
echo ++$d . PHP_EOL;
}
$d = 'A08';
for ($n=0; $n<6; $n++) {
echo ++$d . PHP_EOL;
}
?>Результат выполнения данного примера:
== Буквенные строки == X Y Z AA AB AC == Буквенно-цифровые строки == A9 B0 B1 B2 B3 B4 A09 A10 A11 A12 A13 A14
Инкрементирование или декрементирование булевых переменных не приводит ни к какому результату.
| Пример | Название | Результат |
|---|---|---|
| $a and $b | И | true, если и $a, и $b true. |
| $a or $b | Или | true, если или $a, или $b true. |
| $a xor $b | Исключающее или | true, если $a, или $b true, но не оба. |
| ! $a | Отрицание | true, если $a не true. |
| $a && $b | И | true, если и $a, и $b true. |
| $a || $b | Или | true, если или $a, или $b true. |
Смысл двух разных вариантов для операторов "and" и "or" в том, что они работают с различными приоритетами (смотрите таблицу Приоритет выполнения операторов).
Пример #1 Объяснение логических операторов
<?php
// --------------------
// foo() никогда не будет вызвана, т.к. эти операторы являются шунтирующими (short-circuit)
$a = (false && foo());
$b = (true || foo());
$c = (false and foo());
$d = (true or foo());
// --------------------
// "||" имеет больший приоритет, чем "or"
// Результат выражения (false || true) присваивается переменной $e
// Действует как: ($e = (false || true))
$e = false || true;
// Константа false присваивается $f, а затем значение true игнорируется
// Действует как: (($f = false) or true)
$f = false or true;
var_dump($e, $f);
// --------------------
// "&&" имеет больший приоритет, чем "and"
// Результат выражения (true && false) присваивается переменной $g
// Действует как: ($g = (true && false))
$g = true && false;
// Константа true присваивается $h, а затем значение false игнорируется
// Действует как: (($h = true) and false)
$h = true and false;
var_dump($g, $h);
?>Результатом выполнения данного примера будет что-то подобное:
bool(true) bool(false) bool(false) bool(true)
В PHP есть два оператора для работы со строками (string).
Первый - оператор конкатенации ('.'), который возвращает строку, представляющую
собой соединение левого и правого аргумента. Второй - оператор присваивания с
конкатенацией ('.='), который присоединяет правый аргумент к левому.
Для получения более полной информации ознакомьтесь с разделом
Операторы присваивания.
<?php
$a = "Привет, ";
$b = $a . "Мир!"; // $b теперь содержит строку "Привет, Мир!"
$a = "Привет, ";
$a .= "Мир!"; // $a теперь содержит строку "Привет, Мир!"
?>| Пример | Название | Результат |
|---|---|---|
| $a + $b | Объединение | Объединение массива $a и массива $b. |
| $a == $b | Равно | true в случае, если $a и $b содержат одни и те же пары ключ/значение. |
| $a === $b | Тождественно равно | true в случае, если $a и $b
содержат одни и те же пары ключ/значение в том же самом порядке и того же типа.
|
| $a != $b | Не равно | true, если массив $a не равен массиву $b. |
| $a <> $b | Не равно | true, если массив $a не равен массиву $b. |
| $a !== $b | Тождественно не равно | true, если массив $a не равен тождественно массиву $b. |
Оператор + возвращает левый массив, к которому
был присоединён правый массив. Для ключей, которые существуют в
обоих массивах, будут использованы значения из левого массива, а
соответствующие им элементы из правого массива будут проигнорированы.
<?php
$a = array("a" => "apple", "b" => "banana");
$b = array("a" => "pear", "b" => "strawberry", "c" => "cherry");
$c = $a + $b; // Объединение $a и $b
echo "Объединение \$a и \$b: \n";
var_dump($c);
$c = $b + $a; // Объединение $b и $a
echo "Объединение \$b и \$a: \n";
var_dump($c);
$a += $b; // Объединение $a += $b, это $a и $b
echo "Объединение \$a += \$b: \n";
var_dump($a);
?>
Объединение $a и $b:
array(3) {
["a"]=>
string(5) "apple"
["b"]=>
string(6) "banana"
["c"]=>
string(6) "cherry"
}
Объединение $b и $a:
array(3) {
["a"]=>
string(4) "pear"
["b"]=>
string(10) "strawberry"
["c"]=>
string(6) "cherry"
}
Объединение $a += $b:
array(3) {
["a"]=>
string(5) "apple"
["b"]=>
string(6) "banana"
["c"]=>
string(6) "cherry"
}
При сравнении элементы массива считаются идентичными, если совпадает и ключ, и соответствующее ему значение.
Пример #1 Сравнение массивов
<?php
$a = array("apple", "banana");
$b = array(1 => "banana", "0" => "apple");
var_dump($a == $b); // bool(true)
var_dump($a === $b); // bool(false)
?>
Оператор instanceof используется для определения того,
является ли текущий объект экземпляром указанного
класса.
Пример #1 Использование instanceof с классами
<?php
class MyClass
{
}
class NotMyClass
{
}
$a = new MyClass;
var_dump($a instanceof MyClass);
var_dump($a instanceof NotMyClass);
?>Результат выполнения данного примера:
bool(true) bool(false)
Оператор instanceof также может быть использован
для определения, наследует ли определённый объект какой-либо класс:
Пример #2 Использование instanceof с наследуемыми классами
<?php
class ParentClass
{
}
class MyClass extends ParentClass
{
}
$a = new MyClass;
var_dump($a instanceof MyClass);
var_dump($a instanceof ParentClass);
?>Результат выполнения данного примера:
bool(true) bool(true)
Для проверки непринадлежности объекта некоторому классу,
используйте логический оператор
not.
Пример #3 Использование instanceof для проверки того, что объект
не является экземпляром класса
<?php
class MyClass
{
}
$a = new MyClass;
var_dump(!($a instanceof stdClass));
?>Результат выполнения данного примера:
bool(true)
Наконец, instanceof может быть также использован для проверки
реализации объектом некоторого интерфейса:
Пример #4 Использование instanceof с интерфейсами
<?php
interface MyInterface
{
}
class MyClass implements MyInterface
{
}
$a = new MyClass;
var_dump($a instanceof MyClass);
var_dump($a instanceof MyInterface);
?>Результат выполнения данного примера:
bool(true) bool(true)
Хотя instanceof обычно используется с прямо указанным именем класса,
он также может быть использован с другим объектом или строковой переменной:
Пример #5 Использование instanceof с другими переменными
<?php
interface MyInterface
{
}
class MyClass implements MyInterface
{
}
$a = new MyClass;
$b = new MyClass;
$c = 'MyClass';
$d = 'NotMyClass';
var_dump($a instanceof $b); // $b - объект класса MyClass
var_dump($a instanceof $c); // $c - строка 'MyClass'
var_dump($a instanceof $d); // $d - строка 'NotMyClass'
?>Результат выполнения данного примера:
bool(true) bool(true) bool(false)
Оператор instanceof не генерирует никаких ошибок, если проверяемая переменная не
является объектом. В этом случае он просто возвращает false. Константы, тем не менее,
не допускались до PHP 7.3.0.
Пример #6 Пример использования оператора instanceof для проверки других переменных
<?php
$a = 1;
$b = NULL;
$c = imagecreate(5, 5);
var_dump($a instanceof stdClass); // $a - целое типа integer
var_dump($b instanceof stdClass); // $b - NULL
var_dump($c instanceof stdClass); // $c - значение типа resource
var_dump(FALSE instanceof stdClass);
?>Результат выполнения данного примера:
bool(false) bool(false) bool(false) PHP Fatal error: instanceof expects an object instance, constant given
Начиная с PHP 7.3.0, константы разрешены в левой части оператора instanceof.
Пример #7 Использование instanceof для проверки констант
<?php
var_dump(FALSE instanceof stdClass);
?>Результат выполнения данного примера в PHP 7.3:
bool(false)
Начиная с PHP 8.0.0, instanceof теперь можно использовать с произвольными выражениями.
Выражение должно быть заключено в круглые скобки и представлять собой строку (string).
Пример #8 Пример использования instanceof с произвольным выражением
<?php
class ClassA extends \stdClass {}
class ClassB extends \stdClass {}
class ClassC extends ClassB {}
class ClassD extends ClassA {}
function getSomeClass(): string
{
return ClassA::class;
}
var_dump(new ClassA instanceof ('std' . 'Class'));
var_dump(new ClassB instanceof ('Class' . 'B'));
var_dump(new ClassC instanceof ('Class' . 'A'));
var_dump(new ClassD instanceof (getSomeClass()));
?>Результат выполнения данного примера в PHP 8:
bool(true) bool(true) bool(false) bool(true)
Оператор instanceof аналогичен функции is_a().
Любой сценарий PHP состоит из последовательности инструкций. Инструкцией может быть присваивание, вызов функции, повтор кода (цикл), сравнение, или даже инструкция, которая ничего не делает (пустой оператор). После инструкции обычно ставится точка с запятой. Кроме того, инструкции могут быть объединены в блоки заключением их в фигурные скобки. Блок инструкций также сам по себе является инструкцией. В этом разделе описываются различные типы инструкций.
(PHP 4, PHP 5, PHP 7, PHP 8)
Конструкция if является одной из наиболее важных
во многих языках программирования, в том числе и PHP. Она предоставляет возможность
условного выполнения фрагментов кода. Структура if
реализована в PHP по аналогии с языком C:
if (выражение) инструкция
Как описано в разделе про
выражения, выражение вычисляется в
булево значение. Если выражение принимает значение true,
PHP выполнит инструкцию, а если оно принимает значение
false - проигнорирует. Информацию о том, какие значения считаются равными
значению false, можно найти в разделе 'Преобразование в булев тип'.
Следующий пример выведет a больше b, если значение переменной $a больше, чем $b:
<?php
if ($a > $b)
echo "a больше b";
?>
Часто необходимо, чтобы условно выполнялось более одной инструкции.
Разумеется, для этого нет необходимости помещать каждую инструкцию в
if. Вместо этого можно объединить несколько инструкций в блок.
Например, следующий код выведет a больше b,
если значение переменной $a больше, чем
$b, а затем присвоит значение переменной
$a переменной $b:
<?php
if ($a > $b) {
echo "a больше b";
$b = $a;
}
?>
Инструкции if могут быть бесконечно вложены
в другие инструкции if,
что даёт большую гибкость в организации условного выполнения
различных частей программы.
(PHP 4, PHP 5, PHP 7, PHP 8)
Часто необходимо выполнить одно выражение, если определённое условие
верно, и другое выражение, если условие не верно. Именно
для этого else и используется. else
расширяет оператор if, чтобы выполнить выражение,
в случае, если условие в операторе if
равно false. К примеру,
следующий код выведет a больше чем
b, если $a больше, чем
$b, и a НЕ больше,
чем b в противном случае:
<?php
if ($a > $b) {
echo "a больше, чем b";
} else {
echo "a НЕ больше, чем b";
}
?>else выполняется только, если
выражение if вычисляется как
false, и если нет других любых
выражений elseif, или если они все равны
false также (смотрите elseif).
Замечание: Болтающийся else
В случае вложенных операторов
if-else,elseвсегда ассоциируется с ближайшимif.Несмотря на отступ (который не имеет значения в PHP),<?php
$a = false;
$b = true;
if ($a)
if ($b)
echo "b";
else
echo "c";
?>elseсвязан сif ($b), поэтому этот пример ничего не выведет. Хотя такое поведение допустимо, рекомендуется его избегать, используя фигурные скобки для устранения потенциальных неоднозначностей.
(PHP 4, PHP 5, PHP 7, PHP 8)
Конструкция elseif, как её имя и говорит есть сочетание
if и else. Аналогично
else, она расширяет оператор if
для выполнения различных выражений в случае, когда условие начального оператора
if эквивалентно
false. Однако, в отличие от
else, выполнение альтернативного
выражения произойдёт только тогда, когда условие оператора elseif
будет являться равным true. К примеру,
следующий код может выводить a больше, чем
b, a равно b
или a меньше, чем b:
<?php
if ($a > $b) {
echo "a больше, чем b";
} elseif ($a == $b) {
echo "a равен b";
} else {
echo "a меньше, чем b";
}
?>
Может быть несколько elseif в одном
выражении if. Первое выражение
elseif (если оно есть) равное
true будет выполнено. В PHP вы также можете
написать else if (в два слова), и тогда поведение будет идентичным
elseif' (в одно слово). Синтаксически значение
немного отличается (то же поведение, что и у C),
но в конечном итоге оба выражения приведут к одному и
тому же результату.
Выражение elseif выполнится, если
предшествующее выражение if и предшествующие
выражения elseif эквивалентны
false, а текущий
elseif равен
true.
Замечание: Заметьте, что
elseifиelse ifбудут равнозначны только при использовании фигурных скобок, как в примерах выше. Если используются синтаксис с двоеточием для определения условийif/elseif, возникает необходимость использованияelseifв одном слове. Если разбитьelse ifна два слова, PHP выдаст ошибку разбора.
<?php
/* Некорректный способ: */
if($a > $b):
echo $a." больше, чем ".$b;
else if($a == $b): // Не скомпилируется.
echo "Строка выше вызывает фатальную ошибку.";
endif;
/* Корректный способ: */
if($a > $b):
echo $a." больше, чем ".$b;
elseif($a == $b): // Заметьте, тут одно слово.
echo $a." равно ".$b;
else:
echo $a." не больше и не равно ".$b;
endif;
?>(PHP 4, PHP 5, PHP 7, PHP 8)
PHP предлагает альтернативный синтаксис для некоторых его
управляющих структур, а именно: if,
while, for,
foreach и switch.
В каждом случае основной формой альтернативного синтаксиса является изменение
открывающей фигурной скобки на двоеточие (:), а закрывающей скобки
на endif;, endwhile;,
endfor;, endforeach; или
endswitch; соответственно.
<?php if ($a == 5): ?>
A равно 5
<?php endif; ?>
В приведённом выше примере, блок HTML "A равно 5" вложен внутрь
структуры if, написанной с альтернативным синтаксисом.
Блок HTML будет показан только если переменная $a равна 5.
Альтернативный синтаксис также применяется и к else и
elseif. Ниже приведена структура
if с elseif и else
в альтернативном формате:
<?php
if ($a == 5):
echo "a равно 5";
echo "...";
elseif ($a == 6):
echo "a равно 6";
echo "!!!";
else:
echo "a не равно ни 5 ни 6";
endif;
?>Замечание:
Смешивание синтаксиса в одном и том же блоке управления не поддерживается.
Любой вывод (включая пробельные символы) между выражением switch
и первым case приведут к синтаксической ошибке.
Например, данный код не будет работать:
<?php switch ($foo): ?>
<?php case 1: ?>
...
<?php endswitch; ?>
В то же время следующий пример будет работать,
так как завершающий перевод строки после выражения
switch считается частью закрывающего ?>
и следовательно ничего не выводится между
switch и case:
<?php switch ($foo): ?>
<?php case 1: ?>
...
<?php endswitch; ?>(PHP 4, PHP 5, PHP 7, PHP 8)
Циклы while являются простейшим видом циклов в
PHP. Они ведут себя так же, как и в языке C. Простейшей формой
цикла while является следующее выражение:
while (expr)
statement
Смысл выражения while очень прост. Оно
указывает PHP выполнять вложенные выражения повторно до тех пор, пока
выражение в самом while является
true. Значение выражения expr проверяется
каждый раз перед началом цикла, поэтому даже если значение выражения
изменится в процессе выполнения вложенных выражений в цикле, выполнение
не прекратится до конца итерации (каждый раз, когда PHP выполняет
выражения в цикле - это одна итерация). Если
выражение while равно
false с самого начала, вложенные
выражения ни разу не будут выполнены.
Также, как и с оператором if, вы можете группировать
несколько выражений внутри одного цикла while,
заключая эти выражения между фигурными скобками или
используя альтернативный синтаксис:
while (expr):
statement
...
endwhile;
Следующие примеры идентичны, и оба выведут числа от 1 до 10:
<?php
/* пример 1 */
$i = 1;
while ($i <= 10) {
echo $i++; /* выводиться будет значение переменной
$i перед её увеличением
(post-increment) */
}
/* пример 2 */
$i = 1;
while ($i <= 10):
echo $i;
$i++;
endwhile;
?>(PHP 4, PHP 5, PHP 7, PHP 8)
Цикл do-while очень похож на цикл while,
с тем отличием, что истинность выражения проверяется в конце итерации, а не в начале.
Главное отличие от обычного цикла while в том, что
первая итерация цикла do-while гарантированно выполнится
(истинность выражения проверяется в конце итерации), тогда как она может
не выполниться в обычном цикле while (истинность выражения
которого проверяется в начале выполнения каждой итерации, и если изначально
имеет значение false, то выполнение цикла будет прервано сразу).
Есть только один вариант синтаксиса цикла do-while:
<?php
$i = 0;
do {
echo $i;
} while ($i > 0);
?>
В примере цикл будет выполнен ровно один раз, так как после первой
итерации, когда проверяется истинность выражения, она будет
вычислена как false ($i не больше 0)
и выполнение цикла прекратится.
Опытные пользователи С могут быть знакомы с другим использованием
цикла do-while, которое позволяет остановить
выполнение хода программы в середине блока, для этого нужно обернуть
нужный блок кода вызовом do-while (0) и использовать
break.
Следующий фрагмент кода демонстрирует этот подход:
<?php
do {
if ($i < 5) {
echo "i ещё недостаточно велико";
break;
}
$i *= $factor;
if ($i < $minimum_limit) {
break;
}
echo "значение i уже подходит";
/* обработка i */
} while (0);
?>
Можно использовать оператор
goto
вместо подобного "хака".
(PHP 4, PHP 5, PHP 7, PHP 8)
Цикл for самый сложный цикл в PHP.
Он ведёт себя так же, как и в языке C. Синтаксис цикла
for следующий:
for (expr1; expr2; expr3)
statement
Первое выражение (expr1) всегда вычисляется (выполняется) только один раз в начале цикла.
В начале каждой итерации оценивается выражение
expr2. Если оно принимает значение
true, то цикл продолжается и выполняются вложенные операторы.
Если оно принимает значение false, выполнение цикла заканчивается.
В конце каждой итерации выражение expr3 вычисляется (выполняется).
Каждое из выражений может быть пустым или содержать несколько
выражений, разделённых запятыми. В expr2 все
выражения, разделённые запятыми, вычисляются, но результат берётся из
последнего.
Если выражение expr2 отсутствует, это означает, что цикл
будет выполняться бесконечно. (PHP неявно воспринимает это значение как
true, так же, как в языке C). Это может быть не так бесполезно, как вы
могли подумать, так как часто необходимо прервать цикл, используя
условный оператор break
вместо использования выражения в цикле for,
которое принимает истинное значение.
Рассмотрим следующие примеры. Все они отображают числа от 1 до 10:
<?php
/* пример 1 */
for ($i = 1; $i <= 10; $i++) {
echo $i;
}
/* пример 2 */
for ($i = 1; ; $i++) {
if ($i > 10) {
break;
}
echo $i;
}
/* пример 3 */
$i = 1;
for (; ; ) {
if ($i > 10) {
break;
}
echo $i;
$i++;
}
/* пример 4 */
for ($i = 1, $j = 0; $i <= 10; $j += $i, print $i, $i++);
?>
Конечно, первый пример кажется самым хорошим (или, возможно,
четвёртый), но вы можете обнаружить, что возможность использовать пустые
выражения в циклах for может стать удобной во многих
случаях.
PHP также поддерживает альтернативный синтаксис с двоеточием для циклов
for.
for (expr1; expr2; expr3):
statement
...
endfor;
Перебор массивов как показано ниже - это обычное дело для многих пользователей.
<?php
/*
* Это массив с некоторыми данными, которые мы хотим изменить
* при работе цикла.
*/
$people = array(
array('name' => 'Kalle', 'salt' => 856412),
array('name' => 'Pierre', 'salt' => 215863)
);
for($i = 0; $i < count($people); ++$i) {
$people[$i]['salt'] = mt_rand(000000, 999999);
}
?>Вышеприведённый код может работать медленно, так как размер массива вычисляется в каждой итерации. Поскольку размер не меняется, цикл может быть легко оптимизирован с помощью промежуточной переменной, в которую будет записан размер массива, вместо повторяющихся вызовов функции count():
<?php
$people = array(
array('name' => 'Kalle', 'salt' => 856412),
array('name' => 'Pierre', 'salt' => 215863)
);
for($i = 0, $size = count($people); $i < $size; ++$i) {
$people[$i]['salt'] = mt_rand(000000, 999999);
}
?>(PHP 4, PHP 5, PHP 7, PHP 8)
Конструкция foreach предоставляет простой способ
перебора массивов. foreach работает только с
массивами и объектами, и будет генерировать ошибку при попытке
использования с переменными других типов или неинициализированными переменными.
Существует два вида синтаксиса:
foreach (iterable_expression as $value)
statement
foreach (iterable_expression as $key => $value)
statement
Первый цикл перебирает массив, задаваемый с помощью
iterable_expression. На каждой итерации значение
текущего элемента присваивается переменной $value.
Второй цикл дополнительно присвоит ключ текущего элемента
переменной $key на каждой итерации.
Обратите внимание, что foreach не изменяет указатель внутреннего
массива, который используется такими функциями, как current()
и key().
Возможно настроить итераторы объектов.
Для того, чтобы напрямую изменять элементы массива внутри цикла,
переменной $value должен предшествовать знак &. В этом случае
значение будет присвоено по ссылке.
<?php
$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
$value = $value * 2;
}
// массив $arr сейчас таков: array(2, 4, 6, 8)
unset($value); // разорвать ссылку на последний элемент
?>
Ссылка $value на последний элемент массива останется после окончания
цикла foreach. Рекомендуется уничтожать её с помощью unset().
В противном случае вы можете столкнуться с таким поведением:
<?php
$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
$value = $value * 2;
}
// $arr = array(2, 4, 6, 8)
// Без unset($value), $value всё ещё ссылается на последний элемент: $arr[3]
foreach ($arr as $key => $value) {
// $arr[3] будет перезаписываться значениями $arr при каждой итерации цикла
echo "{$key} => {$value} ";
print_r($arr);
}
// ...И в конце концов предпоследнее значение определит окончательное содержимое $arr[3]
// вывод:
// 0 => 2 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 2 )
// 1 => 4 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 4 )
// 2 => 6 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 6 )
// 3 => 6 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 6 )
?>Можно перебирать значение постоянного массива по ссылке:
<?php
foreach (array(1, 2, 3, 4) as &$value) {
$value = $value * 2;
}
?>
Замечание:
Оператор
foreachне поддерживает возможность подавления сообщений об ошибках с помощью префикса@.
Ещё несколько примеров, демонстрирующие использование оператора:
<?php
/* Пример 1: только значение */
$a = array(1, 2, 3, 17);
foreach ($a as $v) {
echo "Текущее значение переменной \$a: $v.\n";
}
/* Пример 2: значение (для иллюстрации массив выводится в виде значения с ключом) */
$a = array(1, 2, 3, 17);
$i = 0; /* только для пояснения */
foreach ($a as $v) {
echo "\$a[$i] => $v.\n";
$i++;
}
/* Пример 3: ключ и значение */
$a = array(
"one" => 1,
"two" => 2,
"three" => 3,
"seventeen" => 17
);
foreach ($a as $k => $v) {
echo "\$a[$k] => $v.\n";
}
/* Пример 4: многомерные массивы */
$a = array();
$a[0][0] = "a";
$a[0][1] = "b";
$a[1][0] = "y";
$a[1][1] = "z";
foreach ($a as $v1) {
foreach ($v1 as $v2) {
echo "$v2\n";
}
}
/* Пример 5: динамические массивы */
foreach (array(1, 2, 3, 4, 5) as $v) {
echo "$v\n";
}
?>(PHP 5 >= 5.5.0, PHP 7, PHP 8)
Можно перебрать массив массивов и распаковать вложенный массив в переменные цикла, передав list() в качестве значения.
Например:
<?php
$array = [
[1, 2],
[3, 4],
];
foreach ($array as list($a, $b)) {
// $a содержит первый элемент вложенного массива,
// а $b содержит второй элемент.
echo "A: $a; B: $b\n";
}
?>Результат выполнения данного примера:
A: 1; B: 2 A: 3; B: 4
Можно передавать меньшее количество элементов в list(), чем находится во вложенном массиве, в этом случае оставшиеся значения массива будут проигнорированы:
<?php
$array = [
[1, 2],
[3, 4],
];
foreach ($array as list($a)) {
// Обратите внимание на отсутствие $b.
echo "$a\n";
}
?>Результат выполнения данного примера:
1 3
Если массив содержит недостаточно элементов для заполнения всех переменных из list(), то будет сгенерировано замечание об ошибке:
<?php
$array = [
[1, 2],
[3, 4],
];
foreach ($array as list($a, $b, $c)) {
echo "A: $a; B: $b; C: $c\n";
}
?>Результат выполнения данного примера:
Notice: Undefined offset: 2 in example.php on line 7 A: 1; B: 2; C: Notice: Undefined offset: 2 in example.php on line 7 A: 3; B: 4; C:
(PHP 4, PHP 5, PHP 7, PHP 8)
break прерывает выполнение текущей структуры
for, foreach,
while, do-while или
switch.
break принимает необязательный числовой аргумент,
который сообщает ему выполнение какого количества вложенных структур
необходимо прервать. Значение по умолчанию 1, только
ближайшая структура будет прервана.
<?php
$arr = array('один', 'два', 'три', 'четыре', 'стоп', 'пять');
foreach ($arr as $val) {
if ($val == 'стоп') {
break; /* Тут можно было написать 'break 1;'. */
}
echo "$val<br />\n";
}
/* Использование дополнительного аргумента. */
$i = 0;
while (++$i) {
switch ($i) {
case 5:
echo "Итерация 5<br />\n";
break 1; /* Выйти только из конструкции switch. */
case 10:
echo "Итерация 10; выходим<br />\n";
break 2; /* Выходим из конструкции switch и из цикла while. */
default:
break;
}
}
?>(PHP 4, PHP 5, PHP 7, PHP 8)
continue используется внутри циклических структур для
пропуска оставшейся части текущей итерации цикла и, при соблюдении условий,
начала следующей итерации.
Замечание: В PHP оператор switch считается циклическим и внутри него может использоваться
continue. Еслиcontinueне передано аргументов, то он ведёт себя аналогичноbreak, но выдаёт предупреждение о возможной ошибке. Еслиswitchрасположен внутри цикла,continue 2продолжит выполнение внешнего цикла со следующей итерации.
continue принимает необязательный числовой аргумент,
который указывает на скольких уровнях вложенных циклов будет пропущена
оставшаяся часть итерации. Значением по умолчанию является 1,
при которой пропускается оставшаяся часть текущего цикла.
<?php
$arr = ['ноль', 'один', 'два', 'три', 'четыре', 'пять', 'шесть'];
foreach ($arr as $key => $value) {
if (0 === ($key % 2)) { // пропуск чётных чисел
continue;
}
echo $value . "\n";
}
?>Результат выполнения данных примеров:
один три пять
<?php
$i = 0;
while ($i++ < 5) {
echo "Внешний\n";
while (1) {
echo "Средний\n";
while (1) {
echo "Внутренний\n";
continue 3;
}
echo "Это никогда не выведется.\n";
}
echo "Это также не выведется.\n";
}
?>Результат выполнения данных примеров:
Внешний Средний Внутренний Внешний Средний Внутренний Внешний Средний Внутренний Внешний Средний Внутренний Внешний Средний Внутренний
Пропуск точки запятой после continue может привести
к путанице. Пример как не надо делать.
<?php
for ($i = 0; $i < 5; ++$i) {
if ($i == 2)
continue
print "$i\n";
}
?>Ожидается, что результат будет такой:
0 1 3 4
| Версия | Описание |
|---|---|
| 7.3.0 |
continue внутри switch,
использующееся как замена break
для switch будет вызывать ошибку
уровня E_WARNING.
|
(PHP 4, PHP 5, PHP 7, PHP 8)
Оператор switch похож на ряд операторов IF
с одинаковым условием. Во многих случаях вам может понадобиться
сравнивать одну и ту же переменную (или выражение) с множеством
различных значений и выполнять различные участки кода в зависимости
от того, какое значение принимает эта переменная (или выражение). Это
именно тот случай, для которого удобен оператор switch.
Замечание: Обратите внимание, что в отличие от некоторых других языков, оператор continue применяется в конструкциях
switchи действует подобно операторуbreak. Если у вас конструкцияswitchнаходится внутри цикла, и вам необходимо перейти к следующей итерации цикла, используйтеcontinue 2.
Замечание:
Заметьте, что конструкция switch/case использует нестрогое сравнение (==).
В следующем примере каждый блок кода эквивалентен.
В одном используется серия операторов if и elseif,
а в другом - оператор switch. В каждом случае результат один и тот же.
Пример #1 Оператор switch
<?php
// Оператор switch:
switch ($i) {
case 0:
echo "i равно 0";
break;
case 1:
echo "i равно 1";
break;
case 2:
echo "i равно 2";
break;
}
// Эквивалентно:
if ($i == 0) {
echo "i равно 0";
} elseif ($i == 1) {
echo "i равно 1";
} elseif ($i == 2) {
echo "i равно 2";
}
?>Пример #2 Оператор switch допускает сравнение с типом string
<?php
switch ($i) {
case "яблоко":
echo "i это яблоко";
break;
case "шоколадка":
echo "i это шоколадка";
break;
case "пирог":
echo "i это пирог";
break;
}
?>
Важно понять, как оператор switch выполняется,
чтобы избежать ошибок. Оператор switch исполняет
строчка за строчкой (на самом деле выражение за выражением).
В начале никакой код не исполняется. Только в случае
нахождения оператора case, значение которого
совпадает со значением выражения в операторе switch,
PHP начинает исполнять операторы. PHP продолжает исполнять операторы
до конца блока switch либо до тех пор, пока не
встретит оператор break. Если вы не напишете
оператор break в конце секции case, PHP будет продолжать
исполнять команды следующей секции case. Например :
<?php
switch ($i) {
case 0:
echo "i равно 0";
case 1:
echo "i равно 1";
case 2:
echo "i равно 2";
}
?>
В этом примере, если $i равно 0, то PHP исполнит все операторы echo!
Если $i равно 1, PHP исполнит два последних оператора echo.
Вы получите ожидаемое поведение оператора ('i равно 2' будет отображено) только, если
$i будет равно 2. Таким образом, важно не забывать об операторах
break (даже если вы, возможно, хотите избежать его использования по назначению
при определённых обстоятельствах).
В операторе switch выражение вычисляется
один раз и этот результат сравнивается с каждым оператором
case. В выражении elseif,
выражение вычисляется снова. Если ваше условие более сложное,
чем простое сравнение и/или находится в цикле, конструкция
switch может работать быстрее.
Список операторов для исполнения в секции case также может быть пустым, что просто передаёт управление списку операторов в следующей секции case.
<?php
switch ($i) {
case 0:
case 1:
case 2:
echo "i меньше чем 3, но неотрицательный";
break;
case 3:
echo "i равно 3";
}
?>
Специальный вид конструкции case - default. Сюда управление попадает
тогда, когда не сработал ни один из других операторов case. Например:
<?php
switch ($i) {
case 0:
echo "i равно 0";
break;
case 1:
echo "i равно 1";
break;
case 2:
echo "i равно 2";
break;
default:
echo "i не равно 0, 1 или 2";
}
?>Замечание: Несколько указаний default вызовут ошибку
E_COMPILE_ERROR.
Замечание: Формально конструкция
defaultможет быть перечислена в любом месте. Она будет использоваться только в том случае, если ни один другой вариант не подходит. Однако, по соглашению, лучше всего поместить её в конец, как последнюю конструкцию.
Если ни одна конструкция case не совпадает и нет конструкции default,
то код не будет выполнен, как если бы ни одно утверждение if не было истинным.
Значение case может быть задано в виде выражения. Однако это выражение будет оценено само по себе, а затем слабо сопоставлено со значением switch. Это означает, что его нельзя использовать для сложных оценок значения switch. Например:
<?php
$target = 1;
$start = 3;
switch ($target) {
case $start - 1:
print "A";
break;
case $start - 2:
print "B";
break;
case $start - 3:
print "C";
break;
case $start - 4:
print "D";
break;
}
// Выведет "B"
?>
Для более сложных сравнений в качестве значения switch может использоваться значение true.
Или, как вариант, вместо switch использовать блоки if-else.
<?php
$offset = 1;
$start = 3;
switch (true) {
case $start - $offset === 1:
print "A";
break;
case $start - $offset === 2:
print "B";
break;
case $start - $offset === 3:
print "C";
break;
case $start - $offset === 4:
print "D";
break;
}
// Выведет "B"
?>Возможен альтернативный синтаксис для управляющей структуры switch. Для более детальной информации, смотрите Альтернативный синтаксис для управляющих структур.
<?php
switch ($i):
case 0:
echo "i равно 0";
break;
case 1:
echo "i равно 1";
break;
case 2:
echo "i равно 2";
break;
default:
echo "i не равно 0, 1 или 2";
endswitch;
?>Возможно использование точки с запятой вместо двоеточия после оператора case. К примеру :
<?php
switch($beer)
{
case 'tuborg';
case 'carlsberg';
case 'stella';
case 'heineken';
echo 'Хороший выбор';
break;
default;
echo 'Пожалуйста, сделайте новый выбор...';
break;
}
?>(PHP 8)
Выражение match предназначено для ветвления потока исполнения на
основании проверки совпадения значения с заданным условием.
Аналогично оператору switch, выражение
match принимает на вход выражение, которое сравнивается
с множеством альтернатив. Но, в отличие от switch,
оно обрабатывает значение в стиле, больше похожем на тернарный оператор.
Также, в отличие от switch, используется строгое сравнение
(===), а не слабое (==).
Выражение match доступно начиная с PHP 8.0.0.
Пример #1 Структура выражения match
<?php
$return_value = match (subject_expression) {
single_conditional_expression => return_expression,
conditional_expression1, conditional_expression2 => return_expression,
};
?>Пример #2 Простой пример использования match
<?php
$food = 'cake';
$return_value = match ($food) {
'apple' => 'На столе лежит яблоко',
'banana' => 'На столе лежит банан',
'cake' => 'На столе стоит торт',
};
var_dump($return_value);
?>Результат выполнения данного примера:
string(35) "На столе стоит торт"
Замечание: Результат
matchиспользовать не обязательно.
Замечание: Выражение
matchдолжно завершаться точкой с запятой;.
Выражение match похоже на оператор
switch за исключением некоторых ключевых отличий:
match используется строгое сравнение (===).
match возвращает результат.
match исполняется только одна, первая подошедшая, ветвь кода, тогда как
в switch происходит сквозное исполнение начиная с подошедшего условия и
до первого встретившегося оператора break.
match должно быть исчерпывающим.
Также как и оператор switch, match
последовательно проводит проверки на совпадение с заданными условиями.
Выполнение кода условий происходит лениво, т.е. код следующего условия выполняется только
если все предыдущие проверки провалились. Будет выполнена только одна ветвь кода,
соответствующая подошедшему условию.
Пример:
<?php
$result = match ($x) {
foo() => ...,
$this->bar() => ..., // $this->bar() не будет выполнен, если foo() === $x
$this->baz => beep(), // beep() будет выполнен только если $x === $this->baz
// etc.
};
?>
Условия в match могут быть множественными. В этом случае их следует разделять запятыми.
Множественные условия работают по принципу логического ИЛИ и, по сути, являются
сокращённой формой для случаев, когда несколько условий должны обрабатываться идентично.
<?php
$result = match ($x) {
// Множественное условие:
$a, $b, $c => 5,
// Аналогично трём одиночным:
$a => 5,
$b => 5,
$c => 5,
};
?>
Также можно использовать шаблон default.
Этот шаблон совпадает с чем угодно, для чего не нашлось совпадений раньше.
К примеру:
<?php
$expressionResult = match ($condition) {
1, 2 => foo(),
3, 4 => bar(),
default => baz(),
};
?>Замечание: Использование нескольких шаблонов default приведёт к фатальной ошибке
E_FATAL_ERROR.
Выражение match должно быть исчерпывающим. Если
проверяемое выражение не совпало ни с одним из условий, то будет
выброшено исключение UnhandledMatchError.
Пример #3 Пример необработанного выражения
<?php
$condition = 5;
try {
match ($condition) {
1, 2 => foo(),
3, 4 => bar(),
};
} catch (\UnhandledMatchError $e) {
var_dump($e);
}
?>Результат выполнения данного примера:
object(UnhandledMatchError)#1 (7) {
["message":protected]=>
string(33) "Unhandled match value of type int"
["string":"Error":private]=>
string(0) ""
["code":protected]=>
int(0)
["file":protected]=>
string(9) "/in/ICgGK"
["line":protected]=>
int(6)
["trace":"Error":private]=>
array(0) {
}
["previous":"Error":private]=>
NULL
}
Выражение match можно использовать не только для проверки идентичности,
но и для любых выражений, возвращающих логическое значение. В этом случае в качестве входного
параметра передаётся выражение true.
Пример #4 Использование match для ветвления в зависимости от вхождения в диапазоны целых чисел
<?php
$age = 23;
$result = match (true) {
$age >= 65 => 'пожилой',
$age >= 25 => 'взрослый',
$age >= 18 => 'совершеннолетний',
default => 'ребёнок',
};
var_dump($result);
?>Результат выполнения данного примера:
string(11) "совершеннолетний"
Пример #5 Использование match для ветвления в зависимости от содержимого строки
<?php
$text = 'Bienvenue chez nous';
$result = match (true) {
str_contains($text, 'Welcome') || str_contains($text, 'Hello') => 'en',
str_contains($text, 'Bienvenue') || str_contains($text, 'Bonjour') => 'fr',
// ...
};
var_dump($result);
?>Результат выполнения данного примера:
string(2) "fr"
(PHP 4, PHP 5, PHP 7, PHP 8)
Конструкция declare используется для установки
директив исполнения для блока кода. Синтаксис declare
аналогичен с синтаксисом других конструкций управления выполнением:
declare (directive)
statement
Секция directive позволяет установить поведение
блока declare.
В настоящее время распознаются только три директивы:
директива ticks (Дополнительная информация
о директиве ticks
доступна ниже), директива encoding (Дополнительная информация
о директиве encoding
доступна ниже) и директива strict_types (подробности в разделе про
строгую типизацию на странице аргументов функции)
Поскольку директивы обрабатываются при компиляции файла, то только символьные данные могут использоваться как значения директивы. Нельзя использовать переменные и константы. Пример:
<?php
// Правильно:
declare(ticks=1);
// Недопустимо:
const TICK_VALUE = 1;
declare(ticks=TICK_VALUE);
?>
Часть statement блока declare
будет выполнена - как выполняется и какие побочные эффекты
возникают во время выполнения, может зависеть от директивы, которая установлена в
блоке directive.
Конструкция declare также может быть использована
в глобальной области видимости, влияя на весь следующий за ней код
(однако если файл с declare был включён, то она
не будет действовать на родительский файл).
<?php
// это то же самое:
// можно так:
declare(ticks=1) {
// прочие действия
}
// или так:
declare(ticks=1);
// прочие действия
?>Тик - это событие, которое случается каждые
N низкоуровневых операций, выполненных
парсером внутри блока declare.
Значение N задаётся, используя
ticks=N внутри
секции directive блока declare.
Не все выражения подсчитываются. Обычно, условные выражения и выражения аргументов не подсчитываются.
Событие (или несколько событий), которое возникает на каждом тике определяется, используя register_tick_function(). Смотрите пример ниже для дополнительной информации. Имейте в виду, что для одного тика может возникать несколько событий.
Пример #1 Пример использования тика
<?php
declare(ticks=1);
// Функция, исполняемая при каждом тике
function tick_handler()
{
echo "Вызывается tick_handler()\n";
}
register_tick_function('tick_handler'); // вызывает событие тика
$a = 1; // вызывает событие тика
if ($a > 0) {
$a += 2; // вызывает событие тика
print($a); // вызывает событие тика
}
?>Смотрите также register_tick_function() и unregister_tick_function().
Кодировка скрипта может быть указана для каждого скрипта, используя директиву encoding.
Пример #2 Определение кодировки для скрипта.
<?php
declare(encoding='ISO-8859-1');
// прочий код
?>
В сочетании с пространством имён единственно допустимый синтаксис
для declare является declare(encoding='...'); где
... это значение кодировки. declare(encoding='...') {}
приведёт к ошибке парсера, если используется вместе с пространством имён.
Смотрите также zend.script_encoding.
(PHP 4, PHP 5, PHP 7, PHP 8)
return возвращает управление программой модулю, из которого
была вызвана функция.
Выполнение программы продолжается с инструкции, следующей за местом вызова.
Если вызывается из функции, выражение return
немедленно прекращает выполнение текущей функции и
возвращает свой аргумент как значение данной функции.
return также завершит выполнение выражения
eval() или всего файла скрипта.
Если вызывается из глобальной области видимости, выполнение текущего файла
скрипта прекращается. Если текущий файл скрипта был подключён
с помощью функций include или require,
тогда управление возвращается к файлу, который вызывал текущий. Более того, если
текущий файл скрипта был подключён с помощью include, тогда
значение переданное return будет возвращено в качестве
значения вызова include. Если
return вызывается из главного файла скрипта,
тогда выполнение скрипта прекращается. Если текущий файл скрипта был
вызван конфигурационными опциями auto_prepend_file или auto_append_file
из файла настроек php.ini,
тогда выполнение этого скрипта прекращается.
Для более детальной информации смотрите раздел Возвращаемые значения.
Замечание: Заметьте, что
returnявляется языковой конструкцией, а не функцией и круглые скобки, окружающие аргументы, не являются необходимостью. Мало того, они тут не приветствуются.
Замечание: Если параметры не указаны, тогда круглые скобки должны быть опущены и будет возвращён
null. Вызовreturnсо скобками, но без аргументов вызовет синтаксическую ошибку.
Начиная с PHP 7.1.0, операторы возврата без аргумента в функциях,
объявляющих тип возврата, вызывают E_COMPILE_ERROR,
если только тип возврата не void, в этом случае такую же ошибку вызывают операторы возврата с аргументом.
(PHP 4, PHP 5, PHP 7, PHP 8)
require аналогично include,
за исключением того, что в случае возникновения ошибки он также выдаст фатальную ошибку уровня E_COMPILE_ERROR.
Другими словами, он остановит выполнение скрипта, тогда как
include только выдал бы предупреждение
E_WARNING, которое позволило бы скрипту продолжить выполнение.
Смотрите документацию по include, чтобы узнать как он работает.
(PHP 4, PHP 5, PHP 7, PHP 8)
Выражение include включает и выполняет
указанный файл.
Документация ниже также относится к выражению require.
Файлы включаются исходя из пути указанного файла, или, если путь не указан,
используется путь, указанный в директиве include_path. Если файл
не найден в include_path,
include попытается проверить директорию, в которой находится текущий включающий скрипт
и текущую рабочую директорию перед тем, как выдать ошибку. Конструкция
include выдаст E_WARNING, если
не сможет найти файл; поведение отлично от require, который выдаст
E_ERROR.
Обратите внимание, что и include и require
выдают дополнительную ошибку уровня E_WARNING, если к файлу невозможно
получить доступ, перед тем, как выдать последнюю ошибку уровня
E_WARNING или E_ERROR соответственно.
Если путь указан — абсолютный (начинающийся с буквы диска или с
\ в Windows или с / в Unix/Linux
системах) или относительно текущей директории (начинающийся с
. или ..) —
include_path будет проигнорирован вообще.
Например, если имя файла начинается с ../,
парсер будет искать в родительской директории запрошенный файл.
Для дополнительной информации о том, как PHP обрабатывает включаемые файлы и включаемые пути, смотрите документацию для директивы include_path.
Когда файл включается, его код наследует ту же область видимости переменных, что и строка, на которой произошло включение. Все переменные, доступные на этой строке во включающем файле, будут также доступны во включаемом файле. Однако все функции и классы, объявленные во включаемом файле, имеют глобальную область видимости.
Пример #1 Простой пример include
vars.php
<?php
$color = 'зелёное';
$fruit = 'яблоко';
?>
test.php
<?php
echo "Одно $color $fruit"; // Одно
include 'vars.php';
echo "Одно $color $fruit"; // Одно зелёное яблоко
?>Если включение происходит внутри функции включающего файла, тогда весь код, содержащийся во включаемом файле, будет вести себя так, как будто он был определён внутри этой функции. То есть, он будет в той же области видимости переменных этой функции. Исключением к этому правилу являются магические константы, которые выполняются парсером перед тем, как происходит включение.
Пример #2 Включение внутри функции
<?php
function foo()
{
global $color;
include 'vars.php';
echo "Одно $color $fruit";
}
/* vars.php в той же области видимости, что и foo(), *
* поэтому $fruit НЕ будет доступен за пределами этой области *
* $color доступен, поскольку мы объявили переменную глобальной */
foo(); // Одно зелёное яблоко
echo "Одно $color $fruit"; // Одно зелёное
?>Когда файл включается, парсинг в режиме PHP-кода прекращается и переключается в режим HTML в начале указанного файла и продолжается снова в конце. По этой причине любой код внутри включаемого файла, который должен быть выполнен как код PHP, должен быть заключён в корректные теги начала и конца PHP-кода.
Если "обёртки URL include" включены в PHP, вы можете также указать файл для включения через URL (с помощью HTTP или других поддерживающихся обработчиков - смотрите Поддерживаемые протоколы и обёртки для списка протоколов) вместо локального пути. Если целевой сервер интерпретирует указанный файл как код PHP, переменные могут быть переданы во включаемый файл с помощью строки URL-запроса при использовании HTTP GET. Это совсем не то же самое, что включение файла и наследование родительской области видимости; скрипт выполняется на удалённом сервере, и результат затем включается в локальный скрипт.
Пример #3 Пример include через HTTP
<?php
/* В этом примере предполагается, что www.example.com настроен на обработку .php
* файлов, но не .txt. Также, 'Сработает' обозначает, что переменные
* $foo и $bar доступны внутри включаемого файла. */
// Не сработает; file.txt не обрабатывается www.example.com как PHP
include 'http://www.example.com/file.txt?foo=1&bar=2';
// Не сработает; будет искать файл 'file.php?foo=1&bar=2' в
// локальной файловой системе.
include 'file.php?foo=1&bar=2';
// Сработает.
include 'http://www.example.com/file.php?foo=1&bar=2';
?>Удалённые файлы могут быть обработаны на удалённой стороне (в зависимости от расширения файла и того, что удалённый сервер выполняет скрипты PHP или нет), но это всё равно должно производить корректный скрипт PHP, потому что он будет затем обработан уже на локальном сервере. Если файл с удалённого сервера должен быть обработан и только отображён его результат, гораздо эффективно воспользоваться функцией readfile() В противном случае следует соблюдать особую осторожность, чтобы обезопасить удалённый скрипт для получения корректного и желаемого кода.
Смотрите также раздел Удалённые файлы, функции fopen() и file() для дополнительной информации.
Обработка возвращаемых значений: оператор include возвращает
значение FALSE в случае возникновения ошибки и выдаёт предупреждение. Успешные
включения, пока это не переопределено во включаемом файле, возвращают значение
1. Возможно выполнить выражение return
внутри включаемого файла, чтобы завершить процесс выполнения в
этом файле и вернуться к выполнению включающего файла. Кроме того, возможно вернуть
значение из включаемых файлов. Вы можете получить значение включения, как
если бы вы вызвали обычную функцию. Хотя это невозможно при включении
удалённого файла, только если вывод удалённого файла не содержит
корректные теги начала и конца PHP
кода (так же, как и локальный файл). Вы можете определить необходимые
переменные внутри этих тегов и они будут представлены в зависимости от того,
какой файл был выключен.
Так как include - это специальная языковая конструкция,
круглые скобки не обязательны вокруг аргумента. Будьте внимательны при сравнении
возвращаемого значения.
Пример #4 Сравнение возвращаемого значения при include
<?php
// не сработает, интерпретируется как include(('vars.php') == TRUE), то есть include('1')
if (include('vars.php') == TRUE) {
echo 'OK';
}
// сработает
if ((include 'vars.php') == TRUE) {
echo 'OK';
}
?>
Пример #5 Выражения include и return
return.php
<?php
$var = 'PHP';
return $var;
?>
noreturn.php
<?php
$var = 'PHP';
?>
testreturns.php
<?php
$foo = include 'return.php';
echo $foo; // выведет 'PHP'
$bar = include 'noreturn.php';
echo $bar; // выведет 1
?>
$bar имеет значение 1, т.к. включение файла произошло
успешно. Заметьте разницу между примерами сверху. Первый использует
return внутри включаемого файла, тогда как второй не использует.
Если файл не может быть включён, возвращается false и возникает
E_WARNING.
Если во включаемом файле определены функции, они могут быть использованы в главном файле вне зависимости от того, были ли они объявлены до return или после. Если файл включается дважды, PHP выдаст фатальную ошибку, потому что функции уже были определены. Рекомендуется использовать include_once вместо того, чтобы проверять был ли файл уже включён.
Другой путь "включить" PHP-файл в переменную - это захватить
вывод с помощью функций контроля вывода
вместе с include. Например:
Пример #6 Использование буферизации вывода для включения файла PHP в строку
<?php
$string = get_include_contents('somefile.php');
function get_include_contents($filename) {
if (is_file($filename)) {
ob_start();
include $filename;
return ob_get_clean();
}
return false;
}
?>Для того, чтобы включать файлы автоматически в скрипты, обратите внимание на конфигурационные директивы auto_prepend_file и auto_append_file в php.ini.
Замечание: Поскольку это языковая конструкция, а не функция, она не может вызываться при помощи переменных функций или именованных аргументов.
Смотрите также require, require_once, include_once, get_included_files(), readfile(), virtual() и include_path.
(PHP 4, PHP 5, PHP 7, PHP 8)
Выражение require_once аналогично
require за исключением того, что PHP проверит, включался ли
уже данный файл, и если да, не будет включать его ещё раз.
Смотрите документацию include_once для информации
по поведению _once и чем он отличается от таких же функций,
без _once.
(PHP 4, PHP 5, PHP 7, PHP 8)
Выражение include_once включает и выполняет указанный файл во время
выполнения скрипта. Его поведение идентично выражению include,
с той лишь разницей, что если код из файла уже один раз был включён, он не будет включён
и выполнен повторно и вернёт true. Как видно из имени, он включит файл только
один раз.
include_once может использоваться в тех случаях, когда
один и тот же файл может быть включён и выполнен более одного раза во время
выполнения скрипта, в данном случае это поможет избежать
проблем с переопределением функций, переменных и т.д.
Смотрите документацию по include для получения информации о том, как эта функция работает.
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Оператор goto используется для перехода в
другую часть программы. Место, куда необходимо перейти указывается с помощью чувствительный к регистру метки,
за которой ставится двоеточие, после оператора goto
указывается желаемая метка для перехода. Оператор не
является неограниченным "goto". Целевая
метка должна находиться в том же файле, в том же контексте. Имеется в виду, что вы не можете ни перейти за
границы функции или метода, ни перейти внутрь одной из них. Вы также не можете
перейти внутрь любой циклической структуры или оператора switch. Но вы можете выйти
из них, и обычным применением оператора goto является
использование его вместо многоуровневых break.
Пример #1 Пример использования goto
<?php
goto a;
echo 'Foo';
a:
echo 'Bar';
?>Результат выполнения данного примера:
Bar
Пример #2 Пример использования goto в цикле
<?php
for($i=0,$j=50; $i<100; $i++) {
while($j--) {
if($j==17) goto end;
}
}
echo "i = $i";
end:
echo 'j hit 17';
?>Результат выполнения данного примера:
j hit 17
Пример #3 Это не сработает
<?php
goto loop;
for($i=0,$j=50; $i<100; $i++) {
while($j--) {
loop:
}
}
echo "$i = $i";
?>Результат выполнения данного примера:
Fatal error: 'goto' into loop or switch statement is disallowed in script on line 2
Приведём пример синтаксиса, используемого для описания функций:
Пример #1 Псевдокод для демонстрации использования функций
<?php
function foo($arg_1, $arg_2, /* ..., */ $arg_n)
{
echo "Пример функции.\n";
return $retval;
}
?>Внутри функции можно использовать любой корректный PHP-код, в том числе другие функции и даже объявления классов.
Имена функций следуют тем же правилам, что и другие метки в PHP.
Корректное имя функции начинается с буквы или знака подчёркивания,
за которым следует любое количество букв, цифр или знаков
подчёркивания. В качестве регулярного выражения оно может быть
выражено так:
^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$.
Смотрите также Руководство по именованию.
Функции не обязаны быть определены до их использования, исключая тот случай, когда функции определяются условно, как это показано в двух последующих примерах.
В случае, когда функция определяется в зависимости от какого-либо условия, например, как это показано в двух приведённых ниже примерах, обработка описания функции должна предшествовать её вызову.
Пример #2 Функции, зависящие от условий
<?php
$makefoo = true;
/* Мы не можем вызвать функцию foo() в этом месте,
поскольку она ещё не определена, но мы можем
обратиться к bar() */
bar();
if ($makefoo) {
function foo()
{
echo "Я не существую до тех пор, пока выполнение программы меня не достигнет.\n";
}
}
/* Теперь мы благополучно можем вызывать foo(),
поскольку $makefoo была интерпретирована как true */
if ($makefoo) foo();
function bar()
{
echo "Я существую сразу с начала старта программы.\n";
}
?>
Пример #3 Вложенные функции
<?php
function foo()
{
function bar()
{
echo "Я не существую пока не будет вызвана foo().\n";
}
}
/* Мы пока не можем обратиться к bar(),
поскольку она ещё не определена. */
foo();
/* Теперь мы можем вызвать функцию bar(),
обработка foo() сделала её доступной. */
bar();
?>Все функции и классы PHP имеют глобальную область видимости - они могут быть вызваны вне функции, даже если были определены внутри и наоборот.
PHP не поддерживает перегрузку функции, также отсутствует возможность переопределить или удалить объявленную ранее функцию.
Замечание: Имена функций регистронезависимы для символов ASCII от
AдоZ, тем не менее, предпочтительнее вызывать функции так, как они были объявлены.
Функции PHP поддерживают как списки аргументов переменной длины, так и значения аргументов по умолчанию. Смотрите также описания функций func_num_args(), func_get_arg() и func_get_args() для более детальной информации.
Можно вызывать функции PHP рекурсивно.
Пример #4 Рекурсивные функции
<?php
function recursion($a)
{
if ($a < 20) {
echo "$a\n";
recursion($a + 1);
}
}
?>Замечание: Рекурсивный вызов методов/процедур с глубиной более 100-200 уровней рекурсии может вызвать переполнение стека и привести к аварийному завершению скрипта. В частности, бесконечная рекурсия будет считаться программной ошибкой.
Функция может принимать информацию в виде списка аргументов, который является списком разделённых запятыми выражений. Аргументы вычисляются слева направо перед фактическим вызовом функции (энергичное вычисление).
PHP поддерживает передачу аргументов по значению (по умолчанию), передачу аргументов по ссылке, и значения по умолчанию. Списки аргументов переменной длины и именованные аргументы также поддерживаются.
Пример #1 Передача массива в функцию
<?php
function takes_array($input)
{
echo "$input[0] + $input[1] = ", $input[0]+$input[1];
}
?>Начиная с PHP 8.0.0, список аргументов функции может содержать завершающую запятую, которая будет проигнорирована. Это полезно в случае, когда список аргументов очень длинный, либо если имена переменных длинны, что подталкивает к их вертикальному расположению.
Пример #2 Список аргументов функции с завершающей запятой
<?php
function takes_many_args(
$first_arg,
$second_arg,
$a_very_long_argument_name,
$arg_with_default = 5,
$again = 'a default string', // Эта завершающая запятая допустима только начиная с 8.0.0.
)
{
// ...
}
?>По умолчанию аргументы в функцию передаются по значению (это означает, что если вы измените значение аргумента внутри функции, то вне её значение всё равно останется прежним). Если вы хотите разрешить функции модифицировать свои аргументы, вы должны передавать их по ссылке.
Если вы хотите, чтобы аргумент всегда передавался по ссылке, вы можете указать амперсанд (&) перед именем аргумента в описании функции:
Пример #3 Передача аргументов по ссылке
<?php
function add_some_extra(&$string)
{
$string .= 'и кое-что ещё.';
}
$str = 'Это строка, ';
add_some_extra($str);
echo $str; // выведет 'Это строка, и кое-что ещё.'
?>Передача значения в качестве аргумента, которое должно передаваться по ссылке, является ошибкой.
Функция может определять значения по умолчанию для аргументов,
используя синтаксис, подобный присвоению переменной.
Значение по умолчанию используется только в том случае, если параметр не указан;
в частности, обратите внимание, что передача null
не присваивает значение по умолчанию.
Пример #4 Использование значений по умолчанию в определении функции
<?php
function makecoffee($type = "капучино")
{
return "Готовим чашку $type.\n";
}
echo makecoffee();
echo makecoffee(null);
echo makecoffee("эспрессо");
?>Результат выполнения данного примера:
Готовим чашку капучино. Готовим чашку . Готовим чашку эспрессо.
Значениями параметров по умолчанию могут быть скалярные значения, массивы (array),
специальный тип null, и, начиная с версии PHP 8.1.0, объекты,
использующие синтаксис new ClassName().
Пример #5 Использование нескалярных типов в качестве значений по умолчанию
<?php
function makecoffee($types = array("капучино"), $coffeeMaker = NULL)
{
$device = is_null($coffeeMaker) ? "вручную" : $coffeeMaker;
return "Готовлю чашку ".join(", ", $types)." $device.\n";
}
echo makecoffee();
echo makecoffee(array("капучино", "лавацца"), "в чайнике");
?>
Пример #6 Использование объектов в качестве значений по умолчанию (начиная с PHP 8.1.0)
<?php
class DefaultCoffeeMaker {
public function brew() {
return 'Приготовление кофе.';
}
}
class FancyCoffeeMaker {
public function brew() {
return 'Приготовление прекрасного кофе специально для вас.';
}
}
function makecoffee($coffeeMaker = new DefaultCoffeeMaker)
{
return $coffeeMaker->brew();
}
echo makecoffee();
echo makecoffee(new FancyCoffeeMaker);
?>Значение по умолчанию должно быть константным выражением, а не (к примеру) переменной или вызовом функции/метода класса.
Обратите внимание, что любые необязательные аргументы должны быть указаны после любых обязательных аргументов, иначе они не могут быть опущены при вызове. Рассмотрим следующий пример:
Пример #7 Некорректное использование значений по умолчанию
<?php
function makeyogurt($container = "миску", $flavour)
{
return "Делаем $container с $flavour йогуртом.\n";
}
echo makeyogurt("малиновым"); // "малиновым" - это $container, не $flavour
?>Результат выполнения данного примера:
Fatal error: Uncaught ArgumentCountError: Too few arguments to function makeyogurt(), 1 passed in example.php on line 42
Теперь сравним его со следующим примером:
Пример #8 Корректное использование значений по умолчанию
<?php
function makeyogurt($flavour, $container = "миску")
{
return "Делаем $container с $flavour йогуртом.\n";
}
echo makeyogurt("малиновым"); // "малиновым" - это $flavour
?>Результат выполнения данного примера:
Делаем миску с малиновым йогуртом.
Начиная с PHP 8.0.0, именованные аргументы можно использовать для пропуска нескольких необязательных параметров.
Пример #9 Правильное использование аргументов функций по умолчанию
<?php
function makeyogurt($container = "миску", $flavour = "малиновым", $style = "греческим")
{
return "Делаем $container с $flavour $style йогуртом.\n";
}
echo makeyogurt(style: "натуральным");
?>Результат выполнения данного примера:
Делаем миску с малиновым натуральным йогуртом.
Начиная с PHP 8.0.0, объявление обязательных аргументов после необязательных
аргументов является устаревшим.
Обычно это можно решить отказавшись от значения по умолчанию, поскольку оно никогда не будет использоваться.
Исключением из этого правила являются аргументы вида Type $param = null,
где null по умолчанию делает тип неявно обнуляемым.
Такое использование остаётся допустимым, хотя рекомендуется использовать
явный тип nullable.
Пример #10 Объявление необязательных аргументов после обязательных аргументов
<?php
function foo($a = [], $b) {} // По умолчанию не используется; устарел, начиная с версии PHP 8.0.0
function foo($a, $b) {} // Функционально эквивалентны, без уведомления об устаревании
function bar(A $a = null, $b) {} // Все еще разрешено; $a является обязательным, но допускающим значение null
function bar(?A $a, $b) {} // Рекомендуется
?>Замечание: Начиная с PHP 7.1.0, опущение параметра, не заданного по умолчанию, выбрасывает исключение ArgumentCountError; в предыдущих версиях это вызывало предупреждение.
Замечание: Значения по умолчанию могут быть переданы по ссылке.
PHP поддерживает списки аргументов переменной длины для функций,
определяемых пользователем с помощью добавления
многоточия (...).
Замечание: Также можно добиться аргументов переменной длины, используя функции func_num_args(), func_get_arg() и func_get_args(). Этот метод не рекомендуется, поскольку он использовался до введения многоточия (
...).
Список аргументов может содержать многоточие
(...), чтобы показать, что функция принимает переменное
количество аргументов. Аргументы в этом случае будут переданы в виде массива:
Пример #11 Использование ... для доступа к аргументам
<?php
function sum(...$numbers) {
$acc = 0;
foreach ($numbers as $n) {
$acc += $n;
}
return $acc;
}
echo sum(1, 2, 3, 4);
?>Результат выполнения данного примера:
10
Многоточие (...) можно использовать при вызове функции,
чтобы распаковать массив (array) или Traversable
переменную в список аргументов:
Пример #12 Использование ... для передачи аргументов
<?php
function add($a, $b) {
return $a + $b;
}
echo add(...[1, 2])."\n";
$a = [1, 2];
echo add(...$a);
?>Результат выполнения данного примера:
3 3
Можно задать несколько аргументов в привычном виде, а затем добавить
.... В этом случае ... поместит
в массив только те аргументы, которые не нашли соответствия указанным
в объявлении функции.
Также можно добавить
объявление типа перед
.... В этом случае все аргументы,
обработанные многоточием (...), должны соответствовать этому типу параметра.
Пример #13 Аргументы с подсказкой типа
<?php
function total_intervals($unit, DateInterval ...$intervals) {
$time = 0;
foreach ($intervals as $interval) {
$time += $interval->$unit;
}
return $time;
}
$a = new DateInterval('P1D');
$b = new DateInterval('P2D');
echo total_intervals('d', $a, $b).' days';
// Это не сработает, т.к. null не является объектом DateInterval.
echo total_intervals('d', null);
?>Результат выполнения данного примера:
3 days Catchable fatal error: Argument 2 passed to total_intervals() must be an instance of DateInterval, null given, called in - on line 14 and defined in - on line 2
В конце концов, можно передавать аргументы
по ссылке. Для этого
перед ... нужно поставить амперсанд
(&).
Для указания того, что функция принимает переменное число аргументов, никакой специальный синтаксис не используется. Для доступа к аргументам необходимо использовать функции func_num_args(), func_get_arg() и func_get_args().
В первом примере выше было показано, как задать список аргументов переменной длины для предыдущих версий PHP:
Пример #14 Доступ к аргументам в предыдущих версиях PHP
<?php
function sum() {
$acc = 0;
foreach (func_get_args() as $n) {
$acc += $n;
}
return $acc;
}
echo sum(1, 2, 3, 4);
?>Результат выполнения данного примера:
10
В PHP 8.0.0 в виде продолжения позиционных параметров появились именованные аргументы. С их помощью аргументы функции можно передавать по имени параметра, а не по его позиции. Таким образом аргумент становится самодокументированным, независимым от порядка и указанного значения по умолчанию.
Именованные аргументы передаются путём добавления через двоеточия имени параметра перед его значением. В качестве имён параметров можно использовать зарезервированные ключевые слова. Имя параметра должно быть идентификатором, т.е. он не может быть создан динамически.
Пример #15 Синтаксис именованного аргумента
<?php
myFunction(paramName: $value);
array_foobar(array: $value);
// НЕ поддерживается.
function_name($variableStoringParamName: $value);
?>Пример #16 Позиционные аргументы в сравнении с именованными аргументами
<?php
// Использование позиционных аргументов:
array_fill(0, 100, 50);
// Использование именованных аргументов:
array_fill(start_index: 0, count: 100, value: 50);
?>Порядок, в котором передаются именованные аргументы, не имеет значения.
Пример #17 Тот же пример, что и выше, но с другим порядком параметров
<?php
array_fill(value: 50, count: 100, start_index: 0);
?>Именованные аргументы можно комбинировать с позиционными. В этом случае именованные аргументы должны следовать после позиционных аргументов. Также возможно передать только часть необязательных аргументов функции, независимо от их порядка.
Пример #18 Объединение именованных аргументов с позиционными аргументами
<?php
htmlspecialchars($string, double_encode: false);
// То же самое
htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, 'UTF-8', false);
?>Передача одного и того же параметра несколько раз приводит к выбрасыванию исключения Error.
Пример #19 Ошибка, возникающая при передаче одного и того же параметра несколько раз
<?php
function foo($param) { ... }
foo(param: 1, param: 2);
// Error: Named parameter $param overwrites previous argument
foo(1, param: 2);
// Error: Named parameter $param overwrites previous argument
?>Начиная с PHP 8.1.0, можно использовать именованные аргументы после распаковки аргументов. Именованный аргумент не должен переопределять уже распакованный аргумент.
Пример #20 Пример использования именованных аргументов после распаковки
<?php
function foo($a, $b, $c = 3, $d = 4) {
return $a + $b + $c + $d;
}
var_dump(foo(...[1, 2], d: 40)); // 46
var_dump(foo(...['b' => 2, 'a' => 1], d: 40)); // 46
var_dump(foo(...[1, 2], b: 20)); // Фатальная ошибка. Именованный аргумент $b переопределяет предыдущий аргумент
?>Значения возвращаются при помощи необязательного оператора возврата. Возвращаемые значения могут быть любого типа, в том числе это могут быть массивы и объекты. Возврат приводит к завершению выполнения функции и передаче управления обратно к той строке кода, в которой данная функция была вызвана. Для получения более детальной информации ознакомьтесь с описанием return.
Замечание:
Если конструкция return не указана, то функция вернёт значение
null.
Пример #1 Использование конструкции return
<?php
function square($num)
{
return $num * $num;
}
echo square(4); // выводит '16'.
?>Функция не может возвращать несколько значений, но аналогичного результата можно добиться, возвращая массив.
Пример #2 Возврат нескольких значений в виде массива
<?php
function small_numbers()
{
return [0, 1, 2];
}
// Деструктуризация массива будет собирать каждый элемент массива индивидуально
[$zero, $one, $two] = small_numbers();
// До версии 7.1.0 единственной эквивалентной альтернативой было использование конструкции list().
list($zero, $one, $two) = small_numbers();
?>Для того, чтобы функция возвращала результат по ссылке, вам необходимо использовать оператор & и при описании функции, и при присвоении переменной возвращаемого значения:
Пример #3 Возврат результата по ссылке
<?php
function &returns_reference()
{
return $someref;
}
$newref =& returns_reference();
?>Для получения более детальной информации о ссылках обратитесь к разделу документации Подробно о ссылках.
PHP поддерживает концепцию переменных функций. Это означает, что если к имени переменной присоединены круглые скобки, PHP ищет функцию с тем же именем, что и результат вычисления переменной, и пытается её выполнить. Эту возможность можно использовать для реализации обратных вызовов, таблиц функций и множества других вещей.
Переменные функции не будут работать с такими языковыми конструкциями как echo, print, unset(), isset(), empty(), include, require и т.п. Вам необходимо реализовать свою функцию-обёртку для того, чтобы приведённые выше конструкции могли работать с переменными функциями.
Пример #1 Работа с функциями посредством переменных
<?php
function foo() {
echo "В foo()<br />\n";
}
function bar($arg = '')
{
echo "В bar(); аргумент был '$arg'.<br />\n";
}
// Функция-обёртка для echo
function echoit($string)
{
echo $string;
}
$func = 'foo';
$func(); // Вызывает функцию foo()
$func = 'bar';
$func('test'); // Вызывает функцию bar()
$func = 'echoit';
$func('test'); // Вызывает функцию echoit()
?>Вы также можете вызвать методы объекта используя возможности PHP для работы с переменными функциями.
Пример #2 Обращение к методам класса посредством переменных
<?php
class Foo
{
function Variable()
{
$name = 'Bar';
$this->$name(); // Вызываем метод Bar()
}
function Bar()
{
echo "Это Bar";
}
}
$foo = new Foo();
$funcname = "Variable";
$foo->$funcname(); // Обращаемся к $foo->Variable()
?>При вызове статических методов вызов функции "сильнее", чем оператор доступа к статическому свойству:
Пример #3 Пример вызова переменного метода со статическим свойством
<?php
class Foo
{
static $variable = 'статическое свойство';
static function Variable()
{
echo 'Вызов метода Variable';
}
}
echo Foo::$variable; // Это выведет 'статическое свойство'. Переменная $variable будет разрешена в этой области видимости.
$variable = "Variable";
Foo::$variable(); // Это вызовет $foo->Variable(), прочитав $variable из этой области видимости.
?>
Пример #4 Сложные callable-функции
<?php
class Foo
{
static function bar()
{
echo "bar\n";
}
function baz()
{
echo "baz\n";
}
}
$func = array("Foo", "bar");
$func(); // выведет "bar"
$func = array(new Foo, "baz");
$func(); // выведет "baz"
$func = "Foo::bar";
$func(); // выведет "bar"
?>В самом PHP содержится достаточно большое количество встроенных функций и языковых конструкций. Также есть функции, которые требуют, чтобы PHP был собран с определёнными модулями, в противном случае будут генерироваться фатальные ошибки, вызванные использованием неизвестной функции. Например, для того чтобы использовать функции для работы с изображениями, например, imagecreatetruecolor(), необходимо собрать PHP с поддержкой GD. Или же для того, чтобы воспользоваться функцией mysqli_connect(), необходима поддержка модуля MySQLi. Тем не менее, есть много встроенных функций, которые доступны всегда: например, функции обработки строк и функции для работы с переменными. Вызвав phpinfo() или get_loaded_extensions(), можно узнать, поддержка каких модулей есть в используемом PHP. Также следует учесть, что поддержка некоторых дополнительных модулей включена по умолчанию, и что сама документация к PHP разбита по модулям. Ознакомьтесь с разделами Конфигурация, Установка, а также с документацией непосредственно к дополнительным модулям для получения более детальной информации о том, как настроить PHP.
Более подробную информацию о том, как следует читать и интерпретировать прототипы функций, вы можете найти в разделе Как читать определения функции. Очень важно понимать, что возвращает функция, или как именно она модифицирует передаваемые аргументы. Например, функция str_replace() возвращает модифицированную строку, в то время как функция usort() работает с фактически переданной переменной. Каждая страница документации также содержит информацию, которая специфична для данной функции, например, информацию о передаваемых параметрах, изменениях в поведении, возвращаемых значениях в случае как удачного, так и неудачного выполнения, доступности функции в различных версиях. Знание и применение этих (порой даже незаметных) нюансов очень важно для написания корректного PHP-кода.
Замечание: Если в функцию передаются не те аргументы, которые она ожидает, например, массив (array) вместо строки (string), возвращаемое значение функции не определено. Скорее всего в этом случае будет возвращён
null, но это просто соглашение, на него нельзя полагаться. Начиная с PHP 8.0.0, в этом случае должно быть выброшено исключение TypeError.
Замечание:
Скалярные типы для встроенных функций по умолчанию являются допускающими значение
nullв принудительном режиме. Начиная с PHP 8.1.0, передачаnullв параметр встроенной функции, который не объявлен как допускающий значениеnull, не рекомендуется и в принудительном режиме выдаётся уведомление об устаревании, чтобы соответствовать поведению пользовательских функций, где скалярные типы должны быть явно помечены как допускающие значениеnull.Например, функция strlen() ожидает, что параметр
$stringбудет строкой (string), не допускающей значениеnull. По историческим причинам PHP позволяет передаватьnullдля этого параметра в принудительном режиме и параметр неявно приводится к строке (string), в результате чего получается значение"". В строгом режиме выбрасывается исключение TypeError.<?php
var_dump(strlen(null));
// "Deprecated: Passing null to parameter #1 ($string) of type string is deprecated" начиная с PHP 8.1.0
// int(0)
var_dump(str_contains("foobar", null));
// "Deprecated: Passing null to parameter #2 ($needle) of type string is deprecated" начиная с PHP 8.1.0
// bool(true)
?>
Анонимные функции, также известные как замыкания (closures),
позволяют создавать функции, не имеющие определённых имён.
Они наиболее полезны в качестве значений
callable-параметров,
но также могут иметь и множество других применений.
Анонимные функции реализуются с использованием класса Closure.
Пример #1 Пример анонимной функции
<?php
echo preg_replace_callback('~-([a-z])~', function ($match) {
return strtoupper($match[1]);
}, 'hello-world');
// выведет helloWorld
?>Замыкания также могут быть использованы в качестве значений переменных; PHP автоматически преобразует такие выражения в экземпляры внутреннего класса Closure. Присвоение замыкания переменной использует тот же синтаксис, что и для любого другого присвоения, включая завершающую точку с запятой:
Пример #2 Пример присвоения анонимной функции переменной
<?php
$greet = function($name) {
printf("Привет, %s\r\n", $name);
};
$greet('Мир');
$greet('PHP');
?>
Замыкания могут также наследовать переменные из родительской
области видимости. Любая подобная переменная должна быть
объявлена в конструкции use. Начиная с
PHP 7.1, эти переменные не должны включать superglobals,
$this и переменные с теми же именами, что и
параметры функции.
Объявление типа возвращаемого значения функции должно быть помещено
после конструкции use.
Пример #3 Наследование переменных из родительской области видимости
<?php
$message = 'привет';
// Без "use"
$example = function () {
var_dump($message);
};
$example();
// Наследуем $message
$example = function () use ($message) {
var_dump($message);
};
$example();
// Значение унаследованной переменной задано там, где функция определена,
// но не там, где вызвана
$message = 'мир';
$example();
// Сбросим message
$message = 'привет';
// Наследование по ссылке
$example = function () use (&$message) {
var_dump($message);
};
$example();
// Изменённое в родительской области видимости значение
// остаётся тем же внутри вызова функции
$message = 'мир';
echo $example();
// Замыкания могут принимать обычные аргументы
$example = function ($arg) use ($message) {
var_dump($arg . ', ' . $message);
};
$example("привет");
// Объявление типа возвращаемого значения идет после конструкции use
$example = function () use ($message): string {
return "привет $message";
};
var_dump($example());
?>Результатом выполнения данного примера будет что-то подобное:
Notice: Undefined variable: message in /example.php on line 6 NULL string(6) "привет" string(6) "привет" string(6) "привет" string(3) "мир" string(11) "привет, мир" string(10) "привет мир"
Начиная с PHP 8.0.0, список наследуемых переменных может завершаться запятой, которая будет проигнорирована.
Наследование переменных из родительской области видимости не то же самое, что использование глобальных переменных. Глобальные переменные существуют в глобальной области видимости, которая не меняется, вне зависимости от того, какая функция выполняется в данный момент. Родительская область видимости - это функция, в которой было объявлено замыкание (не обязательно та же самая, из которой оно было вызвано). Смотрите следующий пример:
Пример #4 Замыкания и область видимости
<?php
// Базовая корзина покупок, содержащая список добавленных
// продуктов и количество каждого продукта. Включает метод,
// вычисляющий общую цену элементов корзины с помощью
// callback-замыкания.
class Cart
{
const PRICE_BUTTER = 1.00;
const PRICE_MILK = 3.00;
const PRICE_EGGS = 6.95;
protected $products = array();
public function add($product, $quantity)
{
$this->products[$product] = $quantity;
}
public function getQuantity($product)
{
return isset($this->products[$product]) ? $this->products[$product] :
FALSE;
}
public function getTotal($tax)
{
$total = 0.00;
$callback =
function ($quantity, $product) use ($tax, &$total)
{
$pricePerItem = constant(__CLASS__ . "::PRICE_" .
strtoupper($product));
$total += ($pricePerItem * $quantity) * ($tax + 1.0);
};
array_walk($this->products, $callback);
return round($total, 2);
}
}
$my_cart = new Cart;
// Добавляем несколько элементов в корзину
$my_cart->add('butter', 1);
$my_cart->add('milk', 3);
$my_cart->add('eggs', 6);
// Выводим общую сумму с 5% налогом на продажу.
print $my_cart->getTotal(0.05) . "\n";
// Результатом будет 54.29
?>Пример #5 Автоматическое связывание $this
<?php
class Test
{
public function testing()
{
return function() {
var_dump($this);
};
}
}
$object = new Test;
$function = $object->testing();
$function();
?>Результат выполнения данного примера:
object(Test)#1 (0) {
}
При объявлении в контексте класса, текущий
класс будет автоматически связан с ним, делая $this
доступным внутри функций класса. Если вы не хотите автоматического
связывания с текущим классом, используйте статические анонимные функции.
Анонимные функции могут быть объявлены статически. Это предотвратит их автоматическое связывание с текущим классом. Объекты также не будут с ними связаны во время выполнения.
Пример #6 Попытка использовать $this в статической анонимной функции
<?php
class Foo
{
function __construct()
{
$func = static function() {
var_dump($this);
};
$func();
}
};
new Foo();
?>Результат выполнения данного примера:
Notice: Undefined variable: this in %s on line %d NULL
Пример #7 Попытка связать объект со статической анонимной функцией
<?php
$func = static function() {
// тело функции
};
$func = $func->bindTo(new stdClass);
$func();
?>Результат выполнения данного примера:
Warning: Cannot bind an instance to a static closure in %s on line %d
| Версия | Описание |
|---|---|
| 7.1.0 | Анонимные функции не могут замыкаться вокруг superglobals, $this или любой переменной с тем же именем, что и параметр. |
Замечание: Совместно с замыканиями можно использовать функции func_num_args(), func_get_arg() и func_get_args().
Стрелочные функции появились в PHP 7.4, как более лаконичный синтаксис для анонимных функций.
И анонимные, и стрелочные функции реализованы с использованием класса Closure.
Основной вид записи стрелочных функций:
fn (argument_list) => expr.
Стрелочные функции поддерживают те же возможности, что и анонимные функции, за исключением того, что использование переменных из родительской области всегда выполняется автоматически.
Когда переменная, используемая в выражении, определена в родительской области, она будет неявно захвачена по значению. В следующем примере функции $fn1 и $fn2 ведут себя одинаково.
Пример #1 Стрелочные функции захватывают переменные по значению автоматически
<?php
$y = 1;
$fn1 = fn($x) => $x + $y;
// эквивалентно использованию $y по значению:
$fn2 = function ($x) use ($y) {
return $x + $y;
};
var_export($fn1(3));
?>Результат выполнения данного примера:
4
Это также работает во вложенных стрелочных функциях:
Пример #2 Стрелочные функции захватывают переменные по значению автоматически, даже когда они вложены
<?php
$z = 1;
$fn = fn($x) => fn($y) => $x * $y + $z;
// Выведет 51
var_export($fn(5)(10));
?>Подобно анонимным функциям, синтаксис стрелочных функций допускает произвольные сигнатуры функций, включая типы параметров и возвращаемых значений, значения по умолчанию, переменные, а также передачу и возврат по ссылке. Ниже приведены корректные примеры стрелочных функций:
Пример #3 Примеры использования стрелочных функций
<?php
fn(array $x) => $x;
static fn(): int => $x;
fn($x = 42) => $x;
fn(&$x) => $x;
fn&($x) => $x;
fn($x, ...$rest) => $rest;
?>
Стрелочные функции используют привязку переменных по значению.
Это примерно эквивалентно выполнению use($x) для каждой
переменной $x, используемой внутри стрелочной функции.
Привязка по значению означает, что невозможно изменить какие-либо значения
из внешней области.
Вместо этого можно использовать анонимные функции
для привязок по ссылкам.
Пример #4 Значения из внешней области видимости не могут быть изменены стрелочными функциями
<?php
$x = 1;
$fn = fn() => $x++; // Ничего не изменит
$fn();
var_export($x); // Выведет 1
?>
| Версия | Описание |
|---|---|
| 7.4.0 | Стали доступны стрелочные функции. |
Замечание: Можно использовать func_num_args(), func_get_arg() и func_get_args() в стрелочной функции.
Callback-функции как объекты первого класса представлены в PHP 8.1.0 как способ создания анонимных функций из callback-функций. Синтаксис заменяет существующий синтаксис вызова с использованием строк и массивов. Преимущество синтаксиса заключается в том, что он доступен для статического анализа и использует область видимости в точке, где получена callback-функция.
Синтаксис CallableExpr(...) используется для создания объекта Closure из callback-функции. CallableExpr принимает любое выражение, которое может быть вызвано напрямую в грамматике PHP:
Пример #1 Простой пример callback-функции как объекты первого класса
<?php
class Foo {
public function method() {}
public static function staticmethod() {}
public function __invoke() {}
}
$obj = new Foo();
$classStr = 'Foo';
$methodStr = 'method';
$staticmethodStr = 'staticmethod';
$f1 = strlen(...);
$f2 = $obj(...); // вызываемый объект
$f3 = $obj->method(...);
$f4 = $obj->$methodStr(...);
$f5 = Foo::staticmethod(...);
$f6 = $classStr::$staticmethodStr(...);
// традиционная callback-функция с использованием строки, массива
$f7 = 'strlen'(...);
$f8 = [$obj, 'method'](...);
$f9 = [Foo::class, 'staticmethod'](...);
?>Замечание:
...является частью синтаксиса, а не пропуском.
У CallableExpr(...) та же семантика, что и у Closure::fromCallable().
То есть, в отличие от callback-функции с использованием строк и массивов, CallableExpr(...) учитывает область видимости в точке, где она создаётся:
Пример #2 Сравнение области действия CallableExpr(...) и традиционной callback-функции
<?php
class Foo {
public function getPrivateMethod() {
return [$this, 'privateMethod'];
}
private function privateMethod() {
echo __METHOD__, "\n";
}
}
$foo = new Foo;
$privateMethod = $foo->getPrivateMethod();
$privateMethod();
// Fatal error: Call to private method Foo::privateMethod() from global scope
// Это потому, что вызов выполняется вне Foo, и с этого момента будет проверяться видимость.
class Foo1 {
public function getPrivateMethod() {
// Использует область, в которой получена callback-функция.
return $this->privateMethod(...); // идентично Closure::fromCallable([$this, 'privateMethod']);
}
private function privateMethod() {
echo __METHOD__, "\n";
}
}
$foo1 = new Foo1;
$privateMethod = $foo1->getPrivateMethod();
$privateMethod(); // Foo1::privateMethod
?>Замечание:
Создание объекта с помощью этого синтаксиса (например,
new Foo(...)) не поддерживается, поскольку синтаксисnew Foo()не считается callback-функцией.
Замечание:
Callback-функции как объекты первого класса нельзя комбинировать с оператором Nullsafe. Оба следующих результата приводят к ошибке времени компиляции:
<?php
$obj?->method(...);
$obj?->prop->method(...);
?>
PHP включает полноценную объектную модель. Некоторые из её особенностей: видимость, абстрактные и ненаследуемые (final) классы и методы, а также магические методы, интерфейсы и клонирование.
PHP работает с объектами так же, как с ссылками или дескрипторами, это означает что каждая переменная содержит ссылку на объект, а не его копию. Более подробную информацию смотрите в разделе Объекты и ссылки.
Смотрите также Руководство по именованию.
Каждое определение класса начинается с ключевого слова class, затем
следует имя класса, и далее пара фигурных скобок, которые заключают в себе определение
свойств и методов этого класса.
Именем класса может быть любое слово, при условии, что оно не входит в список
зарезервированных слов PHP, начинается с буквы или
символа подчёркивания и за которым следует любое количество букв, цифр или символов
подчёркивания. Если задать эти правила в виде регулярного выражения, то получится
следующее выражение: ^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$.
Класс может содержать собственные константы, переменные (называемые свойствами) и функции (называемые методами).
Пример #1 Простое определение класса
<?php
class SimpleClass
{
// объявление свойства
public $var = 'значение по умолчанию';
// объявление метода
public function displayVar() {
echo $this->var;
}
}
?>Псевдопеременная $this доступна в том случае, если метод был вызван в контексте объекта. $this - значение вызывающего объекта.
Вызов нестатического метода статически вызывает ошибку Error. До PHP 8.0.0 это привело бы к уведомлению об устаревании, и $this не была бы определена.
Пример #2 Некоторые примеры псевдо-переменной $this
<?php
class A
{
function foo()
{
if (isset($this)) {
echo '$this определена (';
echo get_class($this);
echo ")\n";
} else {
echo "\$this не определена.\n";
}
}
}
class B
{
function bar()
{
A::foo();
}
}
$a = new A();
$a->foo();
A::foo();
$b = new B();
$b->bar();
B::bar();
?>Результат выполнения данного примера в PHP 7:
$this определена (A) Deprecated: Non-static method A::foo() should not be called statically in %s on line 27 $this не определена. Deprecated: Non-static method A::foo() should not be called statically in %s on line 20 $this не определена. Deprecated: Non-static method B::bar() should not be called statically in %s on line 32 Deprecated: Non-static method A::foo() should not be called statically in %s on line 20 $this не определена.
Результат выполнения данного примера в PHP 8:
$this определена (A)
Fatal error: Uncaught Error: Non-static method A::foo() cannot be called statically in %s :27
Stack trace:
#0 {main}
thrown in %s on line 27
Начиная с PHP 8.2.0, класс может быть помечен модификатором readonly. Пометка класса как readonly добавит модификатор readonly к каждому объявленному свойству и предотвратит создание динамических свойств. Более того, невозможно добавить их поддержку с помощью атрибута AllowDynamicProperties. Попытка это сделать приведёт к ошибке компиляции.
<?php
#[\AllowDynamicProperties]
readonly class Foo {
}
// Fatal error: Cannot apply #[AllowDynamicProperties] to readonly class Foo
?>
Поскольку ни нетипизированные, ни статические свойства
не могут быть помечены модификатором readonly,
классы, доступные только для чтения также не могут их объявлять:
<?php
readonly class Foo
{
public $bar;
}
// Fatal error: Readonly property Foo::$bar must have type
?><?php
readonly class Foo
{
public static int $bar;
}
// Fatal error: Readonly class Foo cannot declare static properties
?>Класс readonly может быть расширен тогда и только тогда, когда дочерний класс также является классом readonly.
Для создания экземпляра класса используется директива new.
Новый объект всегда будет создан, за исключением случаев, когда он содержит
конструктор, в котором определён вызов
исключения в случае возникновения ошибки.
Рекомендуется определять классы до создания их экземпляров
(в некоторых случаях это обязательно).
Если с директивой new используется строка (string),
содержащая имя класса, то будет создан новый экземпляр этого класса. Если
имя находится в пространстве имён, то оно должно быть задано полностью.
Замечание:
В случае отсутствия аргументов в конструктор класса, круглые скобки после названия класса можно опустить.
Пример #3 Создание экземпляра класса
<?php
$instance = new SimpleClass();
// Это же можно сделать с помощью переменной:
$className = 'SimpleClass';
$instance = new $className(); // new SimpleClass()
?>
Начиная с PHP 8.0.0, поддерживается использование оператора new с произвольными выражениями.
Это позволяет создавать более сложные экземпляры, если выражение представлено в виде строки (string).
Выражения должны быть заключены в круглые скобки.
Пример #4 Создание экземпляра с использованием произвольного выражения
В данном примере мы показываем несколько вариантов допустимых произвольных выражений, которые представляют имя класса.
Пример вызова функции, конкатенации строк и константы ::class.
<?php
class ClassA extends \stdClass {}
class ClassB extends \stdClass {}
class ClassC extends ClassB {}
class ClassD extends ClassA {}
function getSomeClass(): string
{
return 'ClassA';
}
var_dump(new (getSomeClass()));
var_dump(new ('Class' . 'B'));
var_dump(new ('Class' . 'C'));
var_dump(new (ClassD::class));
?>Результат выполнения данного примера в PHP 8:
object(ClassA)#1 (0) {
}
object(ClassB)#1 (0) {
}
object(ClassC)#1 (0) {
}
object(ClassD)#1 (0) {
}
В контексте класса можно создать новый объект через
new self и new parent.
Когда происходит присвоение уже существующего экземпляра класса новой переменной, то эта переменная будет указывать на этот же экземпляр класса. То же самое происходит и при передаче экземпляра класса в функцию. Копию уже созданного объекта можно создать через её клонирование.
Пример #5 Присваивание объекта
<?php
$instance = new SimpleClass();
$assigned = $instance;
$reference =& $instance;
$instance->var = '$assigned будет иметь это значение';
$instance = null; // $instance и $reference становятся null
var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>Результат выполнения данного примера:
NULL
NULL
object(SimpleClass)#1 (1) {
["var"]=>
string(30) "$assigned будет иметь это значение"
}
Создавать экземпляры объекта можно двумя способами:
Пример #6 Создание новых объектов
<?php
class Test
{
static public function getNew()
{
return new static;
}
}
class Child extends Test
{}
$obj1 = new Test();
$obj2 = new $obj1;
var_dump($obj1 !== $obj2);
$obj3 = Test::getNew();
var_dump($obj3 instanceof Test);
$obj4 = Child::getNew();
var_dump($obj4 instanceof Child);
?>Результат выполнения данного примера:
bool(true) bool(true) bool(true)
Обратиться к свойству или методу только что созданного объекта можно с помощью одного выражения:
Пример #7 Доступ к свойствам/методам только что созданного объекта
<?php
echo (new DateTime())->format('Y');
?>Результатом выполнения данного примера будет что-то подобное:
2016
Замечание: До PHP 7.1 аргументы не имели значения, если не определена функция конструктора.
Свойства и методы класса живут в разделённых "пространствах имён", так что возможно иметь свойство и метод с одним и тем же именем. Ссылки как на свойства, так и на методы имеют одинаковую нотацию, и получается, что получите вы доступ к свойству или же вызовете метод - определяется контекстом использования.
Пример #8 Доступ к свойству vs. вызов метода
<?php
class Foo
{
public $bar = 'свойство';
public function bar() {
return 'метод';
}
}
$obj = new Foo();
echo $obj->bar, PHP_EOL, $obj->bar(), PHP_EOL;Результат выполнения данного примера:
свойство метод
Это означает, что вызвать анонимную функцию, присвоенную переменной, напрямую не получится. Вместо этого свойство должно быть назначено, например, переменной. Можно вызвать такое свойство напрямую, заключив его в скобки.
Пример #9 Вызов анонимной функции, содержащейся в свойстве
<?php
class Foo
{
public $bar;
public function __construct() {
$this->bar = function() {
return 42;
};
}
}
$obj = new Foo();
echo ($obj->bar)(), PHP_EOL;Результат выполнения данного примера:
42
Класс может наследовать константы, методы и свойства другого класса используя
ключевое слово extends в его объявлении. Невозможно наследовать несколько
классов, один класс может наследовать только один базовый класс.
Наследуемые константы, методы и свойства могут быть переопределены (за исключением случаев, когда метод или константа класса объявлены как final) путём объявления их с теми же именами, как и в родительском классе. Существует возможность доступа к переопределённым методам или статическим свойствам путём обращения к ним через parent::
Замечание: Начиная с PHP 8.1.0, константы можно объявлять окончательными (final).
Пример #10 Простое наследование классов
<?php
class ExtendClass extends SimpleClass
{
// Переопределение метода родителя
function displayVar()
{
echo "Расширенный класс\n";
parent::displayVar();
}
}
$extended = new ExtendClass();
$extended->displayVar();
?>Результат выполнения данного примера:
Расширенный класс значение по умолчанию
При переопределении метода его сигнатура должна быть совместима с родительским методом.
В противном случае выдаётся фатальная ошибка или, до PHP 8.0.0,
генерируется ошибка уровня E_WARNING.
Сигнатура является совместимой, если она соответствует правилам контравариантности, делает
обязательный параметр необязательным, добавляет только необязательные новые параметры и не ограничивает,
а только ослабляет видимость.
Это известно как принцип подстановки Барбары Лисков или сокращённо LSP.
Правила совместимости не распространяются на конструктор и
сигнатуру private методов, они не будут выдавать фатальную ошибку
в случае несоответствия сигнатуры.
Пример #11 Совместимость дочерних методов
<?php
class Base
{
public function foo(int $a) {
echo "Допустимо\n";
}
}
class Extend1 extends Base
{
function foo(int $a = 5)
{
parent::foo($a);
}
}
class Extend2 extends Base
{
function foo(int $a, $b = 5)
{
parent::foo($a);
}
}
$extended1 = new Extend1();
$extended1->foo();
$extended2 = new Extend2();
$extended2->foo(1);Результат выполнения данного примера:
Допустимо Допустимо
Следующие примеры демонстрируют, что дочерний метод, который удаляет параметр или делает необязательный параметр обязательным, несовместим с родительским методом.
Пример #12 Фатальная ошибка, когда дочерний метод удаляет параметр
<?php
class Base
{
public function foo(int $a = 5) {
echo "Допустимо\n";
}
}
class Extend extends Base
{
function foo()
{
parent::foo(1);
}
}Результат выполнения данного примера в PHP 8 аналогичен:
Fatal error: Declaration of Extend::foo() must be compatible with Base::foo(int $a = 5) in /in/evtlq on line 13
Пример #13 Фатальная ошибка, когда дочерний метод делает необязательный параметр обязательным.
<?php
class Base
{
public function foo(int $a = 5) {
echo "Допустимо\n";
}
}
class Extend extends Base
{
function foo(int $a)
{
parent::foo($a);
}
}Результат выполнения данного примера в PHP 8 аналогичен:
Fatal error: Declaration of Extend::foo(int $a) must be compatible with Base::foo(int $a = 5) in /in/qJXVC on line 13
Переименование параметра метода в дочернем классе не является несовместимостью сигнатуры. Однако это не рекомендуется, так как приведёт к Error во время выполнения, если используются именованные аргументы.
Пример #14 Ошибка при использовании именованных аргументов и параметров, переименованных в дочернем классе
<?php
class A {
public function test($foo, $bar) {}
}
class B extends A {
public function test($a, $b) {}
}
$obj = new B;
// Передача параметров согласно контракту A::test()
$obj->test(foo: "foo", bar: "bar"); // ОШИБКА!Результатом выполнения данного примера будет что-то подобное:
Fatal error: Uncaught Error: Unknown named parameter $foo in /in/XaaeN:14
Stack trace:
#0 {main}
thrown in /in/XaaeN on line 14
Ключевое слово class используется
для разрешения имени класса.
Чтобы получить полное имя класса ClassName,
используйте ClassName::class.
Обычно это довольно полезно при работе с классами, использующими
пространства имён.
Пример #15 Разрешение имени класса
<?php
namespace NS {
class ClassName {
}
echo ClassName::class;
}
?>Результат выполнения данного примера:
NS\ClassName
Замечание:
Разрешение имён класса с использованием
::classпроисходит на этапе компиляции. Это означает, что на момент создания строки с именем класса автозагрузки класса не происходит. Как следствие, имена классов раскрываются, даже если класс не существует. Ошибка в этом случае не выдаётся.Пример #16 Отсутствует разрешение имени класса
<?php
print Does\Not\Exist::class;
?>Результат выполнения данного примера:
Does\Not\Exist
Начиная с PHP 8.0.0, константа ::class также может использоваться
для объектов. Это разрешение происходит во время выполнения, а не во время компиляции.
То же самое, что и при вызове get_class() для объекта.
Пример #17 Разрешение имени объекта
<?php
namespace NS {
class ClassName {
}
}
$c = new ClassName();
print $c::class;
?>Результат выполнения данного примера:
NS\ClassName
Начиная с PHP 8.0.0, к свойствам и методам можно также
обращаться с помощью оператора "nullsafe": ?->.
Оператор nullsafe работает так же, как доступ к свойству или методу, как указано выше,
за исключением того, что если разыменование объекта выдаёт null, то
будет возвращён null, а не выброшено исключение. Если разыменование является частью цепочки,
остальная часть цепочки пропускается.
Аналогично заключению каждого обращения в is_null(), но более компактный.
Пример #18 Оператор Nullsafe
<?php
// Начиная с PHP 8.0.0, эта строка:
$result = $repository?->getUser(5)?->name;
// Эквивалентна следующему блоку кода:
if (is_null($repository)) {
$result = null;
} else {
$user = $repository->getUser(5);
if (is_null($user)) {
$result = null;
} else {
$result = $user->name;
}
}
?>Замечание:
Оператор nullsafe лучше всего использовать, когда null считается допустимым и ожидаемым значением для возвращаемого свойства или метода. Для индикации ошибки предпочтительнее выбрасывать исключение.
Переменные, которые являются членами класса, называются свойства.
Также их называют, используя другие термины, таких как поля,
но в рамках этой документации,
мы будем называть их свойствами.
Они определяются с использованием хотя бы одного необязательного (за исключением readonly-свойств) модификатора
(например, Область видимости, Ключевое слово static или,
начиная с PHP 8.1.0, readonly), начиная с PHP 7.4,
за которым следует необязательное объявление типа, за которым следует обычное объявление переменной.
Это объявление может содержать инициализацию, но
эта инициализация должна быть постоянным значением.
Замечание:
Устаревший способ объявления свойств класса — использование ключевого слова
varвместо модификатора.
Замечание: Свойство, объявленное без модификатора Область видимости, будет объявлено как
public.
В пределах методов класса доступ к нестатическим свойствам может быть
получен с помощью -> (объектного оператора):
$this->property (где property - имя свойства).
Доступ к статическим свойствам осуществляется с помощью ::
(двойного двоеточия): self::$property. Дополнительную информацию о различии
статических и нестатических свойств смотрите в разделе
Ключевое слово static.
Псевдопеременная $this доступна внутри любого метода класса, когда этот метод вызывается из контекста объекта. $this - значение вызывающего объекта.
Пример #1 Определение свойств
<?php
class SimpleClass
{
public $var1 = 'hello ' . 'world';
public $var2 = <<<EOD
hello world
EOD;
public $var3 = 1+2;
// неправильное определение свойств:
public $var4 = self::myStaticMethod();
public $var5 = $myVar;
// правильное определение свойств:
public $var6 = myConstant;
public $var7 = [true, false];
public $var8 = <<<'EOD'
hello world
EOD;
// Без модификатора области видимости:
static $var9;
readonly int $var10;
}
?>Замечание:
Существуют различные функции для обработки классов и объектов. Смотрите справочник по функций для классов/объектов.
Начиная с PHP 7.4.0, определения свойств могут включать Объявление типов, за исключением типа callable.
Пример #2 Пример использования типизированных свойств
<?php
class User
{
public int $id;
public ?string $name;
public function __construct(int $id, ?string $name)
{
$this->id = $id;
$this->name = $name;
}
}
$user = new User(1234, null);
var_dump($user->id);
var_dump($user->name);
?>Результат выполнения данного примера:
int(1234) NULL
Перед обращением к типизированному свойству у него должно быть задано значение, иначе будет выброшено исключение Error.
Пример #3 Обращение к свойствам
<?php
class Shape
{
public int $numberOfSides;
public string $name;
public function setNumberOfSides(int $numberOfSides): void
{
$this->numberOfSides = $numberOfSides;
}
public function setName(string $name): void
{
$this->name = $name;
}
public function getNumberOfSides(): int
{
return $this->numberOfSides;
}
public function getName(): string
{
return $this->name;
}
}
$triangle = new Shape();
$triangle->setName("triangle");
$triangle->setNumberofSides(3);
var_dump($triangle->getName());
var_dump($triangle->getNumberOfSides());
$circle = new Shape();
$circle->setName("circle");
var_dump($circle->getName());
var_dump($circle->getNumberOfSides());
?>Результат выполнения данного примера:
string(8) "triangle" int(3) string(6) "circle" Fatal error: Uncaught Error: Typed property Shape::$numberOfSides must not be accessed before initialization
Начиная с PHP 8.1.0, свойство можно объявить с помощью модификатора readonly, который предотвращает изменение свойства после инициализации.
Пример #4 Примеры readonly-свойств
<?php
class Test {
public readonly string $prop;
public function __construct(string $prop) {
// Правильная инициализация.
$this->prop = $prop;
}
}
$test = new Test("foobar");
// Правильное чтение.
var_dump($test->prop); // string(6) "foobar"
// Неправильное переопределение. Не имеет значения, что присвоенное значение такое же.
$test->prop = "foobar";
// Ошибка: невозможно изменить readonly-свойство Test::$prop
?>Замечание:
Модификатор readonly может применяться только к типизированным свойствам. Readonly-свойство без ограничений типа можно создать с помощью типа Mixed.
Замечание:
Статические readonly-свойства не поддерживаются.
Readonly-свойство можно инициализировать только один раз и только из области, в которой оно было объявлено. Любое другое присвоение или изменение свойства приведёт к исключению Error.
Пример #5 Неправильная инициализация readonly-свойств
<?php
class Test1 {
public readonly string $prop;
}
$test1 = new Test1;
// Неправильная инициализация за пределами закрытой области.
$test1->prop = "foobar";
// Ошибка: не удаётся инициализировать readonly-свойство Test1::$prop из глобальной области
?>Замечание:
Указание явного значения по умолчанию для readonly-свойств не допускается, потому что readonly-свойство со значением по умолчанию, по сути, то же самое, что и константа и поэтому не особенно полезно.
<?php
class Test {
// Ошибка: у readonly-свойства Test::$prop не может быть значения по умолчанию
public readonly int $prop = 42;
}
?>
Замечание:
Readonly-свойства не могут быть уничтожены с помощью unset() после их инициализации. Однако можно уничтожить readonly-свойство до инициализации из области, в которой было объявлено свойство.
Модификации не обязательно являются простыми присвоениями, всё перечисленное ниже также приведёт к исключению Error:
<?php
class Test {
public function __construct(
public readonly int $i = 0,
public readonly array $ary = [],
) {}
}
$test = new Test;
$test->i += 1;
$test->i++;
++$test->i;
$test->ary[] = 1;
$test->ary[0][] = 1;
$ref =& $test->i;
$test->i =& $ref;
byRef($test->i);
foreach ($test as &$prop);
?>Однако readonly-свойства не исключают внутренней изменчивости. Объекты (или ресурсы), хранящиеся в readonly-свойствах по-прежнему могут быть изменены внутри:
<?php
class Test {
public function __construct(public readonly object $obj) {}
}
$test = new Test(new stdClass);
// Правильное внутреннее изменение.
$test->obj->foo = 1;
// Неправильное переопределение.
$test->obj = new stdClass;
?>При попытке присвоить несуществующее свойство объекту (object), PHP автоматически создаст соответствующее свойство. Это динамически созданное свойство будет доступно только для данного экземпляра класса.
Константы также могут быть объявлены в пределах одного класса.
Область видимости констант по умолчанию public.
Замечание:
Константы класса могут быть переопределены дочерним классом. Начиная с PHP 8.1.0, константы класса не могут быть переопределены дочерним классом, если он определён как окончательный (final).
Интерфейсы также могут содержать константы. За примерами обращайтесь к разделу об интерфейсах.
К классу можно обратиться с помощью переменной.
Значение переменной не может быть ключевым словом
(например, self, parent и
static).
Обратите внимание, что константы класса задаются один раз для всего класса, а не отдельно для каждого созданного объекта этого класса.
Пример #1 Объявление и использование константы
<?php
class MyClass
{
const CONSTANT = 'значение константы';
function showConstant() {
echo self::CONSTANT . "\n";
}
}
echo MyClass::CONSTANT . "\n";
$classname = "MyClass";
echo $classname::CONSTANT . "\n";
$class = new MyClass();
$class->showConstant();
echo $class::CONSTANT."\n";
?>
Специальная константа ::class,
которой на этапе компиляции присваивается полное имя класса, полезна при использовании с классами,
использующими пространства имён.
Пример #2 Пример использования ::class с пространством имён
<?php
namespace foo {
class bar {
}
echo bar::class; // foo\bar
}
?>Пример #3 Пример констант, заданных выражением
<?php
const ONE = 1;
class foo {
const TWO = ONE * 2;
const THREE = ONE + self::TWO;
const SENTENCE = 'Значение константы THREE - ' . self::THREE;
}
?>Пример #4 Модификаторы видимости констант класса, начиная с PHP 7.1.0
<?php
class Foo {
public const BAR = 'bar';
private const BAZ = 'baz';
}
echo Foo::BAR, PHP_EOL;
echo Foo::BAZ, PHP_EOL;
?>Результат выполнения данного примера в PHP 7.1:
bar Fatal error: Uncaught Error: Cannot access private const Foo::BAZ in …
Замечание:
Начиная с PHP 7.1.0 для констант класса можно использовать модификаторы области видимости.
Большинство разработчиков объектно-ориентированных приложений используют такое соглашение именования файлов, в котором каждый класс хранится в отдельно созданном для него файле. Одна из самых больших неприятностей - необходимость писать в начале каждого скрипта длинный список подгружаемых файлов (по одному для каждого класса).
Функция spl_autoload_register() позволяет зарегистрировать необходимое количество автозагрузчиков для автоматической загрузки классов и интерфейсов, если они в настоящее время не определены. Регистрируя автозагрузчики, PHP получает последний шанс для интерпретатора загрузить класс прежде, чем он закончит выполнение скрипта с ошибкой.
Любая конструкция, подобная классу может быть автоматически загружена таким же образом, включая классы, интерфейсы, трейты и перечисления.
До PHP 8.0.0 можно было использовать __autoload() для автозагрузки классов и интерфейсов. Однако это менее гибкая альтернатива spl_autoload_register(), функция __autoload() объявлена устаревшей в PHP 7.2.0 и удалена в PHP 8.0.0.
Замечание:
Функция spl_autoload_register() может быть вызвана несколько раз, чтобы зарегистрировать несколько автозагрузчиков. Выброс исключения из функции автозагрузки, однако, прервёт этот процесс и не позволит запускать дальнейшие функции автозагрузки. По этой причине выбрасывать исключения из функции автозагрузки настоятельно не рекомендуется.
Пример #1 Пример автоматической загрузки
В этом примере функция пытается загрузить классы MyClass1
и MyClass2 из файлов MyClass1.php
и MyClass2.php соответственно.
<?php
spl_autoload_register(function ($class_name) {
include $class_name . '.php';
});
$obj = new MyClass1();
$obj2 = new MyClass2();
?>Пример #2 Ещё один пример автоматической загрузки
В этом примере представлена попытка загрузки интерфейса ITest.
<?php
spl_autoload_register(function ($name) {
var_dump($name);
});
class Foo implements ITest {
}
/*
string(5) "ITest"
Fatal error: Interface 'ITest' not found in ...
*/
?>PHP позволяет объявлять методы-конструкторы. Классы, в которых объявлен метод-конструктор, будут вызывать этот метод при каждом создании нового объекта, так что это может оказаться полезным, например, для инициализации какого-либо состояния объекта перед его использованием.
Замечание: Конструкторы, определённые в классах-родителях, не вызываются автоматически, если дочерний класс определяет собственный конструктор. Чтобы вызвать конструктор, объявленный в родительском классе, требуется вызвать parent::__construct() внутри конструктора дочернего класса. Если в дочернем классе не определён конструктор, то он может быть унаследован от родительского класса как обычный метод (если он не был определён как приватный).
Пример #1 Конструкторы при наследовании
<?php
class BaseClass {
function __construct() {
print "Конструктор класса BaseClass\n";
}
}
class SubClass extends BaseClass {
function __construct() {
parent::__construct();
print "Конструктор класса SubClass\n";
}
}
class OtherSubClass extends BaseClass {
// наследует конструктор BaseClass
}
// Конструктор класса BaseClass
$obj = new BaseClass();
// Конструктор класса BaseClass
// Конструктор класса SubClass
$obj = new SubClass();
// Конструктор класса BaseClass
$obj = new OtherSubClass();
?>В отличие от других методов, __construct() освобождается от обычных правил совместимости сигнатуры при наследовании.
Конструкторы - это обычные методы, которые вызываются при инстанциировании соответствующих объектов. Следовательно, они могут иметь произвольное количество аргументов, которые могут быть обязательными, могут быть типизированными и могут иметь значения по умолчанию. Аргументы конструктора указываются в круглых скобках после имени класса.
Пример #2 Использование аргументов в конструкторах
<?php
class Point {
protected int $x;
protected int $y;
public function __construct(int $x, int $y = 0) {
$this->x = $x;
$this->y = $y;
}
}
// Передаём оба параметра.
$p1 = new Point(4, 5);
// Передаём только обязательные параметры. Для $y используется значение по умолчанию 0.
$p2 = new Point(4);
// Вызываем с именованными параметрами (начиная с PHP 8.0):
$p3 = new Point(y: 5, x: 4);
?>Если у класса нет конструктора, или его конструктор не имеет обязательных параметров, скобки после имени класса можно не писать.
До PHP 8.0.0, классы в глобальном пространстве имён будут интерпретировать метод,
названный так же, как класс, как конструктор старого стиля. Этот синтаксис считается
устаревшим и будет вызывать ошибку уровня E_DEPRECATED, но
всё равно эти методы будут вызываться в качестве конструктора.
Если в классе присутствуют и __construct(),
и метод с именем класса, то в качестве конструктора будет вызван
__construct().
Для классов, находящихся в собственном пространстве имён и для всех классов, начиная с PHP 8.0.0, метод, названный по имени класса, будет игнорироваться.
В новом коде всегда используйте __construct().
Начиная с PHP 8.0.0, параметры конструктора можно использовать для задания соответствующих свойств объекта. Это довольно распространённая практика — присваивать свойствам объекта параметры, переданные в конструктор, не производя никаких дополнительных преобразований. Определение свойств класса в конструкторе позволяет значительно сократить количество шаблонного кода для такого случая. Пример выше можно будет переписать следующим образом:
Пример #3 Использование определения свойств в конструкторе
<?php
class Point {
public function __construct(protected int $x, protected int $y = 0) {
}
}Если декларация аргумента конструктора включает модификатор видимости, PHP интерпретирует его одновременно и как аргумент конструктора, и как свойство объекта и автоматически присвоит свойству значение, переданное в конструктор. При этом, если не предполагается какой-либо дополнительной логики, тело конструктора можно оставить пустым. Код конструктора выполнится после того, как все аргументы присвоятся всем соответствующим свойствам.
Не все передаваемые в конструктор аргументы должны быть свойствами объекта. В конструкторе можно задавать как обычные, так и являющиеся свойствами объекта аргументы в любом порядке. Аргументы-свойства никак не влияют на код, исполняемый в конструкторе.
Замечание:
Свойства объектов не могут быть типа callable в связи с неоднозначностью которую они представляют для движка PHP. Соответственно и свойства определяемые в конструкторе также не могут быть типа callable. Любые другие декларации типов допустимы.
Замечание:
Атрибуты, заданные для таких аргументов, будут применены как для них самих, так и для соответствующих свойств. Значения по умолчанию для продвигаемого аргумента конструктора будут реплицироваться только на аргумент, а не на свойство.
Начиная с PHP 8.1.0, объекты можно использовать в качестве значений параметров по умолчанию, статических переменных и глобальных констант, а также в аргументах атрибутов. Объекты также теперь можно передавать в define().
Замечание:
Использование динамического или не строкового имени класса или анонимного класса не допускается. Использование распаковки аргументов не допускается. Использование неподдерживаемых выражений в качестве аргументов не допускается.
Пример #4 Пример использования new в инициализации класса
<?php
// Всё допустимо:
static $x = new Foo;
const C = new Foo;
function test($param = new Foo) {}
#[AnAttribute(new Foo)]
class Test {
public function __construct(
public $prop = new Foo,
) {}
}
// Всё не допустимо (ошибка во времени компиляции):
function test(
$a = new (CLASS_NAME_CONSTANT)(), // динамическое имя класса
$b = new class {}, // анонимный класс
$c = new A(...[]), // распаковка аргументов
$d = new B($abc), // неподдерживаемое постоянное выражение
) {}
?>PHP поддерживает только один конструктор для класса. Однако в некоторых случаях есть необходимость создавать объект разными путями в зависимости от разных входных данных. Рекомендуемый способ - использовать статические методы как обёртки над конструктором.
Пример #5 Использование статических методов для создания объектов
<?php
class Product {
private ?int $id;
private ?string $name;
private function __construct(?int $id = null, ?string $name = null) {
$this->id = $id;
$this->name = $name;
}
public static function fromBasicData(int $id, string $name): static {
$new = new static($id, $name);
return $new;
}
public static function fromJson(string $json): static {
$data = json_decode($json);
return new static($data['id'], $data['name']);
}
public static function fromXml(string $xml): static {
// Пользовательская логика.
$data = convert_xml_to_array($xml);
$new = new static();
$new->id = $data['id'];
$new->name = $data['name'];
return $new;
}
}
$p1 = Product::fromBasicData(5, 'Widget');
$p2 = Product::fromJson($some_json_string);
$p3 = Product::fromXml($some_xml_string);Конструктор можно сделать скрытым или защищённым для предотвращения его прямого вызова. В таком случае объект класса можно будет создать только с помощью статических методов. Так как это методы того же класса, они имеют доступ ко всем его скрытым методам, даже если они относятся к разным экземплярам класса. Скрытый конструктор опционален и может присутствовать или отсутствовать по необходимости.
В примере выше три публичных статических метода демонстрируют различные способы создания экземпляра объекта.
fromBasicData() принимает явные параметры, создаёт экземпляр
класса через конструктор и возвращает объект.fromJson() принимает JSON строку, производит над ней некоторые
преобразования, извлекает данные необходимые для создания объекта и, так же как и
предыдущий метод, вызывает конструктор и возвращает созданный объект.fromXml() принимает XML строку, извлекает нужные данные и, так
как в конструкторе нет обязательных параметров, вызывает его без них. После этого, так
как ему доступны скрытые свойства, он присваивает им значения напрямую. После чего
возвращает готовый объект.
Во всех трёх случаях, ключевое слово static транслируется в имя класса,
в котором этот код вызывается. В нашем случае Product.
PHP предоставляет концепцию деструктора, аналогичную с той, которая применяется в других ОО-языках, таких как C++. Деструктор будет вызван при освобождении всех ссылок на определённый объект или при завершении скрипта (порядок выполнения деструкторов не гарантируется).
Пример #6 Пример использования деструктора
<?php
class MyDestructableClass
{
function __construct() {
print "Конструктор\n";
}
function __destruct() {
print "Уничтожается " . __CLASS__ . "\n";
}
}
$obj = new MyDestructableClass();Как и в случае с конструкторами, деструкторы, объявленные в родительском классе, не будут вызываться автоматически. Для вызова деструктора родительского класса, требуется вызвать parent::__destruct() в теле деструктора дочернего класса. Подобно конструкторам, дочерний класс может унаследовать деструктор из родительского класса, если он не определён в нем.
Деструктор будет вызываться даже в том случае, если скрипт был остановлен с помощью функции exit(). Вызов exit() в деструкторе предотвратит запуск всех последующих функций завершения.
Замечание:
Деструкторы, вызываемые при завершении скрипта, вызываются после отправки HTTP-заголовков. Рабочая директория во время фазы завершения скрипта может отличаться в некоторых SAPI (например, в Apache).
Замечание:
Попытка выбросить исключение из деструктора (вызываемого во время завершения скрипта) вызывает фатальную ошибку.
Область видимости свойства, метода или константы (начиная c PHP 7.1.0) может быть определена путём
использования следующих ключевых слов в объявлении: public,
protected или private. Доступ к свойствам
и методам класса, объявленным как public (общедоступный), разрешён отовсюду.
Модификатор protected (защищённый) разрешает доступ самому классу, наследующим его классам и родительским классам.
Модификатор private (закрытый) ограничивает область видимости так, что только класс,
где объявлен сам элемент, имеет к нему доступ.
Свойства класса могут быть определены как public, private или protected. Свойства, объявленные без явного ключевого слова области видимости, определяются как общедоступные (public).
Пример #1 Объявление свойства класса
<?php
/**
* Определение MyClass
*/
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj = new MyClass();
echo $obj->public; // Работает
echo $obj->protected; // Неисправимая ошибка
echo $obj->private; // Неисправимая ошибка
$obj->printHello(); // Выводит Public, Protected и Private
/**
* Определение MyClass2
*/
class MyClass2 extends MyClass
{
// Мы можем переопределить общедоступные и защищённые свойства, но не закрытые
public $public = 'Public2';
protected $protected = 'Protected2';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj2 = new MyClass2();
echo $obj2->public; // Работает
echo $obj2->private; // Неопределён
echo $obj2->protected; // Неисправимая ошибка
$obj2->printHello(); // Выводит Public2, Protected2, Undefined
?>Методы класса могут быть определены как public, private или protected. Методы, объявленные без указания области видимости, определяются как public.
Пример #2 Объявление метода
<?php
/**
* Определение MyClass
*/
class MyClass
{
// Объявление общедоступного конструктора
public function __construct() { }
// Объявление общедоступного метода
public function MyPublic() { }
// Объявление защищённого метода
protected function MyProtected() { }
// Объявление закрытого метода
private function MyPrivate() { }
// Это общедоступный метод
function Foo()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate();
}
}
$myclass = new MyClass;
$myclass->MyPublic(); // Работает
$myclass->MyProtected(); // Неисправимая ошибка
$myclass->MyPrivate(); // Неисправимая ошибка
$myclass->Foo(); // Работает общедоступный, защищённый и закрытый
/**
* Определение MyClass2
*/
class MyClass2 extends MyClass
{
// Это общедоступный метод
function Foo2()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate(); // Неисправимая ошибка
}
}
$myclass2 = new MyClass2;
$myclass2->MyPublic(); // Работает
$myclass2->Foo2(); // Работает общедоступный и защищённый, закрытый не работает
class Bar
{
public function test() {
$this->testPrivate();
$this->testPublic();
}
public function testPublic() {
echo "Bar::testPublic\n";
}
private function testPrivate() {
echo "Bar::testPrivate\n";
}
}
class Foo extends Bar
{
public function testPublic() {
echo "Foo::testPublic\n";
}
private function testPrivate() {
echo "Foo::testPrivate\n";
}
}
$myFoo = new Foo();
$myFoo->test(); // Bar::testPrivate
// Foo::testPublic
?>Начиная с PHP 7.1.0, константы класса могут быть определены как public, private или protected. Константы, объявленные без указания области видимости, определяются как public.
Пример #3 Объявление констант, начиная с PHP 7.1.0
<?php
/**
* Объявление класса MyClass
*/
class MyClass
{
// Объявление общедоступной константы
public const MY_PUBLIC = 'public';
// Объявление защищённой константы
protected const MY_PROTECTED = 'protected';
// Объявление закрытой константы
private const MY_PRIVATE = 'private';
public function foo()
{
echo self::MY_PUBLIC;
echo self::MY_PROTECTED;
echo self::MY_PRIVATE;
}
}
$myclass = new MyClass();
MyClass::MY_PUBLIC; // Работает
MyClass::MY_PROTECTED; // Неисправимая ошибка
MyClass::MY_PRIVATE; // Неисправимая ошибка
$myclass->foo(); // Выводятся константы public, protected и private
/**
* Объявление класса MyClass2
*/
class MyClass2 extends MyClass
{
// Публичный метод
function foo2()
{
echo self::MY_PUBLIC;
echo self::MY_PROTECTED;
echo self::MY_PRIVATE; // Неисправимая ошибка
}
}
$myclass2 = new MyClass2;
echo MyClass2::MY_PUBLIC; // Работает
$myclass2->foo2(); // Выводятся константы public и protected, но не private
?>Объекты, которые имеют общий тип (наследуются от одного класса), имеют доступ к элементам с модификаторами private и protected друг друга, даже если не являются одним и тем же экземпляром. Это объясняется тем, что реализация видимости элементов известна внутри этих объектов.
Пример #4 Доступ к элементам с модификатором private из объектов одного типа
<?php
class Test
{
private $foo;
public function __construct($foo)
{
$this->foo = $foo;
}
private function bar()
{
echo 'Доступ к закрытому методу.';
}
public function baz(Test $other)
{
// Мы можем изменить закрытое свойство:
$other->foo = 'привет';
var_dump($other->foo);
// Мы также можем вызвать закрытый метод:
$other->bar();
}
}
$test = new Test('test');
$test->baz(new Test('other'));
?>Результат выполнения данного примера:
string(6) "привет" Доступ к закрытому методу.
Наследование — это хорошо зарекомендовавший себя принцип программирования, и PHP использует этот принцип в своей объектной модели. Этот принцип повлияет на то, как многие классы и объекты связаны друг с другом.
Например, при расширении класса дочерний класс наследует все общедоступные и защищённые методы, свойства и константы родительского класса. До тех пор пока эти методы не будут переопределены, они будут сохранять свою исходную функциональность.
Это полезно для определения и абстрагирования функциональности и позволяет реализовать дополнительную функциональность в похожих объектах без необходимости реализовывать всю общую функциональность.
Закрытые методы родительского класса недоступны для дочернего класса. В результате
дочерние классы могут повторно реализовать закрытый метод без учёта обычных
правил наследования. Однако до PHP 8.0.0 к закрытым методам применялись ограничения
final и static. Начиная с PHP 8.0.0,
единственное ограничение закрытого метода, которое применяется - это конструкторы private final,
поскольку это обычный способ "отключить" конструктор при использовании вместо него статичных фабричных методов.
Видимость методов,
свойств и констант можно ослабить, например, защищённый метод
может быть помечен как общедоступный, но нельзя ограничить видимость,
например, нельзя пометить общедоступное свойство как закрытое.
Исключением являются конструкторы, видимость которых может быть ограничена,
например, общедоступный конструктор может быть помечен
как закрытый в дочернем классе.
Замечание:
Если не используется автозагрузка, классы должны быть объявлены до того, как они будут использоваться. Если класс расширяет другой, то родительский класс должен быть объявлен до наследующего класса. Это правило применяется к классам, которые наследуют другие классы или интерфейсы.
Замечание:
Не разрешается переопределять свойство чтения-записи с помощью readonly-свойства или наоборот.
<?php
class A {
public int $prop;
}
class B extends A {
// Нельзя: read-write -> readonly
public readonly int $prop;
}
?>
Пример #1 Пример наследования
<?php
class Foo
{
public function printItem($string)
{
echo 'Foo: ' . $string . PHP_EOL;
}
public function printPHP()
{
echo 'PHP просто супер.' . PHP_EOL;
}
}
class Bar extends Foo
{
public function printItem($string)
{
echo 'Bar: ' . $string . PHP_EOL;
}
}
$foo = new Foo();
$bar = new Bar();
$foo->printItem('baz'); // Выведет: 'Foo: baz'
$foo->printPHP(); // Выведет: 'PHP просто супер'
$bar->printItem('baz'); // Выведет: 'Bar: baz'
$bar->printPHP(); // Выведет: 'PHP просто супер'
?>До PHP 8.1.0 большинство внутренних классов или методов не объявляли свои типы возвращаемых значений и при их расширении допускался любой тип возвращаемого значения.
Начиная с PHP 8.1.0, большинство внутренних методов начали "предварительно" объявлять тип возвращаемого значения. В этом случае тип возвращаемого значения методов должен быть совместим с расширяемым родителем; в противном случае выдаётся уведомление об устаревании. Обратите внимание, что отсутствие явного объявления типа возвращаемого значения также считается несоответствием сигнатуры и, соответственно, приводит к уведомлению об устаревании.
Если тип возвращаемого значения не может быть объявлен для переопределяемого метода из-за проблем с совместимостью с различными версиями PHP, может быть добавлен атрибут ReturnTypeWillChange, чтобы заглушить уведомление об устаревании.
Пример #2 Переопределяющий метод не объявляет никакого типа возвращаемого значения
<?php
class MyDateTime extends DateTime
{
public function modify(string $modifier) { return false; }
}
// "Deprecated: Return type of MyDateTime::modify(string $modifier) should either be compatible with DateTime::modify(string $modifier): DateTime|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice", начиная с PHP 8.1.0
?>Пример #3 Переопределяющий метод объявляет неверный тип возвращаемого значения
<?php
class MyDateTime extends DateTime
{
public function modify(string $modifier): ?DateTime { return null; }
}
// "Deprecated: Return type of MyDateTime::modify(string $modifier): ?DateTime should either be compatible with DateTime::modify(string $modifier): DateTime|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice", начиная с PHP 8.1.0
?>Пример #4 Переопределяющий метод объявляет неверный тип возвращаемого значения без уведомления об устаревании
<?php
class MyDateTime extends DateTime
{
/**
* @return DateTime|false
*/
#[\ReturnTypeWillChange]
public function modify(string $modifier) { return false; }
}
// Уведомление об устаревании не выводится
?>Оператор разрешения области видимости (также называемый "Paamayim Nekudotayim") или просто "двойное двоеточие" - это лексема, позволяющая обращаться к статическим свойствам, константам и переопределённым свойствам или методам класса.
При обращении к этим элементам извне класса, необходимо использовать имя этого класса.
Можно обратиться к классу с помощью переменной.
Значение переменной не должно быть ключевым словом (например, self,
parent или static).
"Paamayim Nekudotayim" на первый взгляд может показаться странным словосочетанием для обозначения двойного двоеточия. Однако, во время создания Zend Engine версии 0.5 (который входил в PHP3), команда Zend выбрала именно это обозначение. Оно на самом деле означает "двойное двоеточие" - на иврите!
Пример #1 Использование :: вне объявления класса
<?php
class MyClass {
const CONST_VALUE = 'Значение константы';
}
$classname = 'MyClass';
echo $classname::CONST_VALUE;
echo MyClass::CONST_VALUE;
?>Для обращения к свойствам и методам внутри самого класса используются ключевые слова self, parent и static.
Пример #2 Использование :: внутри объявления класса
<?php
class OtherClass extends MyClass
{
public static $my_static = 'статическая переменная';
public static function doubleColon() {
echo parent::CONST_VALUE . "\n";
echo self::$my_static . "\n";
}
}
$classname = 'OtherClass';
$classname::doubleColon();
OtherClass::doubleColon();
?>Когда дочерний класс переопределяет методы, объявленные в родительском классе, PHP не будет осуществлять автоматический вызов методов, принадлежащих классу-родителю. Эта функциональность возлагается на метод, переопределяемый в дочернем классе. Данное правило распространяется на конструкторы и деструкторы, перегруженные и "магические" методы.
Пример #3 Обращение к методу в родительском классе
<?php
class MyClass
{
protected function myFunc() {
echo "MyClass::myFunc()\n";
}
}
class OtherClass extends MyClass
{
// Переопределить родительское определение
public function myFunc()
{
// Но всё ещё вызываем родительскую функцию
parent::myFunc();
echo "OtherClass::myFunc()\n";
}
}
$class = new OtherClass();
$class->myFunc();
?>Смотрите также некоторые примеры статических вызовов.
Эта страница описывает использование ключевого слова
static
для определения статических методов и свойств. static также
может использоваться для определения
статических переменных, определения статических анонимных функций
и позднего статического связывания.
Для получения информации о таком применении ключевого слова static обратитесь по вышеуказанным страницам.
Объявление свойств и методов класса статическими позволяет обращаться к ним без создания экземпляра класса. К ним также можно получить доступ статически в созданном экземпляре объекта класса.
Так как статические методы вызываются без создания экземпляра класса, то псевдопеременная $this недоступна внутри статических методов.
Вызов нестатических методов статически вызывает ошибку Error.
До PHP 8.0.0 вызов нестатических методов статически был объявлен устаревшим
и вызывал ошибку уровня E_DEPRECATED.
Пример #1 Пример статического метода
<?php
class Foo {
public static function aStaticMethod() {
// ...
}
}
Foo::aStaticMethod();
$classname = 'Foo';
$classname::aStaticMethod();
?>
Доступ к статическим свойствам осуществляется с помощью оператора разрешения области видимости
(::), и к ним нельзя получить доступ через оператор объекта (->).
На класс можно ссылаться с помощью переменной.
Значение переменной в таком случае не может быть ключевым
словом (например, self, parent и
static).
Пример #2 Пример статического свойства
<?php
class Foo
{
public static $my_static = 'foo';
public function staticValue() {
return self::$my_static;
}
}
class Bar extends Foo
{
public function fooStatic() {
return parent::$my_static;
}
}
print Foo::$my_static . "\n";
$foo = new Foo();
print $foo->staticValue() . "\n";
print $foo->my_static . "\n"; // Не определено свойство my_static
print $foo::$my_static . "\n";
$classname = 'Foo';
print $classname::$my_static . "\n";
print Bar::$my_static . "\n";
$bar = new Bar();
print $bar->fooStatic() . "\n";
?>Результат выполнения данного примера в PHP 8 аналогичен:
foo foo Notice: Accessing static property Foo::$my_static as non static in /in/V0Rvv on line 23 Warning: Undefined property: Foo::$my_static in /in/V0Rvv on line 23 foo foo foo foo
PHP поддерживает определение абстрактных классов и методов. На основе абстрактного класса нельзя создавать объекты, и любой класс, содержащий хотя бы один абстрактный метод, должен быть определён как абстрактный. Методы, объявленные абстрактными, несут, по существу, лишь описательный смысл и не могут включать реализацию.
При наследовании от абстрактного класса, все методы, помеченные абстрактными в родительском классе, должны быть определены в дочернем классе и следовать обычным правилам наследования и совместимости сигнатуры.
Пример #1 Пример абстрактного класса
<?php
abstract class AbstractClass
{
// Данные методы должны быть определены в дочернем классе
abstract protected function getValue();
abstract protected function prefixValue($prefix);
// Общий метод
public function printOut() {
print $this->getValue() . "\n";
}
}
class ConcreteClass1 extends AbstractClass
{
protected function getValue() {
return "ConcreteClass1";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass1";
}
}
class ConcreteClass2 extends AbstractClass
{
public function getValue() {
return "ConcreteClass2";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass2";
}
}
$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."\n";
$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') ."\n";
?>Результат выполнения данного примера:
ConcreteClass1 FOO_ConcreteClass1 ConcreteClass2 FOO_ConcreteClass2
Пример #2 Пример абстрактного класса
<?php
abstract class AbstractClass
{
// Наш абстрактный метод требует только определить необходимые аргументы
abstract protected function prefixName($name);
}
class ConcreteClass extends AbstractClass
{
// Наш дочерний класс может определить необязательные аргументы, не указанные в объявлении родительского метода
public function prefixName($name, $separator = ".") {
if ($name == "Pacman") {
$prefix = "Mr";
} elseif ($name == "Pacwoman") {
$prefix = "Mrs";
} else {
$prefix = "";
}
return "{$prefix}{$separator} {$name}";
}
}
$class = new ConcreteClass;
echo $class->prefixName("Pacman"), "\n";
echo $class->prefixName("Pacwoman"), "\n";
?>Результат выполнения данного примера:
Mr. Pacman Mrs. Pacwoman
Интерфейсы объектов позволяют создавать код, который указывает, какие методы должен реализовать класс, без необходимости определять, как именно они должны быть реализованы. Интерфейсы разделяют пространство имён с классами и трейтами, поэтому они не могут называться одинаково.
Интерфейсы объявляются так же, как и обычные классы, но с использованием
ключевого слова interface вместо class.
Тела методов интерфейсов должны быть пустыми.
Все методы, определённые в интерфейсах, должны быть общедоступными, что следует из самой природы интерфейса.
На практике интерфейсы используются в двух взаимодополняющих случаях:
Iterable, Cacheable, Renderable
и так далее, чтобы описать их поведение.
Интерфейсы могут определять магические методы, требуя от реализующих классов реализации этих методов.
Замечание:
Хотя они поддерживаются, использование конструкторов в интерфейсах настоятельно не рекомендуется. Это значительно снижает гибкость объекта, реализующего интерфейс. Кроме того, к конструкторам не применяются правила наследования, что может привести к противоречивому и неожиданному поведению.
implements
Для реализации интерфейса используется оператор implements.
Класс должен реализовать все методы, описанные в интерфейсе, иначе
произойдёт фатальная ошибка. При желании классы могут реализовывать
более одного интерфейса, разделяя каждый интерфейс запятой.
Класс, реализующий интерфейс, может использовать для своих параметров имя, отличное от имени интерфейса. Однако, начиная с PHP 8.0, в языке поддерживаются именованные аргументы, и вызывающий код может полагаться на имя параметра в интерфейсе. По этой причине настоятельно рекомендуется, чтобы разработчики использовали те же имена параметров, что и реализуемый интерфейс.
Замечание:
Интерфейсы могут быть унаследованы друг от друга, так же, как и классы, с помощью оператора extends.
Замечание:
Класс, реализующий интерфейс, должен объявить все методы в интерфейсе с совместимой сигнатурой. Класс может реализовывать несколько интерфейсов, которые объявляют метод с одинаковым именем. В этом случае реализация должна следовать правилам совместимости сигнатуры для всех интерфейсов. Таким образом, можно применять ковариантность и контравариантность.
Интерфейсы могут содержать константы. Константы интерфейсов работают точно так же, как и константы классов. До PHP 8.1.0 они не могли быть переопределены классом или интерфейсом, который их наследует.
Пример #1 Пример интерфейса
<?php
// Объявим интерфейс 'Template'
interface Template
{
public function setVariable($name, $var);
public function getHtml($template);
}
// Реализация интерфейса
// Это будет работать
class WorkingTemplate implements Template
{
private $vars = [];
public function setVariable($name, $var)
{
$this->vars[$name] = $var;
}
public function getHtml($template)
{
foreach($this->vars as $name => $value) {
$template = str_replace('{' . $name . '}', $value, $template);
}
return $template;
}
}
// Это не будет работать
// Fatal error: Class BadTemplate contains 1 abstract methods
// and must therefore be declared abstract (Template::getHtml)
// (Фатальная ошибка: Класс BadTemplate содержит 1 абстрактный метод
// и поэтому должен быть объявлен абстрактным (Template::getHtml))
class BadTemplate implements Template
{
private $vars = [];
public function setVariable($name, $var)
{
$this->vars[$name] = $var;
}
}
?>Пример #2 Наследование интерфейсов
<?php
interface A
{
public function foo();
}
interface B extends A
{
public function baz(Baz $baz);
}
// Это сработает
class C implements B
{
public function foo()
{
}
public function baz(Baz $baz)
{
}
}
// Это не сработает и выдаст фатальную ошибку
class D implements B
{
public function foo()
{
}
public function baz(Foo $foo)
{
}
}
?>Пример #3 Совместимость с несколькими интерфейсами
<?php
class Foo {}
class Bar extends Foo {}
interface A {
public function myfunc(Foo $arg): Foo;
}
interface B {
public function myfunc(Bar $arg): Bar;
}
class MyClass implements A, B
{
public function myfunc(Foo $arg): Bar
{
return new Bar();
}
}
?>Пример #4 Множественное наследование интерфейсов
<?php
interface A
{
public function foo();
}
interface B
{
public function bar();
}
interface C extends A, B
{
public function baz();
}
class D implements C
{
public function foo()
{
}
public function bar()
{
}
public function baz()
{
}
}
?>Пример #5 Интерфейсы с константами
<?php
interface A
{
const B = 'Константа интерфейса';
}
// Выведет: Константа интерфейса
echo A::B;
class B implements A
{
const B = 'Константа класса';
}
// Выведет: Константа класса
// До PHP 8.1.0 этот код не будет работать,
// потому что было нельзя переопределять константы.
echo B::B;
?>Пример #6 Интерфейсы с абстрактными классами
<?php
interface A
{
public function foo(string $s): string;
public function bar(int $i): int;
}
// Абстрактный класс может реализовывать только часть интерфейса.
// Классы, расширяющие абстрактный класс, должны реализовать все остальные.
abstract class B implements A
{
public function foo(string $s): string
{
return $s . PHP_EOL;
}
}
class C extends B
{
public function bar(int $i): int
{
return $i * 2;
}
}
?>Пример #7 Одновременное расширение и внедрение
<?php
class One
{
/* ... */
}
interface Usable
{
/* ... */
}
interface Updatable
{
/* ... */
}
// Порядок ключевых слов здесь важен. "extends" должно быть первым.
class Two extends One implements Usable, Updatable
{
/* ... */
}
?>Интерфейс, совместно с объявлениями типов, предоставляет отличный способ проверки того, что определённый объект содержит определённый набор методов. Смотрите также оператор instanceof и объявление типов.
PHP реализует метод для повторного использования кода под названием трейт (trait).
Трейт - это механизм обеспечения повторного использования кода в языках с поддержкой только одиночного наследования, таких как PHP. Трейт предназначен для уменьшения некоторых ограничений одиночного наследования, позволяя разработчику повторно использовать наборы методов свободно, в нескольких независимых классах и реализованных с использованием разных архитектур построения классов. Семантика комбинации трейтов и классов определена таким образом, чтобы снизить уровень сложности, а также избежать типичных проблем, связанных с множественным наследованием и смешиванием (mixins).
Трейт очень похож на класс, но предназначен для группирования функционала хорошо структурированным и последовательным образом. Невозможно создать самостоятельный экземпляр трейта. Это дополнение к обычному наследованию и позволяет сделать горизонтальную композицию поведения, то есть применение членов класса без необходимости наследования.
Пример #1 Пример использования трейта
<?php
trait ezcReflectionReturnInfo {
function getReturnType() { /*1*/ }
function getReturnDescription() { /*2*/ }
}
class ezcReflectionMethod extends ReflectionMethod {
use ezcReflectionReturnInfo;
/* ... */
}
class ezcReflectionFunction extends ReflectionFunction {
use ezcReflectionReturnInfo;
/* ... */
}
?>Наследуемый член из базового класса переопределяется членом, находящимся в трейте. Порядок приоритета следующий: члены из текущего класса переопределяют методы в трейте, которые в свою очередь переопределяют унаследованные методы.
Пример #2 Пример приоритета старшинства
Наследуемый метод от базового класса переопределяется методом, добавленным в MyHelloWorld из трейта SayWorld. Поведение такое же как и для методов, определённых в классе MyHelloWorld. Порядок приоритета такой: методы из текущего класса переопределяют методы трейта, которые в свою очередь переопределяют методы из базового класса.
<?php
class Base {
public function sayHello() {
echo 'Hello ';
}
}
trait SayWorld {
public function sayHello() {
parent::sayHello();
echo 'World!';
}
}
class MyHelloWorld extends Base {
use SayWorld;
}
$o = new MyHelloWorld();
$o->sayHello();
?>Результат выполнения данного примера:
Hello World!
Пример #3 Пример альтернативного порядка приоритета
<?php
trait HelloWorld {
public function sayHello() {
echo 'Hello World!';
}
}
class TheWorldIsNotEnough {
use HelloWorld;
public function sayHello() {
echo 'Hello Universe!';
}
}
$o = new TheWorldIsNotEnough();
$o->sayHello();
?>Результат выполнения данного примера:
Hello Universe!
В класс можно добавить несколько трейтов, перечислив их в директиве
use через запятую.
Пример #4 Пример использования нескольких трейтов
<?php
trait Hello {
public function sayHello() {
echo 'Hello ';
}
}
trait World {
public function sayWorld() {
echo 'World';
}
}
class MyHelloWorld {
use Hello, World;
public function sayExclamationMark() {
echo '!';
}
}
$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();
$o->sayExclamationMark();
?>Результат выполнения данного примера:
Hello World!
Если два трейта добавляют метод с одним и тем же именем, это приводит к фатальной ошибке в случае, если конфликт явно не разрешён.
Для разрешения конфликтов именования между трейтами, используемыми в одном и том же
классе, необходимо использовать оператор insteadof для того, чтобы точно
выбрать один из конфликтующих методов.
Так как предыдущий оператор позволяет только исключать методы, оператор
as может быть использован для включения одного из конфликтующих
методов под другим именем. Обратите внимание, что оператор as не
переименовывает метод и не влияет на какой-либо другой метод.
Пример #5 Пример разрешения конфликтов
В этом примере Talker использует трейты A и B. Так как в A и B есть конфликтующие методы, он использует вариант smallTalk из трейта B, а вариант bigTalk - из трейта A.
Класс Aliased_Talker применяет оператор as,
чтобы получить возможность использовать реализацию bigTalk из B
под дополнительным псевдонимом talk.
<?php
trait A {
public function smallTalk() {
echo 'a';
}
public function bigTalk() {
echo 'A';
}
}
trait B {
public function smallTalk() {
echo 'b';
}
public function bigTalk() {
echo 'B';
}
}
class Talker {
use A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
}
}
class Aliased_Talker {
use A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
B::bigTalk as talk;
}
}
?>
Используя синтаксис оператора as, можно также изменить
видимость метода в использующем трейт классе.
Пример #6 Пример изменения видимости метода
<?php
trait HelloWorld {
public function sayHello() {
echo 'Hello World!';
}
}
// Изменение видимости метода sayHello
class MyClass1 {
use HelloWorld { sayHello as protected; }
}
// Создание псевдонима метода с изменённой видимостью
// видимость sayHello не изменилась
class MyClass2 {
use HelloWorld { sayHello as private myPrivateHello; }
}
?>Трейты могут использоваться как в классах, так и в других трейтах. Используя один или более трейтов в определении другого трейта, он может частично или полностью состоять из членов, определённых в этих трейтах.
Пример #7 Пример трейтов, составленных из трейтов
<?php
trait Hello {
public function sayHello() {
echo 'Hello ';
}
}
trait World {
public function sayWorld() {
echo 'World!';
}
}
trait HelloWorld {
use Hello, World;
}
class MyHelloWorld {
use HelloWorld;
}
$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();
?>Результат выполнения данного примера:
Hello World!
Трейты поддерживают использование абстрактных методов для того, чтобы установить требования к использующему классу. Поддерживаются общедоступные, защищённые и закрытые методы. До PHP 8.0.0 поддерживались только общедоступные и защищённые абстрактные методы.
Конкретный класс исполняет эти требования путём определения конкретного метода с тем же именем; при этом сигнатура метода может отличаться.
Пример #8 Требования трейта при помощи абстрактных методов
<?php
trait Hello {
public function sayHelloWorld() {
echo 'Hello'.$this->getWorld();
}
abstract public function getWorld();
}
class MyHelloWorld {
private $world;
use Hello;
public function getWorld() {
return $this->world;
}
public function setWorld($val) {
$this->world = $val;
}
}
?>В трейтах можно определять статические переменные, статические методы и статические свойства.
Замечание:
Начиная с PHP 8.1.0, вызов статического метода или доступ к статическому свойству непосредственно в трейте устарел. К статическим методам и свойствам следует обращаться только в классе, использующем трейт.
Пример #9 Статические переменные
<?php
trait Counter {
public function inc() {
static $c = 0;
$c = $c + 1;
echo "$c\n";
}
}
class C1 {
use Counter;
}
class C2 {
use Counter;
}
$o = new C1(); $o->inc(); // echo 1
$p = new C2(); $p->inc(); // echo 1
?>Пример #10 Статические методы
<?php
trait StaticExample {
public static function doSomething() {
return 'Что-либо делаем';
}
}
class Example {
use StaticExample;
}
Example::doSomething();
?>Пример #11 Статические свойства
<?php
trait StaticExample {
public static $static = 'foo';
}
class Example {
use StaticExample;
}
echo Example::$static;
?>Трейты могут также определять свойства.
Пример #12 Определение свойств
<?php
trait PropertiesTrait {
public $x = 1;
}
class PropertiesExample {
use PropertiesTrait;
}
$example = new PropertiesExample;
$example->x;
?>Если трейт определяет свойство, то класс не может определить свойство с таким же именем, кроме случаев полного совпадения (та же область видимости и тип, модификатор readonly и начальное значение), иначе будет выброшена фатальная ошибка.
Пример #13 Разрешение конфликтов
<?php
trait PropertiesTrait {
public $same = true;
public $different1 = false;
public bool $different2;
public bool $different3;
}
class PropertiesExample {
use PropertiesTrait;
public $same = true;
public $different1 = true; // Фатальная ошибка
public string $different2; // Фатальная ошибка
readonly protected bool $different3; // Фатальная ошибка
}
?>Начиная с версии PHP 8.2.0, трейты могут также определять константы.
Пример #14 Определение констант
<?php
trait ConstantsTrait {
public const FLAG_MUTABLE = 1;
final public const FLAG_IMMUTABLE = 5;
}
class ConstantsExample {
use ConstantsTrait;
}
$example = new ConstantsExample;
echo $example::FLAG_MUTABLE; // 1
?>Если трейт определяет константу, то класс не может определить константу с таким же именем, если только они не совместимы (одинаковая область видимости, начальное значение и модификатор final), иначе выбрасывается фатальная ошибка.
Пример #15 Разрешение конфликтов
<?php
trait ConstantsTrait {
public const FLAG_MUTABLE = 1;
final public const FLAG_IMMUTABLE = 5;
}
class ConstantsExample {
use ConstantsTrait;
public const FLAG_IMMUTABLE = 5; // Фатальная ошибка
}
?>Анонимные классы полезны, когда нужно создать простые, одноразовые объекты.
<?php
// Использование явного класса
class Logger
{
public function log($msg)
{
echo $msg;
}
}
$util->setLogger(new Logger());
// Использование анонимного класса
$util->setLogger(new class {
public function log($msg)
{
echo $msg;
}
});Они могут передавать аргументы в конструкторы, расширять другие классы, реализовывать интерфейсы и использовать трейты как обычный класс:
<?php
class SomeClass {}
interface SomeInterface {}
trait SomeTrait {}
var_dump(new class(10) extends SomeClass implements SomeInterface {
private $num;
public function __construct($num)
{
$this->num = $num;
}
use SomeTrait;
});Результат выполнения данного примера:
object(class@anonymous)#1 (1) {
["Command line code0x104c5b612":"class@anonymous":private]=>
int(10)
}
Вложение анонимного класса в другой класс не даёт ему доступ к закрытым или защищённым методам и свойствам этого внешнего класса. Для того, чтобы использовать защищённые свойства и методы внешнего класса, анонимный класс может расширить внешний класс. Чтобы использовать закрытые свойства внешнего класса в анонимном классе, их нужно передать в конструктор:
<?php
class Outer
{
private $prop = 1;
protected $prop2 = 2;
protected function func1()
{
return 3;
}
public function func2()
{
return new class($this->prop) extends Outer {
private $prop3;
public function __construct($prop)
{
$this->prop3 = $prop;
}
public function func3()
{
return $this->prop2 + $this->prop3 + $this->func1();
}
};
}
}
echo (new Outer)->func2()->func3();Результат выполнения данного примера:
6
Все объекты, созданные одним и тем же объявлением анонимного класса, являются экземплярами этого самого класса.
<?php
function anonymous_class()
{
return new class {};
}
if (get_class(anonymous_class()) === get_class(anonymous_class())) {
echo 'Тот же класс';
} else {
echo 'Другой класс';
}Результат выполнения данного примера:
Тот же класс
Замечание:
Обратите внимание, что анонимным классам присваиваются имена движком PHP, как показано в примере ниже. Это имя следует рассматривать как особенность реализации, на которую не следует полагаться.
<?php
echo get_class(new class {});Результатом выполнения данного примера будет что-то подобное:
class@anonymous/in/oNi1A0x7f8636ad2021
Перегрузка в PHP означает возможность динамически создавать
свойства и методы. Эти динамические сущности обрабатываются с
помощью магических методов, которые можно создать в классе для
различных видов действий.
Методы перегрузки вызываются при взаимодействии со свойствами
или методами, которые не были объявлены или не видны в текущей области
видимости. Далее в этом разделе будут использоваться термины
недоступные свойства
или недоступные методы
для обозначения этой комбинации объявления и области видимости.
Все методы перегрузки должны быть объявлены как public.
Замечание:
Ни один из аргументов этих магических методов не может быть передан по ссылке.
Замечание:
Интерпретация
перегрузкив PHP отличается от большинства объектно-ориентированных языков. Традиционно перегрузка означает возможность иметь несколько одноимённых методов с разным количеством и типами аргументов.
$name): bool$name): voidМетод __set() будет выполнен при записи данных в недоступные (защищённые или приватные) или несуществующие свойства.
Метод __get() будет выполнен при чтении данных из недоступных (защищённых или приватных) или несуществующих свойств.
Метод __isset() будет выполнен при использовании isset() или empty() на недоступных (защищённых или приватных) или несуществующих свойствах.
Метод __unset() будет выполнен при вызове unset() на недоступном (защищённом или приватном) или несуществующем свойстве.
Аргумент $name представляет собой имя вызываемого свойства. Метод __set() содержит аргумент $value, представляющий собой значение, которое будет записано в свойство с именем $name.
Перегрузка свойств работает только в контексте объекта.
Данные магические методы не будут вызваны в статическом контексте.
Поэтому эти методы не должны объявляться
статическими.
При объявлении любого магического метода как
static будет выдано предупреждение.
Замечание:
Возвращаемое значение __set() будет проигнорировано из-за способа обработки в PHP оператора присваивания. Аналогично, __get() никогда не вызывается при объединении присваиваний, например, подобным образом:
$a = $obj->b = 8;
Замечание:
PHP не будет вызывать перегруженный метод изнутри того же перегруженного метода. Это означает, что, например, написание
return $this->fooвнутри __get() вернётnullи вызовет ошибку уровняE_WARNING, если не определено свойствоfoo, вместо того, чтобы вызвать метод __get() во второй раз. Однако методы перегрузки могут неявно вызывать другие методы перегрузки (например, метод __set() вызывает метод __get()).
Пример #1 Перегрузка свойств с помощью методов __get(), __set(), __isset() и __unset()
<?php
class PropertyTest
{
/** Место хранения перегружаемых данных. */
private $data = array();
/** Перегрузка не применяется к объявленным свойствам. */
public $declared = 1;
/** Здесь перегрузка будет использована только при доступе вне класса. */
private $hidden = 2;
public function __set($name, $value)
{
echo "Установка '$name' в '$value'\n";
$this->data[$name] = $value;
}
public function __get($name)
{
echo "Получение '$name'\n";
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
$trace = debug_backtrace();
trigger_error(
'Неопределённое свойство в __get(): ' . $name .
' в файле ' . $trace[0]['file'] .
' на строке ' . $trace[0]['line'],
E_USER_NOTICE);
return null;
}
public function __isset($name)
{
echo "Установлено ли '$name'?\n";
return isset($this->data[$name]);
}
public function __unset($name)
{
echo "Уничтожение '$name'\n";
unset($this->data[$name]);
}
/** Не магический метод, просто для примера. */
public function getHidden()
{
return $this->hidden;
}
}
echo "<pre>\n";
$obj = new PropertyTest;
$obj->a = 1;
echo $obj->a . "\n\n";
var_dump(isset($obj->a));
unset($obj->a);
var_dump(isset($obj->a));
echo "\n";
echo $obj->declared . "\n\n";
echo "Давайте поэкспериментируем с закрытым свойством 'hidden':\n";
echo "Закрытые свойства видны внутри класса, поэтому __get() не используется...\n";
echo $obj->getHidden() . "\n";
echo "Закрытые свойства не видны вне класса, поэтому __get() используется...\n";
echo $obj->hidden . "\n";
?>Результат выполнения данного примера:
Установка 'a' в '1' Получение 'a' 1 Установлено ли 'a'? bool(true) Уничтожение 'a' Установлено ли 'a'? bool(false) 1 Давайте поэкспериментируем с закрытым свойством 'hidden': Закрытые свойства видны внутри класса, поэтому __get() не используется... 2 Закрытые свойства не видны вне класса, поэтому __get() используется... Получение 'hidden' Notice: Неопределённое свойство в __get(): hidden в <file> on line 70 in <file> on line 29
__call() запускается при вызове недоступных методов в контексте объект.
__callStatic() запускается при вызове недоступных методов в статическом контексте.
Аргумент $name представляет собой имя вызываемого метода. Аргумент $arguments представляет собой нумерованный массив, содержащий параметры, переданные в вызываемый метод $name.
Пример #2 Перегрузка методов с помощью методов __call() и __callStatic()
<?php
class MethodTest {
public function __call($name, $arguments) {
// Замечание: значение $name регистрозависимо.
echo "Вызов метода '$name' "
. implode(', ', $arguments). "\n";
}
public static function __callStatic($name, $arguments) {
// Замечание: значение $name регистрозависимо.
echo "Вызов статического метода '$name' "
. implode(', ', $arguments). "\n";
}
}
$obj = new MethodTest;
$obj->runTest('в контексте объекта');
MethodTest::runTest('в статическом контексте');
?>Результат выполнения данного примера:
Вызов метода 'runTest' в контексте объекта Вызов статического метода 'runTest' в статическом контексте
PHP предоставляет такой способ объявления объектов, который даёт возможность пройти по списку элементов данного объекта, например, с помощью оператора foreach. По умолчанию, в этом обходе (итерации) будут участвовать все видимые свойства объекта.
Пример #1 Итерация простого объекта
<?php
class MyClass
{
public $var1 = 'значение 1';
public $var2 = 'значение 2';
public $var3 = 'значение 3';
protected $protected = 'защищённая переменная';
private $private = 'закрытая переменная';
function iterateVisible() {
echo "MyClass::iterateVisible:\n";
foreach ($this as $key => $value) {
print "$key => $value\n";
}
}
}
$class = new MyClass();
foreach($class as $key => $value) {
print "$key => $value\n";
}
echo "\n";
$class->iterateVisible();
?>Результат выполнения данного примера:
var1 => значение 1 var2 => значение 2 var3 => значение 3 MyClass::iterateVisible: var1 => значение 1 var2 => значение 2 var3 => значение 3 protected => защищённая переменная private => закрытая переменная
Как показывает результат, foreach проитерировал все доступные и принадлежащие объекту видимые свойства.
Магические методы - это специальные методы, которые переопределяют действие PHP по умолчанию, когда над объектом выполняются определённые действия.
Все имена методов, начинающиеся с __, зарезервированы PHP.
Не рекомендуется использовать имена методов с __ в PHP, если вы не хотите использовать соответствующую
магическую функциональность.
Следующие названия методов считаются магическими: __construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __serialize(), __unserialize(), __toString(), __invoke(), __set_state(), __clone() и __debugInfo()
Все магические методы, за исключением
__construct(),
__destruct() и
__clone(),
ДОЛЖНЫ быть объявлены как public,
в противном случае будет вызвана ошибка уровня E_WARNING.
До PHP 8.0.0 для магических методов
__sleep(),
__wakeup(),
__serialize(),
__unserialize() и
__set_state()
не выполнялась проверка.
Если объявления типа используются в определении магического метода, они должны быть идентичны сигнатуре, описанной в этом документе. В противном случае выдаётся фатальная ошибка. До PHP 8.0.0 диагностические сообщения не отправлялись. Однако __construct() и __destruct() не должны объявлять возвращаемый тип; в противном случае выдаётся фатальная ошибка.
Функция serialize() проверяет, присутствует ли в
классе метод с магическим именем __sleep().
Если это так, то этот метод выполняется до любой операции сериализации. Он может
очистить объект и должен возвращать массив с именами
всех переменных этого объекта, которые должны быть сериализованы.
Если метод ничего не возвращает, то сериализуется null и
выдаётся предупреждение E_NOTICE.
Замечание:
Недопустимо возвращать в __sleep() имена закрытых свойств в родительском классе. Это приведёт к ошибке уровня
E_NOTICE. Вместо этого вы можете использовать __serialize().
Предполагаемое использование __sleep() состоит в завершении работы над данными, ждущими обработки или других подобных задач очистки. Кроме того, этот метод может быть полезен, когда есть очень большие объекты, которые нет необходимости полностью сохранять.
С другой стороны, функция unserialize() проверяет наличие метода с магическим именем __wakeup(). Если она имеется, эта функция может восстанавливать любые ресурсы, которые может иметь объект.
Предполагаемое использование __wakeup() заключается в восстановлении любых соединений с базой данных, которые могли быть потеряны во время операции сериализации и выполнения других операций повторной инициализации.
Пример #1 Сериализация и десериализация
<?php
class Connection
{
protected $link;
private $dsn, $username, $password;
public function __construct($dsn, $username, $password)
{
$this->dsn = $dsn;
$this->username = $username;
$this->password = $password;
$this->connect();
}
private function connect()
{
$this->link = new PDO($this->dsn, $this->username, $this->password);
}
public function __sleep()
{
return array('dsn', 'username', 'password');
}
public function __wakeup()
{
$this->connect();
}
}?>$data): voidserialize() проверяет, есть ли в классе функция с магическим именем __serialize(). Если да, функция выполняется перед любой сериализацией. Она должна создать и вернуть ассоциативный массив пар ключ/значение, которые представляют сериализованную форму объекта. Если массив не возвращён, будет выдано TypeError.
Замечание:
Если и __serialize() и __sleep() определены в одном и том же объекте, будет вызван только метод __serialize(). __sleep() будет игнорироваться. Если объект реализует интерфейс Serializable, метод
serialize()интерфейса будет игнорироваться, а вместо него будет использован __serialize().
Предполагаемое использование __serialize() заключается в определении удобного для сериализации произвольного представления объекта. Элементы массива могут соответствовать свойствам объекта, но это не обязательно.
И наоборот, unserialize() проверяет наличие магической функции __unserialize(). Если функция присутствует, ей будет передан восстановленный массив, который был возвращён из __serialize(). Затем он может восстановить свойства объекта из этого массива соответствующим образом.
Замечание:
Если и __unserialize() и __wakeup() определены в одном и том же объекте, будет вызван только метод __unserialize(). __wakeup() будет игнорироваться.
Замечание:
Функция доступна с PHP 7.4.0.
Пример #2 Сериализация и десериализация
<?php
class Connection
{
protected $link;
private $dsn, $username, $password;
public function __construct($dsn, $username, $password)
{
$this->dsn = $dsn;
$this->username = $username;
$this->password = $password;
$this->connect();
}
private function connect()
{
$this->link = new PDO($this->dsn, $this->username, $this->password);
}
public function __serialize(): array
{
return [
'dsn' => $this->dsn,
'user' => $this->username,
'pass' => $this->password,
];
}
public function __unserialize(array $data): void
{
$this->dsn = $data['dsn'];
$this->username = $data['user'];
$this->password = $data['pass'];
$this->connect();
}
}?>
Метод __toString() позволяет классу решать,
как он должен реагировать при преобразовании в
строку. Например, что вывести при выполнении echo $obj;.
Начиная с PHP 8.0.0, возвращаемое значение следует стандартной семантике типа PHP, что означает, что оно будет преобразовано в строку (string), если возможно, и если strict typing отключён.
Начиная с PHP 8.0.0, любой класс, содержащий метод __toString(), также будет неявно реализовывать интерфейс Stringable и, таким образом, будет проходить проверку типа для этого интерфейса В любом случае рекомендуется явно реализовать интерфейс.
В PHP 7.4 возвращаемое значение ДОЛЖНО быть строкой (string), иначе выдаётся Error.
До PHP 7.4.0 возвращаемое значение должно быть
строкой (string), в противном случае выдаётся фатальная ошибка E_RECOVERABLE_ERROR.
is emitted.
Нельзя выбросить исключение из метода __toString() до PHP 7.4.0. Это приведёт к фатальной ошибке.
Пример #3 Простой пример
<?php
// Объявление простого класса
class TestClass
{
public $foo;
public function __construct($foo)
{
$this->foo = $foo;
}
public function __toString()
{
return $this->foo;
}
}
$class = new TestClass('Привет');
echo $class;
?>Результат выполнения данного примера:
Привет
Метод __invoke() вызывается, когда скрипт пытается выполнить объект как функцию.
Пример #4 Использование __invoke()
<?php
class CallableClass
{
public function __invoke($x)
{
var_dump($x);
}
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
?>Результат выполнения данного примера:
int(5) bool(true)
Пример #5 Пример использования __invoke()
<?php
class Sort
{
private $key;
public function __construct(string $key)
{
$this->key = $key;
}
public function __invoke(array $a, array $b): int
{
return $a[$this->key] <=> $b[$this->key];
}
}
$customers = [
['id' => 1, 'first_name' => 'John', 'last_name' => 'Do'],
['id' => 3, 'first_name' => 'Alice', 'last_name' => 'Gustav'],
['id' => 2, 'first_name' => 'Bob', 'last_name' => 'Filipe']
];
// сортировка клиентов по имени
usort($customers, new Sort('first_name'));
print_r($customers);
// сортировка клиентов по фамилии
usort($customers, new Sort('last_name'));
print_r($customers);
?>Результат выполнения данного примера:
Array
(
[0] => Array
(
[id] => 3
[first_name] => Alice
[last_name] => Gustav
)
[1] => Array
(
[id] => 2
[first_name] => Bob
[last_name] => Filipe
)
[2] => Array
(
[id] => 1
[first_name] => John
[last_name] => Do
)
)
Array
(
[0] => Array
(
[id] => 1
[first_name] => John
[last_name] => Do
)
[1] => Array
(
[id] => 2
[first_name] => Bob
[last_name] => Filipe
)
[2] => Array
(
[id] => 3
[first_name] => Alice
[last_name] => Gustav
)
)
$properties): objectЭтот статический метод вызывается для тех классов, которые экспортируются функцией var_export().
Единственным параметром этого метода является массив, содержащий экспортируемые
свойства в виде ['property' => value, ...].
Пример #6 Использование __set_state()
<?php
class A
{
public $var1;
public $var2;
public static function __set_state($an_array)
{
$obj = new A;
$obj->var1 = $an_array['var1'];
$obj->var2 = $an_array['var2'];
return $obj;
}
}
$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';
$b = var_export($a, true);
var_dump($b);
eval('$c = ' . $b . ';');
var_dump($c);
?>Результат выполнения данного примера:
string(60) "A::__set_state(array(
'var1' => 5,
'var2' => 'foo',
))"
object(A)#2 (2) {
["var1"]=>
int(5)
["var2"]=>
string(3) "foo"
}
Замечание: При экспорте объекта var_export() не проверяет, реализует ли класс объекта метод __set_state(), поэтому повторный импорт объектов приведёт к исключению Error, если метод __set_state() не реализован. В частности, это относится к некоторым внутренним классам. Необходимость проверки, реализует ли импортируемый класс метод __set_state(), полностью лежит на разработчике.
Этот метод вызывается функцией var_dump(), когда необходимо вывести список свойств объекта. Если этот метод не определён, тогда будут выведены все свойства объекта c модификаторами public, protected и private.
Пример #7 Использование __debugInfo()
<?php
class C {
private $prop;
public function __construct($val) {
$this->prop = $val;
}
public function __debugInfo() {
return [
'propSquared' => $this->prop ** 2,
];
}
}
var_dump(new C(42));
?>Результат выполнения данного примера:
object(C)#1 (1) {
["propSquared"]=>
int(1764)
}
PHP предоставляет ключевое слово final, разместив которое
перед объявлениями методов или констант класса, можно предотвратить их
переопределение в дочерних классах. Если же сам класс определяется
с этим ключевым словом, то он не сможет быть унаследован.
Пример #1 Пример окончательных (final) методов
<?php
class BaseClass {
public function test() {
echo "Вызван метод BaseClass::test()\n";
}
final public function moreTesting() {
echo "Вызван метод BaseClass::moreTesting()\n";
}
}
class ChildClass extends BaseClass {
public function moreTesting() {
echo "Вызван метод ChildClass::moreTesting()\n";
}
}
// Выполнение заканчивается фатальной ошибкой: Cannot override final method BaseClass::moreTesting()
// (Окончательный (final) метод BaseClass::moreТesting() не может быть переопределён)
?>
Пример #2 Пример окончательного (final) класса
<?php
final class BaseClass {
public function test() {
echo "Вызван метод BaseClass::test()\n";
}
// Поскольку класс уже является final, ключевое слово final является избыточным
final public function moreTesting() {
echo "BaseClass::moreTesting() called\n";
}
}
class ChildClass extends BaseClass {
}
// Выполнение заканчивается фатальной ошибкой: Class ChildClass may not inherit from final class (BaseClass)
// (Класс ChildClass не может быть унаследован от окончательного класса (BaseClass))
?>
Пример #3 Пример окончательной (final) константы класса, начиная с PHP 8.1.0
<?php
class Foo
{
final public const X = "foo";
}
class Bar extends Foo
{
public const X = "bar";
}
// Ошибка: Bar::X не может переопределить окончательную константу Foo::X
?>Замечание: Свойства не могут быть объявлены окончательными: только классы, методы и константы (начиная с PHP 8.1.0) могут быть объявлены как окончательные (final). Начиная с PHP 8.0.0, закрытые методы не могут быть объявлены окончательными, за исключением конструктора.
Создание копии объекта с абсолютно идентичными свойствами не всегда является приемлемым вариантом. Хорошим примером необходимости копирования конструкторов может послужить ситуация, когда у вас есть объект, представляющий собой окно GTK и содержащий ресурс-идентификатор этого окна; когда вы создаёте копию этого объекта, вам может понадобиться, чтобы копия объекта содержала ресурс-идентификатор нового окна. Другим примером может послужить ситуация, когда ваш объект содержит ссылку на какой-либо другой используемый объект и, когда вы создаёте копию родительского объекта, вам нужно также создать новый экземпляр этого другого объекта, так, чтобы копия объекта-контейнера содержала собственный отдельный экземпляр содержащегося объекта.
Копия объекта создаётся с использованием ключевого слова clone
(который вызывает метод __clone()
объекта, если это возможно).
$copy_of_object = clone $object;
При клонировании объекта, PHP выполняет поверхностную копию всех свойств объекта. Любые свойства, являющиеся ссылками на другие переменные, останутся ссылками.
После завершения клонирования, если метод __clone() определён, то будет вызван метод __clone() вновь созданного объекта для возможного изменения всех необходимых свойств.
Пример #1 Клонирование объекта
<?php
class SubObject
{
static $instances = 0;
public $instance;
public function __construct() {
$this->instance = ++self::$instances;
}
public function __clone() {
$this->instance = ++self::$instances;
}
}
class MyCloneable
{
public $object1;
public $object2;
function __clone()
{
// Принудительно клонируем this->object1, иначе
// он будет указывать на один и тот же объект.
$this->object1 = clone $this->object1;
}
}
$obj = new MyCloneable();
$obj->object1 = new SubObject();
$obj->object2 = new SubObject();
$obj2 = clone $obj;
print("Оригинальный объект:\n");
print_r($obj);
print("Клонированный объект:\n");
print_r($obj2);
?>Результат выполнения данного примера:
Оригинальный объект:
MyCloneable Object
(
[object1] => SubObject Object
(
[instance] => 1
)
[object2] => SubObject Object
(
[instance] => 2
)
)
Клонированный объект:
MyCloneable Object
(
[object1] => SubObject Object
(
[instance] => 3
)
[object2] => SubObject Object
(
[instance] => 2
)
)
Возможно обращаться к свойствам/методам только что склонированного объекта:
Пример #2 Доступ к только что склонированному объекту
<?php
$dateTime = new DateTime();
echo (clone $dateTime)->format('Y');
?>Результатом выполнения данного примера будет что-то подобное:
2016
При использовании оператора сравнения (==),
свойства объектов просто сравниваются друг с другом, а именно: два
объекта равны, если они имеют одинаковые атрибуты и значения
(значения сравниваются через ==) и являются
экземплярами одного и того же класса.
С другой стороны, при использовании оператора идентичности (===),
переменные, содержащие объекты, считаются идентичными только тогда, когда
они ссылаются на один и тот же экземпляр одного и того же класса.
Следующий пример пояснит эти правила.
Пример #1 Пример сравнения объектов
<?php
function bool2str($bool)
{
return (string) $bool;
}
function compareObjects(&$o1, &$o2)
{
echo 'o1 == o2 : ' . bool2str($o1 == $o2) . "\n";
echo 'o1 != o2 : ' . bool2str($o1 != $o2) . "\n";
echo 'o1 === o2 : ' . bool2str($o1 === $o2) . "\n";
echo 'o1 !== o2 : ' . bool2str($o1 !== $o2) . "\n";
}
class Flag
{
public $flag;
function __construct($flag = true) {
$this->flag = $flag;
}
}
class OtherFlag
{
public $flag;
function __construct($flag = true) {
$this->flag = $flag;
}
}
$o = new Flag();
$p = new Flag();
$q = $o;
$r = new OtherFlag();
echo "Два экземпляра одного и того же класса\n";
compareObjects($o, $p);
echo "\nДве ссылки на один и тот же экземпляр\n";
compareObjects($o, $q);
echo "\nЭкземпляры двух разных классов\n";
compareObjects($o, $r);
?>Результат выполнения данного примера:
Два экземпляра одного и того же класса o1 == o2 : TRUE o1 != o2 : FALSE o1 === o2 : FALSE o1 !== o2 : TRUE Две ссылки на один и тот же экземпляр o1 == o2 : TRUE o1 != o2 : FALSE o1 === o2 : TRUE o1 !== o2 : FALSE Экземпляры двух разных классов o1 == o2 : FALSE o1 != o2 : TRUE o1 === o2 : FALSE o1 !== o2 : TRUE
Замечание:
Модули могут определять собственные правила для сравнения своих объектов (
==).
PHP реализует функцию, называемую позднее статическое связывание, которая может быть использована для того, чтобы получить ссылку на вызываемый класс в контексте статического наследования.
Если говорить более точно, позднее статическое связывание сохраняет имя класса
указанного в последнем "неперенаправленном вызове". В случае статических
вызовов это явно указанный класс (обычно слева от оператора
::);
в случае не статических вызовов это класс объекта. "Перенаправленный вызов" - это
статический вызов, начинающийся с self::, parent::,
static::, или, если двигаться вверх по иерархии классов,
forward_static_call().
Функция get_called_class() может быть использована для
получения строки с именем вызванного класса, а static::
представляет её область действия.
Само название "позднее статическое связывание" отражает в себе внутреннюю
реализацию этой особенности. "Позднее связывание" отражает тот факт, что
обращения через static:: не будут вычисляться по отношению
к классу, в котором вызываемый метод определён, а будут вычисляться на основе
информации в ходе исполнения.
Также эта особенность была названа "статическое связывание" потому, что она
может быть использована (но не обязательно) в статических методах.
self::
Статические ссылки на текущий класс, такие как self::
или __CLASS__, вычисляются используя класс,
к которому эта функция принадлежит, как и в том месте, где она была определена:
Пример #1 Использование self::
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
self::who();
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>Результат выполнения данного примера:
A
Позднее статическое связывание пытается устранить это ограничение, предоставляя
ключевое слово, которое ссылается на класс, вызванный непосредственно в
ходе выполнения. Попросту говоря, ключевое слово, которое позволит вам
ссылаться на B из test() в
предыдущем примере. Было решено не вводить новое ключевое слово, а
использовать static, которое уже зарезервировано.
Пример #2 Простое использование static::
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // Здесь действует позднее статическое связывание
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>Результат выполнения данного примера:
B
Замечание:
В нестатическом контексте вызванным классом будет тот, к которому относится экземпляр объекта. Поскольку
$this->будет пытаться вызывать закрытые методы из той же области действия, использованиеstatic::может дать разные результаты. Другое отличие в том, чтоstatic::может ссылаться только на статические поля класса.
Пример #3 Использование static:: в нестатическом контексте
<?php
class A {
private function foo() {
echo "success!\n";
}
public function test() {
$this->foo();
static::foo();
}
}
class B extends A {
/* foo() будет скопирован в В, следовательно его область действия по прежнему А,
и вызов будет успешным */
}
class C extends A {
private function foo() {
/* исходный метод заменён; область действия нового метода - С */
}
}
$b = new B();
$b->test();
$c = new C();
$c->test(); // потерпит ошибку
?>Результат выполнения данного примера:
success! success! success! Fatal error: Call to private method C::foo() from context 'A' in /tmp/test.php on line 9
Замечание:
Разрешающая область позднего статического связывания будет фиксирована вычисляющем её статическим вызовом. С другой стороны, статические вызовы с использованием таких директив как
parent::илиself::перенаправляют информацию вызова.Пример #4 Перенаправленные и неперенаправленные вызовы
<?php
class A {
public static function foo() {
static::who();
}
public static function who() {
echo __CLASS__."\n";
}
}
class B extends A {
public static function test() {
A::foo();
parent::foo();
self::foo();
}
public static function who() {
echo __CLASS__."\n";
}
}
class C extends B {
public static function who() {
echo __CLASS__."\n";
}
}
C::test();
?>Результат выполнения данного примера:
A C C
Одним из ключевых моментов объектно-ориентированной парадигмы PHP, который часто обсуждается, является "передача объектов по ссылке по умолчанию". Это не совсем верно. Данный раздел уточняет это понятие, используя некоторые примеры.
Ссылка в PHP - это псевдоним (алиас), который позволяет присвоить двум переменным одинаковое значение. В PHP объектная переменная больше не содержит сам объект как значение. Такая переменная содержит только идентификатор объекта, который позволяет найти конкретный объект при обращении к нему. Когда объект передаётся как аргумент функции, возвращается или присваивается другой переменной, то эти разные переменные не являются псевдонимами (алиасами): они содержат копию идентификатора, который указывает на один и тот же объект.
Пример #1 Ссылки и объекты
<?php
class A {
public $foo = 1;
}
$a = new A;
$b = $a; // $a и $b - копии одного идентификатора
// ($a) = ($b) = <id>
$b->foo = 2;
echo $a->foo."\n";
$c = new A;
$d = &$c; // $c и $d - ссылки
// ($c,$d) = <id>
$d->foo = 2;
echo $c->foo."\n";
$e = new A;
function foo($obj) {
// ($obj) = ($e) = <id>
$obj->foo = 2;
}
foo($e);
echo $e->foo."\n";
?>Результат выполнения данного примера:
2 2 2
Функция serialize() возвращает строковое представление любого значения, которое может быть сохранено в PHP. Функция unserialize() может использовать эту строку для восстановления исходного значения переменной. Использование сериализации для сохранения объекта сохранит все его переменные. Методы в объекте не будут сохранены, только имя класса.
Для того, чтобы иметь возможность выполнить unserialize() для объекта, нужно, чтобы класс этого объекта был определён заранее. То есть, если у вас есть экземпляр класса А, и вы сделаете его сериализацию, вы получите его строковое представление, которое содержит значение всех переменных, содержащихся в нем. Для того, чтобы восстановить объект из строки в другом PHP-файле, класс A должен быть определён заранее. Это можно сделать, например, путём сохранения определения класса A в отдельный файл и подключить этот файл или использовать функцию spl_autoload_register() для автоматического подключения.
<?php
// classa.inc:
class A {
public $one = 1;
public function show_one() {
echo $this->one;
}
}
// page1.php:
include("classa.inc");
$a = new A;
$s = serialize($a);
// сохраняем $s где-нибудь, откуда page2.php сможет его получить.
file_put_contents('store', $s);
// page2.php:
// это нужно для того, чтобы функция unserialize работала правильно.
include("classa.inc");
$s = file_get_contents('store');
$a = unserialize($s);
// теперь можно использовать метод show_one() объекта $a.
$a->show_one();
?>Если в приложении производится сериализация объектов для последующего использования, настоятельно рекомендуется подключать определение класса для этого объекта во всем приложении. Невыполнение этого требования может привести к тому, что объект будет десериализован без определения класса, что приведёт к тому, что PHP будет использовать для этого объекта класс __PHP_Incomplete_Class_Name, который не имеет методов и сделает объект бесполезным.
Поэтому, если в приведённом выше примере $a стало частью сессии
после запуска session_register("a"), вы должны подключать
файл classa.inc на всех ваших страницах, а не только page1.php
и page2.php.
Обратите внимание, что, кроме вышеприведённого совета, также можно подключиться к событиям сериализации и десериализации объекта с помощью методов __sleep() и __wakeup(). Метод __sleep() также позволяет сериализовать лишь некоторое подмножество свойств объекта.
В PHP 7.2.0 была добавлена частичная контравариантность путём устранения ограничений типа для параметров в дочернем методе. Начиная с PHP 7.4.0, добавлена полная поддержка ковариантности и контравариантности.
Ковариантность позволяет дочернему методу возвращать более конкретный тип, чем тип возвращаемого значения его родительского метода. В то время как контравариантность позволяет типу параметра в дочернем методе быть менее специфичным, чем в родительском.
Объявление типа считается более конкретным в следующем случае:
Чтобы проиллюстрировать, как работает ковариантность, создадим простой абстрактный родительский класс Animal. Animal будет расширен за счёт дочерних классов Cat и Dog.
<?php
abstract class Animal
{
protected string $name;
public function __construct(string $name)
{
$this->name = $name;
}
abstract public function speak();
}
class Dog extends Animal
{
public function speak()
{
echo $this->name . " лает";
}
}
class Cat extends Animal
{
public function speak()
{
echo $this->name . " мяукает";
}
}Обратите внимание, что в примере нет методов, которые возвращают значения. Будет добавлено несколько фабрик, которые возвращают новый объект типа класса Animal, Cat или Dog.
<?php
interface AnimalShelter
{
public function adopt(string $name): Animal;
}
class CatShelter implements AnimalShelter
{
public function adopt(string $name): Cat // Возвращаем класс Cat вместо Animal
{
return new Cat($name);
}
}
class DogShelter implements AnimalShelter
{
public function adopt(string $name): Dog // Возвращаем класс Dog вместо Animal
{
return new Dog($name);
}
}
$kitty = (new CatShelter)->adopt("Рыжик");
$kitty->speak();
echo "\n";
$doggy = (new DogShelter)->adopt("Бобик");
$doggy->speak();Результат выполнения данного примера:
Рыжик мяукает Бобик лает
В продолжение предыдущего примера, где мы использовали классы Animal, Cat и Dog, мы введём новые классы Food и AnimalFood и добавим в абстрактный класс Animal новый метод eat(AnimalFood $food).
<?php
class Food {}
class AnimalFood extends Food {}
abstract class Animal
{
protected string $name;
public function __construct(string $name)
{
$this->name = $name;
}
public function eat(AnimalFood $food)
{
echo $this->name . " ест " . get_class($food);
}
}Чтобы увидеть суть контравариантности, мы переопределим метод eat класса Dog таким образом, чтобы он мог принимать любой объект класса Food. Класс Cat оставим без изменений.
<?php
class Dog extends Animal
{
public function eat(Food $food) {
echo $this->name . " ест " . get_class($food);
}
}Следующий пример покажет поведение контравариантности.
<?php
$kitty = (new CatShelter)->adopt("Рыжик");
$catFood = new AnimalFood();
$kitty->eat($catFood);
echo "\n";
$doggy = (new DogShelter)->adopt("Бобик");
$banana = new Food();
$doggy->eat($banana);Результат выполнения данного примера:
Рыжик ест AnimalFood Бобик ест Food
Но что случится, если $kitty попробует съесть (eat()) банан ($banana)?
$kitty->eat($banana);Результат выполнения данного примера:
Fatal error: Uncaught TypeError: Argument 1 passed to Animal::eat() must be an instance of AnimalFood, instance of Food given
Здесь перечислены изменения модели ООП в PHP. Описания и другие примечания этих возможностей можно найти в документации ООП PHP.
| Версия | Описание |
|---|---|
| 8.1.0 | Добавлено: Поддержка модификатора final для констант класса. Кроме того, константы интерфейса по умолчанию становятся переопределяемыми. |
| 8.0.0 | Добавлено: Поддержка оператора Nullsafe ?-> для доступа к свойствам и методам объектов, которые могут быть равны null. |
| 7.4.0 | Изменено: Теперь можно выбрасывать исключение в функции __toString(). |
| 7.4.0 | Добавлено: поддержка ограниченной ковариантности типов возвращаемого значения и типов аргументов. Поддержка полной вариативности производится только если используется автозагрузка. Внутри одного файла возможны только нециклические ссылки на типы. |
| 7.4.0 | Добавлено: Теперь можно задавать тип для свойств класса. |
| 7.3.0 | Несовместимость: распаковка аргументов для Traversable с нецелочисленными ключами больше не поддерживается. Такое поведение изначально не планировалось и теперь удалено. |
| 7.3.0 | Несовместимость: в прошлых версиях можно было разделить статические свойства при помощи присваивания по ссылке. Теперь нельзя. |
| 7.3.0 |
Изменено: теперь оператор
instanceof
допускает литералы в качестве первого операнда. В этом
случае всегда будет возвращено false.
|
| 7.2.0 | Устарело: метод __autoload() объявлен устаревшим в пользу spl_autoload_register(). |
| 7.2.0 |
Изменено: для имён классов, интерфейсов и трейтов нельзя использовать слово object.
|
| 7.2.0 | Изменено: для группового use теперь можно добавлять висящую запятую в конце списка. |
| 7.2.0 | Изменено: Типы параметров из переопределённых методов и реализации интерфейсов теперь указывать не обязательно |
| 7.2.0 | Изменено: если один абстрактный класс наследует от другого абстрактного класса, то он может переопределять его абстрактные методы. |
| 7.1.0 |
Изменено: для имён классов, интерфейсов и трейтов нельзя использовать слова: void и iterable.
|
| 7.1.0 | Добавлено: теперь можно задавать область видимости для констант классов. |
| 7.0.0 | Устарело: Статический вызов нестатических методов. |
| 7.0.0 | Устарело: конструктор в стиле PHP 4. Т.е. метод с именем идентичным имени класса, в котором он объявлен. |
| 7.0.0 | Добавлено: групповая декларация use: классы, функции и константы, которые надо импортировать из одного и того же пространства имён теперь могут быть сгруппированы в одном выражении use. |
| 7.0.0 |
Добавлено: добавлена поддержка
анонимных классов
с помощью new class.
|
| 7.0.0 | Несовместимость: итерирование объектов не реализующих Traversable теперь ведёт себя аналогично итерированию массива по ссылке. |
| 7.0.0 | Изменено: Определение одинаковых (полностью совпадающих) свойств в двух трейтах больше не вызывает ошибку. |
| 5.6.0 | Добавлено: метод __debugInfo(). |
| 5.5.0 | Добавлено: магическая константа ::class. |
| 5.5.0 | Добавлено: finally в обработчик исключений. |
| 5.4.0 | Добавлено: трейты. |
| 5.4.0 | Изменено: Если абстрактный класс определяет сигнатуру для конструктора, то она будет принудительно применяться. |
| 5.3.3 | Изменено: Методы с тем же именем, что и последний элемент пространства имён класса больше не будут рассматриваться как конструктор. Это изменение не влияет классы, не использующие пространства имён. |
| 5.3.0 | Изменено: Больше не требуется, чтобы классы, реализующие интерфейсы с методами, которые имеют значения по умолчанию в прототипе, соответствовали значениям по умолчанию в интерфейсе. |
| 5.3.0 |
Изменено: Теперь стало возможным ссылаться на класс, используя переменную (например,
echo $classname::constant;).
Значение переменной не может быть ключевым словом (например, self,
parent или static).
|
| 5.3.0 |
Изменено: Ошибка E_WARNING происходит, если
магические перегруженные
методы объявлены как статические.
Это также усиливает требование, что эти методы должны быть общедоступными.
|
| 5.3.0 | Изменено: До 5.3.0, исключения в функции __autoload() не могли быть перехвачены в блоке catch и приводили к фатальной ошибке. Сейчас исключения в функции __autoload могут быть перехвачены в блоке catch, но с одной оговоркой. Если перехватывается пользовательское исключение, то класс, обрабатывающий это исключение, должен быть доступен. Функция __autoload может быть использована рекурсивно для автозагрузки пользовательского класса обработки исключения. |
| 5.3.0 | Добавлено: Метод __callStatic. |
| 5.3.0 | Добавлено: Поддержка heredoc и nowdoc для констант и определений свойств класса. Примечание: Значение heredoc должны следовать тем же правилам, что и строки в двойных кавычках (например, без переменных внутри). |
| 5.3.0 | Добавлено: Позднее статическое связывание. |
| 5.3.0 | Добавлено: метод __invoke(). |
| 5.2.0 |
Изменено: Метод __toString()
вызывался только, когда он напрямую объединён с
echo или print.
Сейчас он вызывается в любом контексте строки (например, в
printf() с модификатором %s), но не
в других типах контекста (например, с модификатором %d).
С PHP 5.2.0, преобразование объектов без метода __toString
в строку выдаёт ошибку уровня E_RECOVERABLE_ERROR.
|
| 5.1.3 |
Изменено: В предыдущих версиях PHP 5 использование var
считалось устаревшим и выдавало ошибку E_STRICT.
Сейчас это не считается устаревшим, поэтому ошибка больше не выдаётся.
|
| 5.1.0 | Изменено: Статический метод __set_state() теперь вызывается для классов, экспортируемых функцией var_export(). |
| 5.1.0 | Добавлены: методы __isset() и __unset(). |
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Что такое пространства имён? В широком смысле - это один из способов инкапсуляции
элементов. Такое абстрактное понятие можно увидеть во многих местах. Например, в любой
операционной системе директории служат для группировки связанных файлов и выступают в
качестве пространства имён для находящихся в них файлов. В качестве конкретного примера
файл foo.txt может находиться сразу в обеих директориях:
/home/greg и /home/other, но две копии
foo.txt не могут существовать в одной директории. Кроме того, для доступа
к foo.txt извне директории /home/greg, мы должны
добавить имя директории перед именем файла используя разделитель, чтобы получить
/home/greg/foo.txt. Этот же принцип распространяется и на пространства
имён в программировании.
В PHP пространства имён используются для решения двух проблем, с которыми сталкиваются авторы библиотек и приложений при создании повторно используемых элементов кода, таких как классы и функции:
Пространства имён в PHP предоставляют возможность группировать логически связанные классы, интерфейсы, функции и константы.
Пример #1 Пример синтаксиса, использующего пространство имён
<?php
namespace my\name; // смотрите раздел "Определение пространств имён"
class MyClass {}
function myfunction() {}
const MYCONST = 1;
$a = new MyClass;
$c = new \my\name\MyClass; // смотрите раздел "Глобальная область видимости"
$a = strlen('hi'); // смотрите раздел "Использование пространств имён: возврат
// к глобальной функции/константе"
$d = namespace\MYCONST; // смотрите раздел "оператор пространства имён и
// константа __NAMESPACE__"
$d = __NAMESPACE__ . '\MYCONST';
echo constant($d); // смотрите раздел "Пространства имён и динамические особенности языка"
?>Замечание: Имена пространств имён регистронезависимы.
Замечание:
Пространства имён
PHPили составные имена, начинающиеся с этого слова (например, такие какPHP\Classes), зарезервированы для нужд языка, их не следует использовать в пользовательском коде.
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Хотя любой корректный PHP-код может находиться внутри пространства имён, только классы (включая абстрактные и трейты), интерфейсы, функции и константы зависят от него.
Пространства имён объявляются с помощью зарезервированного слова namespace.
Файл, содержащий пространство имён, должен содержать его объявление в начале
перед любым другим кодом, кроме зарезервированного слова
declare.
Пример #1 Объявление единого пространства имён
<?php
namespace MyProject;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
?>Только выражениеЗамечание: Абсолютные имена (т.е. имена, начинающиеся с обратной косой черты) не допускаются в объявлениях пространства имён, поскольку такие конструкции интерпретируются как относительные выражения пространства имён.
declare может находиться перед объявлением
пространства имён для указания кодировки файла. Кроме того, объявлению пространства имён
не должен предшествовать не PHP-код, в том числе лишние пробелы:
Пример #2 Объявление простого пространства имён
<html>
<?php
namespace MyProject; // fatal error - объявление пространства имён должно быть первым выражением в скрипте
?>Кроме того, в отличие от любой другой конструкции PHP, одно и то же пространство имён можно определять в нескольких файлах, что позволяет распределять их содержимое по файловой системе.
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Так же как файлы и каталоги, пространства имён PHP позволяют создавать иерархию имён. Таким образом, имя пространства может быть определено с подуровнями:
Пример #1 Определение пространства имён с иерархией
<?php
namespace MyProject\Sub\Level;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
?>MyProject\Sub\Level\CONNECT_OK,
класс MyProject\Sub\Level\Connection и функцию
MyProject\Sub\Level\connect.
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Несколько пространств имён также можно описать в одном файле с помощью двух допустимых синтаксических конструкций.
Пример #1 Описание нескольких пространств имён, простой синтаксис
<?php
namespace MyProject;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
namespace AnotherProject;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
?>Данный синтаксис не рекомендуется для комбинирования пространств имён в одном файле. Вместо этого рекомендуется использовать альтернативный синтаксис со скобками.
Пример #2 Описание нескольких пространств имён, синтаксис со скобками
<?php
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace AnotherProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
?>Настоятельно не рекомендуется при программировании комбинировать несколько пространств имён в один файл. Основным применением этому может быть объединение нескольких PHP-файлов в один файл.
Для объединения кода в глобальном пространстве имён с кодом в других пространствах имён, используется только синтаксис со скобками. Глобальный код должен быть помещён в конструкцию описания пространства имён без указания имени:
Пример #3 Описание глобального и обычного пространства имён в одном файле
<?php
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace { // глобальный код
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
?>PHP-код не может находиться вне скобок конструкции пространства имён, кроме начального выражения declare.
Пример #4 Описание глобального и обычного пространства имён в одном файле
<?php
declare(encoding='UTF-8');
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace { // глобальный код
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
?>(PHP 5 >= 5.3.0, PHP 7, PHP 8)
До обсуждения использования пространств имён важно понять, как PHP узнает, какие элементы из пространства имён запрашиваются в вашем коде. Можно провести аналогию между пространствами имён PHP и файловой системой. Есть три способа обратиться к файлу в файловой системе:
foo.txt, преобразуемое в
currentdirectory/foo.txt, где currentdirectory - текущая
директория, в которой мы находимся. Тогда, если текущая директория
/home/foo, то имя преобразуется в /home/foo/foo.txt.
subdirectory/foo.txt, преобразуется
в currentdirectory/subdirectory/foo.txt.
/main/foo.txt, которое остаётся
таким же: /main/foo.txt.
$a = new foo(); или
foo::staticmethod();. Если текущее пространство имён
currentnamespace, то эти имена преобразуются в
currentnamespace\foo. Если код находится в глобальном
пространстве имён, то имена остаются такими же: foo.
Предупреждение: неполные имена для функций и констант будут определяться
в глобальном пространстве имён, если они не определены в текущем пространстве имён.
Подробнее в Использование пространств
имён: доступ к глобальным функциям и классам.
$a = new subnamespace\foo(); или
subnamespace\foo::staticmethod();. Если текущее пространство имён
currentnamespace, то эти имена преобразуются в
currentnamespace\subnamespace\foo. Если
код находится в глобальном пространстве имён, то имена преобразуются в subnamespace\foo.
$a = new \currentnamespace\foo(); или
\currentnamespace\foo::staticmethod();. Имена всегда
определяются так же, как и записаны: currentnamespace\foo.
Ниже приведён пример трёх вариантов синтаксиса в реальном коде:
file1.php
<?php
namespace Foo\Bar\subnamespace;
const FOO = 1;
function foo() {}
class foo
{
static function staticmethod() {}
}
?>file2.php
<?php
namespace Foo\Bar;
include 'file1.php';
const FOO = 2;
function foo() {}
class foo
{
static function staticmethod() {}
}
/* Неполные имена */
foo(); // определяется как функция Foo\Bar\foo
foo::staticmethod(); // определяется как класс Foo\Bar\foo с методом staticmethod
echo FOO; // определяется как константа Foo\Bar\FOO
/* Полные имена */
subnamespace\foo(); // определяется как функция Foo\Bar\subnamespace\foo
subnamespace\foo::staticmethod(); // определяется как класс Foo\Bar\subnamespace\foo
// c методом staticmethod
echo subnamespace\FOO; // определяется как константа Foo\Bar\subnamespace\FOO
/* Абсолютные имена */
\Foo\Bar\foo(); // определяется как функция Foo\Bar\foo
\Foo\Bar\foo::staticmethod(); // определяется как класс Foo\Bar\foo с методом staticmethod
echo \Foo\Bar\FOO; // определяется как константа Foo\Bar\FOO
?>
Обратите внимание, что для доступа к любым глобальным
классам, функциям или константам, может использоваться абсолютное имя, такое как
\strlen(), или \Exception, или
\INI_ALL.
Пример #1 Доступ к глобальным классам, функциям и константам из пространства имён
<?php
namespace Foo;
function strlen() {}
const INI_ALL = 3;
class Exception {}
$a = \strlen('hi'); // вызывает глобальную функцию strlen
$b = \INI_ALL; // получает доступ к глобальной константе INI_ALL
$c = new \Exception('error'); // Создаёт экземпляр глобального класса Exception
?>(PHP 5 >= 5.3.0, PHP 7, PHP 8)
На реализацию пространств имён в PHP повлияли и динамические особенности языка. Преобразуем нижеследующий код для использования пространств имён:
Пример #1 Динамически доступные элементы
example1.php:
<?php
class classname
{
function __construct()
{
echo __METHOD__,"\n";
}
}
function funcname()
{
echo __FUNCTION__,"\n";
}
const constname = "global";
$a = 'classname';
$obj = new $a; // выводит classname::__construct
$b = 'funcname';
$b(); // выводит funcname
echo constant('constname'), "\n"; // выводит global
?>Пример #2 Динамически доступные элементы пространства имён
<?php
namespace namespacename;
class classname
{
function __construct()
{
echo __METHOD__,"\n";
}
}
function funcname()
{
echo __FUNCTION__,"\n";
}
const constname = "namespaced";
include 'example1.php';
$a = 'classname';
$obj = new $a; // выводит classname::__construct
$b = 'funcname';
$b(); // выводит funcname
echo constant('constname'), "\n"; // выводит global
/* обратите внимание, что при использовании двойных кавычек символ обратного слеша должен быть заэкранирован. Например, "\\namespacename\\classname" */
$a = '\namespacename\classname';
$obj = new $a; // выводит namespacename\classname::__construct
$a = 'namespacename\classname';
$obj = new $a; // также выводит namespacename\classname::__construct
$b = 'namespacename\funcname';
$b(); // выводит namespacename\funcname
$b = '\namespacename\funcname';
$b(); // также выводит namespacename\funcname
echo constant('\namespacename\constname'), "\n"; // выводит namespaced
echo constant('namespacename\constname'), "\n"; // также выводит namespaced
?>Обязательно прочитайте примечание об экранировании имён пространства имён в строках.
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
PHP поддерживает два способа доступа к абстрактным элементам в текущем пространстве
имён таким, как магическая константа __NAMESPACE__ и ключевое
слово namespace.
Значение константы __NAMESPACE__ - это строка, которая содержит
имя текущего пространства имён. В глобальном пространстве, вне пространства имён, она
содержит пустую строку.
Пример #1 Пример использование константы __NAMESPACE__ в коде с пространством имён
<?php
namespace MyProject;
echo '"', __NAMESPACE__, '"'; // выводит "MyProject"
?>Пример #2 Пример использование константы __NAMESPACE__ в глобальном пространстве
<?php
echo '"', __NAMESPACE__, '"'; // выводит ""
?>__NAMESPACE__ полезна для динамически конструируемых
имён, например:
Пример #3 использование константы __NAMESPACE__ для динамического конструирования имени
<?php
namespace MyProject;
function get($classname)
{
$a = __NAMESPACE__ . '\\' . $classname;
return new $a;
}
?>
Ключевое слово namespace может быть использовано для
явного запроса элемента из текущего пространства имён или из подпространства.
Это эквивалент оператора self для классов в пространстве имён.
Пример #4 Оператор namespace, внутри пространства имён
<?php
namespace MyProject;
use blah\blah as mine; // смотрите "Использование пространств имён: импорт/создание псевдонима имени"
blah\mine(); // вызывает функцию MyProject\blah\mine()
namespace\blah\mine(); // вызывает функцию MyProject\blah\mine()
namespace\func(); // вызывает функцию MyProject\func()
namespace\sub\func(); // вызывает функцию MyProject\sub\func()
namespace\cname::method(); // вызывает статический метод "method" класса MyProject\cname
$a = new namespace\sub\cname(); // Создаёт экземпляр класса MyProject\sub\cname
$b = namespace\CONSTANT; // присваивает значение константы MyProject\CONSTANT переменной $b
?>Пример #5 Оператор namespace в глобальном коде
<?php
namespace\func(); // вызывает функцию func()
namespace\sub\func(); // вызывает функцию sub\func()
namespace\cname::method(); // вызывает статический метод "method" класса cname
$a = new namespace\sub\cname(); // Создаёт экземпляр класса sub\cname
$b = namespace\CONSTANT; // присваивает значение константы CONSTANT переменной $b
?>(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Возможность ссылаться на внешнее абсолютное имя по псевдониму или импортированию - это важная особенность пространств имён. Это похоже на возможность файловых систем unix создавать символические ссылки на файл или директорию.
PHP может создавать псевдонимы имени/импортировать константы, функции, классы, интерфейсы, трейты, перечисления и пространства имён.
Создание псевдонима имени выполняется с помощью оператора use.
Вот пример, показывающий 5 типов импорта:
Пример #1 импорт/создание псевдонима имени с помощью оператора use
<?php
namespace foo;
use My\Full\Classname as Another;
// это тоже самое, что и использование My\Full\NSname as NSname
use My\Full\NSname;
// импортирование глобального класса
use ArrayObject;
// импортирование функции
use function My\Full\functionName;
// псевдоним функции
use function My\Full\functionName as func;
// импортирование константы
use const My\Full\CONSTANT;
$obj = new namespace\Another; // создаёт экземпляр класса foo\Another
$obj = new Another; // создаёт объект класса My\Full\Classname
NSname\subns\func(); // вызывает функцию My\Full\NSname\subns\func
$a = new ArrayObject(array(1)); // создаёт объект класса ArrayObject
// без выражения "use ArrayObject" мы создадим объект класса foo\ArrayObject
func(); // вызывает функцию My\Full\functionName
echo CONSTANT; // выводит содержимое константы My\Full\CONSTANT
?>Foo\Bar, в отличие от
глобальных имён, которые его не содержат, такие как FooBar) нет
необходимости в начальном обратном слеше (\) и его присутствие там не рекомендуется, так
как импортируемые имена должны быть абсолютными и не обрабатываются
относительно текущего пространства имён.
PHP дополнительно поддерживает удобное сокращение для задания нескольких операторов use в одной и той же строке
Пример #2 импорт/создание псевдонима имени с помощью оператора use, комбинирование нескольких операторов use
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // создаёт объект класса My\Full\Classname
NSname\subns\func(); // вызывает функцию My\Full\NSname\subns\func
?>Импорт выполняется во время компиляции и поэтому не влияет на имена динамических классов, функций или констант.
Пример #3 Импорт и динамические имена
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // создаёт объект класса My\Full\Classname
$a = 'Another';
$obj = new $a; // создаёт объект класса Another
?>В дополнение, импорт распространяется только на неполные и полные имена. Абсолютные имена не затрагиваются операцией импорта.
Пример #4 Импортирование и абсолютные имена
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // создаёт объект класса My\Full\Classname
$obj = new \Another; // создаёт объект класса Another
$obj = new Another\thing; // создаёт объект класса My\Full\Classname\thing
$obj = new \Another\thing; // создаёт объект класса Another\thing
?>
Ключевое слово use должно быть указано в самом начале файла (в
глобальной области) или внутри объявления пространства имён. Это необходимо потому, что
импорт выполняется во время компиляции, а не во время исполнения, поэтому оно не может
быть заключено в блок. Следующий пример показывает недопустимое применение
ключевого слова use:
Пример #5 Недопустимое правило импорта
<?php
namespace Languages;
function toGreenlandic()
{
use Languages\Danish;
//...
}
?>Замечание:
Правила импорта задаются на каждый файл отдельно. Это означает, что присоединяемые файлы НЕ будут наследовать правила импорта из родительского файла.
use
Классы, функции и константы, импортируемые из
одного и того же namespace, могут группироваться в одном операторе use.
<?php
use some\namespace\ClassA;
use some\namespace\ClassB;
use some\namespace\ClassC as C;
use function some\namespace\fn_a;
use function some\namespace\fn_b;
use function some\namespace\fn_c;
use const some\namespace\ConstA;
use const some\namespace\ConstB;
use const some\namespace\ConstC;
// Эквивалентно следующему групповому использованию
use some\namespace\{ClassA, ClassB, ClassC as C};
use function some\namespace\{fn_a, fn_b, fn_c};
use const some\namespace\{ConstA, ConstB, ConstC};(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Без определения пространства имён, определения всех классов и функций
находятся в глобальном пространстве - так же, как это было в PHP до введения
пространств имён. Добавление префикса \ к именам означает, что
это имя должно находиться в глобальном пространстве, даже если вы находитесь в
контексте определённого пространства имён.
Пример #1 Использование глобального пространства и его задание
<?php
namespace A\B\C;
/* Эта функция является A\B\C\fopen */
function fopen() {
/* ... */
$f = \fopen(...); // вызов глобальной функции fopen
return $f;
}
?>(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Внутри пространства имён, когда PHP встречает неполное имя класса, функции или константы, он преобразует эти имена с разными приоритетами. Имена классов всегда преобразуются к текущему имени пространства имён. Таким образом, чтобы получить доступ ко внутреннему классу или пользовательскому классу вне пространства имён, необходимо ссылаться по их абсолютному имени. Например:
Пример #1 Доступ к глобальным классам внутри пространства имён
<?php
namespace A\B\C;
class Exception extends \Exception {}
$a = new Exception('hi'); // $a - это объект класса A\B\C\Exception
$b = new \Exception('hi'); // $b - это объект класса Exception
$c = new ArrayObject; // фатальная ошибка, класс A\B\C\ArrayObject не найден
?>Для функций и констант, PHP будет прибегать к глобальным функциям или константам, если функция или константа не существует в пространстве имён.
Пример #2 Необходимость прибегнуть к глобальным функциям/константам внутри пространства имён
<?php
namespace A\B\C;
const E_ERROR = 45;
function strlen($str)
{
return \strlen($str) - 1;
}
echo E_ERROR, "\n"; // выводит "45"
echo INI_ALL, "\n"; // выводит "7" - прибегнет к глобальной INI_ALL
echo strlen('hi'), "\n"; // выводит "1"
if (is_array('hi')) { // выводит строку "это не массив"
echo "это массив\n";
} else {
echo "это не массив\n";
}
?>(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Для этих правил здесь приведены несколько важных определений:
Это идентификатор без разделителя пространств имён, например, Foo
Это идентификатор с разделителем пространств имён, например, Foo\Bar
Это идентификатор с разделителем пространств имён, который начинается с разделителя пространств имён,
например, \Foo\Bar. Пространство имён \Foo
также является абсолютным именем.
Это идентификатор, начинающийся с namespace, такой как
namespace\Foo\Bar.
Имена разрешаются согласно следующим правилам:
\A\B разрешается в A\B.
namespace
на текущее пространство имён. Если имя встречается в глобальном пространстве имён,
префикс namespace\ просто удаляется. К примеру
namespace\A внутри пространства имён X\Y разрешается
в X\Y\A. То же самое имя в глобальном пространстве имён разрешается в
A.
A\B\C
импортировано как C, тогда имя C\D\E преобразуется в
A\B\C\D\E.
C\D\E внутри пространства имён A\B,
преобразуется в A\B\C\D\E.
use A\B\C;, использование new C()
разрешается как A\B\C(). Аналогично, после
use function A\B\fn;, использование fn() разрешается
как A\B\fn.
new C() внутри пространства имён A\B разрешаются как
A\B\C.
A\B,
вызывающий функцию foo(), разрешается так:
A\B\foo().
foo().
Пример #1 Примеры разрешения имён
<?php
namespace A;
use B\D, C\E as F;
// вызовы функций
foo(); // сперва пытается вызвать "foo", определённую в пространстве имён "A",
// затем вызывает глобальную функцию "foo"
\foo(); // вызывает функцию "foo", определённую в глобальном пространстве
my\foo(); // вызывает функцию "foo", определённую в пространстве "A\my"
F(); // сперва пытается вызвать "F", определённую в пространстве имён "A",
// затем вызывает глобальную функцию "F"
// ссылки на классы
new B(); // создаёт объект класса "B", определённого в пространстве имён "A".
// если не найден, то пытается сделать автозагрузку класса "A\B"
new D(); // используя правила импорта, создаёт объект класса "D", определённого в пространстве имён "B"
// если не найден, то пытается сделать автозагрузку класса "B\D"
new F(); // используя правила импорта, создаёт объект класса "E", определённого в пространстве имён "C"
// если не найден, то пытается сделать автозагрузку класса "C\E"
new \B(); // создаёт объект класса "B", определённого в глобальном пространстве,
// если не найден, то пытается сделать автозагрузку класса "B"
new \D(); // создаёт объект класса "D", определённого в глобальном пространстве,
// если не найден, то пытается сделать автозагрузку класса "D"
new \F(); // создаёт объект класса "F", определённого в глобальном пространстве,
// если не найден, то пытается сделать автозагрузку класса "F"
// статические методы/функции пространства имён из другого пространства имён
B\foo(); // вызывает функцию "foo" из пространства имён "A\B"
B::foo(); // вызывает метод "foo" из класса "B", определённого в пространстве имён "A"
// если класс "A\B" не найден, то пытается сделать автозагрузку класса "A\B"
D::foo(); // используя правила импорта, вызывает метод "foo" класса "D", определённого в пространстве имён "B"
// если класс "B\D" не найден, то пытается сделать автозагрузку класса "B\D"
\B\foo(); // вызывает функцию "foo" из пространства имён "B"
\B::foo(); // вызывает метод "foo" класса "B" из глобального пространства
// если класс "B" не найден, то пытается сделать автозагрузку класса "B"
// статические методы/функции пространства имён из текущего пространства имён
A\B::foo(); // вызывает метод "foo" класса "B" из пространства имён "A\A"
// если класс "A\A\B" не найден, то пытается сделать автозагрузку класса "A\A\B"
\A\B::foo(); // вызывает метод "foo" класса "B" из пространства имён "A"
// если класс "A\B" не найден, то пытается сделать автозагрузку класса "A\B"
?>(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Этот список вопросов разделён на две части: общие вопросы и некоторые особенности реализации, которые полезны для более полного понимания.
Сперва, общие вопросы.
\my\name или \name
преобразуется?
my\name преобразуется?
name преобразуется?
name преобразуется?
Некоторые детали реализации пространств имён, которые полезно понимать.
Нет. Пространства имён не оказывают никакого влияния ни на какой существующий код ни в каком виде или на любой написанный код, который не содержит пространств имён. Вы можете написать такой код, если желаете:
Пример #1 Доступ к глобальным классам вне пространства имён
<?php
$a = new \stdClass;
?>Это функционально эквивалентно следующему:
Пример #2 Доступ к глобальным классам вне пространства имён
<?php
$a = new stdClass;
?>
Пример #3 Доступ ко внутренним классам в пространствах имён
<?php
namespace foo;
$a = new \stdClass;
function test(\ArrayObject $parameter_type_example = null) {}
$a = \DirectoryIterator::CURRENT_AS_FILEINFO;
// расширение внутреннего или глобального класса
class MyException extends \Exception {}
?>
Пример #4 Доступ ко внутренним классам, функциям или константам в пространствах имён
<?php
namespace foo;
class MyClass {}
// использование класса из текущего пространства имен в качестве типа параметра
function test(MyClass $parameter_type_example = null) {}
// другой способ использовать класс из текущего пространства имен в качестве типа параметра
function test(\foo\MyClass $parameter_type_example = null) {}
// расширение класса из текущего пространства имён
class Extended extends MyClass {}
// доступ к глобальной функции
$a = \globalfunc();
// доступ к глобальной константе
$b = \INI_ALL;
?>\my\name или \name
преобразуется?
Имена, которые начинаются с \ всегда преобразуются к тому как
они выглядят, т.е. \my\name - это на самом деле my\name,
и \Exception - это Exception.
Пример #5 Абсолютные имена
<?php
namespace foo;
$a = new \my\name(); // создаёт экземпляр класса "my\name"
echo \strlen('hi'); // вызывает функцию "strlen"
$a = \INI_ALL; // переменной $a присваивается значение константы "INI_ALL"
?>my\name преобразуется?
Имена, которые содержат обратный слеш, но не начинаются с него, такие как
my\name могут быть преобразованы двумя различными способами.
Если присутствует
импортирующее выражение, которое создаёт синоним my другого имени, то
этот синоним применяется к my в my\name.
В ином случае, текущее имя пространства имён становится префиксом к my\name.
Пример #6 Полные имена
<?php
namespace foo;
use blah\blah as foo;
$a = new my\name(); // создаёт экземпляр класса "foo\my\name"
foo\bar::name(); // вызывает статический метод "name" в классе "blah\blah\bar"
my\bar(); // вызывает функцию "foo\my\bar"
$a = my\BAR; // присваивает переменной $a значение константы "foo\my\BAR"
?>name преобразуется?
Имена классов, которые не содержат обратный слеш, такие как
name могут быть преобразованы двумя различными способами.
Если присутствует
импортирующее выражение, которое создаёт синоним name другого имени, то
применяется этот синоним.
В ином случае, текущее имя пространства имён становится префиксом к name.
Пример #7 Неполные имена классов
<?php
namespace foo;
use blah\blah as foo;
$a = new name(); // создаёт экземпляр класса "foo\name"
foo::name(); // вызывает статический метод "name" в классе "blah\blah"
?>name преобразуется?
Имена функций или констант, которые не содержат обратного слеша, такие как
name могут быть преобразованы двумя различными способами.
Сперва, текущее имя пространства имён становится префиксом к name.
Затем, если константа или функция name не существует
в текущем пространстве имён, используется глобальная константа или функция name,
если она существует.
Пример #8 Неполные имена функций или констант
<?php
namespace foo;
use blah\blah as foo;
const FOO = 1;
function my() {}
function foo() {}
function sort(&$a)
{
\sort($a); // вызывает глобальную функцию "sort"
$a = array_flip($a);
return $a;
}
my(); // вызывает "foo\my"
$a = strlen('hi'); // вызывает глобальную функцию "strlen", потому что "foo\strlen" не существует
$arr = array(1,3,2);
$b = sort($arr); // вызывает функцию "foo\sort"
$c = foo(); // вызывает функцию "foo\foo" - импорт не применяется
$a = FOO; // присваивает переменной $a значение константы "foo\FOO" - импорт не применяется
$b = INI_ALL; // присваивает переменной $b значение глобальной константы "INI_ALL"
?>Следующие комбинации скриптов допустимы:
file1.php
<?php
namespace my\stuff;
class MyClass {}
?>another.php
<?php
namespace another;
class thing {}
?>file2.php
<?php
namespace my\stuff;
include 'file1.php';
include 'another.php';
use another\thing as MyClass;
$a = new MyClass; // создаёт экземпляр класса "thing" из пространства имён "another"
?>
Конфликт имён отсутствует даже несмотря на то, что класс MyClass существует
внутри пространства имён my\stuff, потому что определение MyClass
находится в отдельном файле. Однако следующий пример приводит к фатальной ошибке с конфликтом
имён, потому что класс MyClass определён в том же файле, где находится оператор use.
<?php
namespace my\stuff;
use another\thing as MyClass;
class MyClass {} // фатальная ошибка: MyClass конфликтует с выражением импорта
$a = new MyClass;
?>PHP не позволяет вложение пространств имён одно в другое
<?php
namespace my\stuff {
namespace nested {
class foo {}
}
}
?><?php
namespace my\stuff\nested {
class foo {}
}
?>Очень важно представлять это, потому что обратный слеш используется как экранирующий символ внутри строк. Он всегда должен быть продублирован, когда используется внутри строки, иначе появляется риск возникновения неумышленных последствий:
Пример #9 Подводные камни при использовании имени пространства имён внутри строки с двойными кавычками
<?php
$a = "dangerous\name"; // \n - это переход на новую строку внутри строки с двойными кавычками!
$obj = new $a;
$a = 'not\at\all\dangerous'; // а тут нет проблем.
$obj = new $a;
?>
Любая неопределённая константа, являющаяся неполным именем, как FOO, будет
приводить к выводу сообщения о том, что PHP предположил, что FOO было значение
константы. Любая константа, с полным или абсолютным именем, которая содержит
символ обратного слеша будет приводить к фатальной ошибке, если не будет найдена.
Пример #10 Неопределённые константы
<?php
namespace bar;
$a = FOO; // выводит предупреждение: undefined constants "FOO" assumed "FOO";
$a = \FOO; // фатальная ошибка: undefined namespace constant FOO
$a = Bar\FOO; // фатальная ошибка: undefined namespace constant bar\Bar\FOO
$a = \Bar\FOO; // фатальная ошибка: undefined namespace constant Bar\FOO
?>Любая попытка определить константу пространства имён, которая совпадает с названиями специальных встроенных констант, приведёт к фатальной ошибке.
Пример #11 Неопределённые константы
<?php
namespace bar;
const NULL = 0; // Фатальная ошибка;
const true = 'stupid'; // также фатальная ошибка;
// и т.д.
?>(PHP 8 >= 8.1.0)
Перечисления или "Enums" позволяют разработчику определять настраиваемый тип, который ограничен одним из дискретного числа возможных значений. Это может быть особенно полезно при определении модели предметной области, поскольку позволяет "сделать неверные состояния недопустимыми".
Перечисления представлены во многих языках программирования с множеством различных функций. В PHP перечисления - это особый вид объектов. Сами перечисления являются классами и все его возможные случаи являются объектами одного экземпляра этого класса. Это означает, что варианты перечисления являются допустимыми объектами и могут использоваться везде, где можно использовать объект, включая проверки типов.
Самым популярным примером перечислений является встроенный логический тип,
который представляет собой перечислимый тип с допустимыми значениями true и false.
Перечисления позволяют разработчикам определять свои собственные произвольно надёжные перечисления.
Перечисления похожи на классы и используют те же пространства имён, что и классы, интерфейсы и трейты. Они также могут быть загружены автоматически. Перечисления определяют новый тип, который имеет фиксированное ограниченное количество возможных допустимых значений.
<?php
enum Suit
{
case Hearts;
case Diamonds;
case Clubs;
case Spades;
}
?>
Это объявление создаёт новый перечислимый тип с именем Suit, у которого четыре и только четыре
допустимых значения: Suit::Hearts, Suit::Diamonds,
Suit::Clubs и Suit::Spades.
Переменным может быть присвоено одно из этих допустимых значений. Тип функции может быть проверен на соответствие типу перечисления
и в этом случае могут быть переданы только значения этого типа.
<?php
function pick_a_card(Suit $suit) { ... }
$val = Suit::Diamonds;
// OK
pick_a_card($val);
// OK
pick_a_card(Suit::Clubs);
// TypeError: pick_a_card(): Argument #1 ($suit) must be of type Suit, string given
pick_a_card('Spades');
?>
Перечисление может иметь ноль или более вариантов case без ограничений.
Перечисление без вариантов синтаксически корректно, хотя и бесполезно.
Для вариантов перечисления применяются те же правила синтаксиса, что и для любой метки в PHP, смотрите Константы.
По умолчанию варианты не поддерживаются скалярным значением. То есть Suit::Hearts
не равно "0". Вместо этого каждый вариант поддерживается одноэлементным объектом с таким именем.
Это означает, что:
<?php
$a = Suit::Spades;
$b = Suit::Spades;
$a === $b; // true
$a instanceof Suit; // true
?>
Это также означает, что значения перечисления никогда не являются < или >
друг с другом, поскольку эти сравнения не имеют смысла для объектов.
Сравнения всегда будут возвращать false при работе с вариантами перечисления.
Тип варианта без связанных данных называется "Чистый вариант". Перечисление, которое содержит только чистые варианты, называется чистым перечислением.
Все чистые варианты реализованы как экземпляры своего типа перечисления. Тип перечисления внутренне представлен как класс.
У всех обращений есть свойство, доступное только для чтения, name,
которое является именем самого варианта, чувствительным к регистру.
<?php
print Suit::Spades->name;
// prints "Spades"
?>Также можно использовать функции defined() и constant() для проверки существования или чтения регистра перечисления, если имя получено динамически. Однако это не рекомендуется, так как для большинства случаев использования перечислений лучше использовать Типизированные перечисления.
По умолчанию у вариантов перечислений нет скалярного эквивалента. Это просто одноэлементные объекты. Однако существует множество случаев, когда варианты перечислений должны иметь возможность обращаться к базе данных или аналогичному хранилищу данных и обратно, поэтому полезно иметь встроенный скалярный (и, следовательно, тривиально сериализуемый) эквивалент, определённый внутренне.
Чтобы определить скалярный эквивалент для перечислений, используйте следующий синтаксис:
<?php
enum Suit: string
{
case Hearts = 'H';
case Diamonds = 'D';
case Clubs = 'C';
case Spades = 'S';
}
?>Вариант, имеющий скалярный эквивалент, называется типизированным, поскольку он "поддерживается" более простым значением. Перечисление, у которого все варианты типизированные, называется "типизированным перечислением". Типизированное перечисление может содержать только типизированные варианты. Чистое перечисление может содержать только чистые варианты.
Типизированное перечисление может поддерживаться типами int или string
и данное перечисление поддерживает только один тип за раз (то есть не допускается объединение int|string).
Если перечисление помечено как имеющее скалярный эквивалент, тогда все варианты должны иметь определённый явно уникальный скалярный эквивалент.
Не существует автоматически генерируемых скалярных эквивалентов (например, последовательных целых чисел).
Типизированные варианты должны быть уникальными; два варианта типизированного перечисления не могут иметь одного и того же скалярного эквивалента.
Однако константа может относиться к варианту, фактически создавая псевдоним.
Смотрите Константы перечислений.
Эквивалентные значения должны быть строками или строковыми выражениями.
Константы и постоянные выражения не поддерживаются. То есть 1 + 1 разрешено,
а 1 + SOME_CONST - нет.
У типизированных вариантов есть дополнительное свойство, доступное только для чтения, value,
которое является значением, указанным в определении.
<?php
print Suit::Clubs->value;
// Выведет "C"
?>
Чтобы сделать свойство value доступным только для чтения, нельзя назначить переменную в качестве ссылки на неё.
То есть следующий код выдаст ошибку:
<?php
$suit = Suit::Clubs;
$ref = &$suit->value;
// Error: Cannot acquire reference to property Suit::$value
?>Типизированные перечисления реализуют внутренний интерфейс BackedEnum, который предоставляет два дополнительных метода:
from(int|string): self возьмёт скаляр и вернёт соответствующий вариант перечисления.
Если вариант не найден, метод выдаст ValueError.
Это полезно в тех случаях, когда входной скаляр является доверенным,
а отсутствие значения перечисления следует рассматривать как ошибку остановки приложения.
tryFrom(int|string): ?self возьмёт скаляр и вернёт соответствующий вариант перечисления.
Если вариант не найден, метод вернёт null.
Это полезно в тех случаях, когда входной скаляр не является доверенным и вызывающая функция
хочет реализовать свою собственную обработку ошибок или логику значения по умолчанию.
Методы from() и tryFrom() следуют стандартным правилам
слабой/строгой типизации. В режиме слабой типизации допустима передача целого числа или строки
и система соответствующим образом преобразует значение.
Передача числа с плавающей точкой также будет работать с принудительным преобразованием.
В режиме строгой типизации передача целого числа в from() в перечислении
со строковой типизацией (или наоборот) приведёт к TypeError,
как и передача числа с плавающей точкой при любых обстоятельствах.
Все остальные типы параметров вызовут ошибку TypeError в обоих режимах.
<?php
$record = get_stuff_from_database($id);
print $record['suit'];
$suit = Suit::from($record['suit']);
// Недопустимые данные выдают ошибку ValueError: "X" не является допустимым скалярным значением для перечисления "Suit"
print $suit->value;
$suit = Suit::tryFrom('A') ?? Suit::Spades;
// Недопустимые данные возвращают значение null, поэтому вместо этого используется Suit::Spades.
print $suit->value;
?>
Ручное определение метода from() или tryFrom() в типизированных перечислениях
приведёт к фатальной ошибке.
Перечисления (как чистые перечисления, так и типизированные перечисления) могут содержать методы и могут реализовывать интерфейсы. Если перечисление реализует интерфейс, то любая проверка типа для этого интерфейса также будет принимать все варианты этого перечисления.
<?php
interface Colorful
{
public function color(): string;
}
enum Suit implements Colorful
{
case Hearts;
case Diamonds;
case Clubs;
case Spades;
// Выполняет интерфейсный контракт.
public function color(): string
{
return match($this) {
Suit::Hearts, Suit::Diamonds => 'Красный',
Suit::Clubs, Suit::Spades => 'Чёрный'
};
}
// Не является частью интерфейса; хорошо.
public function shape(): string
{
return "Rectangle";
}
}
function paint(Colorful $c) { ... }
paint(Suit::Clubs); // Работает
print Suit::Diamonds->shape(); // выведет "Rectangle"
?>
В этом примере у всех четырёх экземпляров Suit есть два метода:
color() и shape().
Что касается вызывающего кода и проверки типов, они ведут себя точно так же, как и любой другой экземпляр объекта.
В типизированных перечислениях объявление интерфейса идёт после объявления типа.
<?php
interface Colorful
{
public function color(): string;
}
enum Suit: string implements Colorful
{
case Hearts = 'H';
case Diamonds = 'D';
case Clubs = 'C';
case Spades = 'S';
// Выполняет интерфейсный контракт.
public function color(): string
{
return match($this) {
Suit::Hearts, Suit::Diamonds => 'Красный',
Suit::Clubs, Suit::Spades => 'Чёрный'
};
}
}
?>
Внутри метода определяется переменная $this, которая ссылается на экземпляр варианта.
Методы могут быть сколь угодно сложными, но на практике обычно возвращают статическое значение
или match для $this,
чтобы предоставить разные результаты для разных случаев.
Обратите внимание, что в этом случае было бы лучше также определить тип перечисления SuitColor
со значениями Red и Black и вернуть его вместо этого.
Однако это усложнило бы этот пример.
Вышеупомянутая иерархия логически похожа на следующую структуру классов (хотя это не фактический исполняемый код):
<?php
interface Colorful
{
public function color(): string;
}
final class Suit implements UnitEnum, Colorful
{
public const Hearts = new self('Hearts');
public const Diamonds = new self('Diamonds');
public const Clubs = new self('Clubs');
public const Spades = new self('Spades');
private function __construct(public readonly string $name) {}
public function color(): string
{
return match($this) {
Suit::Hearts, Suit::Diamonds => 'Красный',
Suit::Clubs, Suit::Spades => 'Чёрный'
};
}
public function shape(): string
{
return "Прямоугольник";
}
public static function cases(): array
{
// Недопустимый метод, поскольку определение метода cases() в перечислениях вручную запрещено.
// Смотрите также раздел "Список значений".
}
}
?>Методы могут быть общедоступными, закрытыми или защищёнными, хотя на практике закрытые и защищённые эквивалентны, поскольку наследование не допускается.
Перечисления также могут иметь статические методы. Использование статических методов в самом перечислении в первую очередь предназначено для альтернативных конструкторов. Например:
<?php
enum Size
{
case Small;
case Medium;
case Large;
public static function fromLength(int $cm): static
{
return match(true) {
$cm < 50 => static::Small,
$cm < 100 => static::Medium,
default => static::Large,
};
}
}
?>Статические методы могут быть общедоступными, закрытыми или защищёнными, хотя на практике закрытые и защищённые эквивалентны, поскольку наследование не допускается.
Перечисления могут содержать константы, которые могут быть общедоступными, закрытыми или защищёнными, хотя на практике закрытые и защищённые эквивалентны, поскольку наследование не допускается.
Константа перечисления может относиться к варианту перечисления:
<?php
enum Size
{
case Small;
case Medium;
case Large;
public const Huge = self::Large;
}
?>
Перечисления могут использовать трейты, которые будут вести себя так же, как и классы.
Предостережение заключается в том, что трейты, используемые (use)
в перечислении не должны содержать свойств.
Они могут включать только методы и статические методы. Трейт со свойствами приведёт к фатальной ошибке.
<?php
interface Colorful
{
public function color(): string;
}
trait Rectangle
{
public function shape(): string {
return "Прямоугольник";
}
}
enum Suit implements Colorful
{
use Rectangle;
case Hearts;
case Diamonds;
case Clubs;
case Spades;
public function color(): string
{
return match($this) {
Suit::Hearts, Suit::Diamonds => 'Красный',
Suit::Clubs, Suit::Spades => 'Чёрный',
};
}
}
?>Поскольку варианты представлены как константы в самом перечислении, они могут использоваться как статические значения в большинстве константных выражений: значения по умолчанию для свойств, значения по умолчанию для статических переменных, значения по умолчанию для параметров, глобальные значения и значения констант класса. Они не могут использоваться в других значениях варианта перечисления, но обычные константы могут относиться к варианту перечисления.
Однако неявные вызовы магических методов, таких как ArrayAccess в перечислениях, не допускаются в статических или константных определениях, поскольку мы не можем абсолютно гарантировать, что результирующее значение будет детерминированным или что вызов метода не будет иметь побочных эффектов. Вызовы функций, вызовы методов и доступ к свойствам по-прежнему являются недопустимыми операциями в постоянных выражениях.
<?php
// Это полностью законное определение перечисления.
enum Direction implements ArrayAccess
{
case Up;
case Down;
public function offsetGet($val) { ... }
public function offsetExists($val) { ... }
public function offsetSet($val) { throw new Exception(); }
public function offsetUnset($val) { throw new Exception(); }
}
class Foo
{
// Это разрешено.
const Bar = Direction::Down;
// Это запрещено, так как не может быть детерминированным.
const Bar = Direction::Up['short'];
// Fatal error: Cannot use [] on enums in constant expression
}
// Это совершенно законно, потому что это не постоянное выражение.
$x = Direction::Up['short'];
?>Хотя перечисления построены на классах и объектах, они не поддерживают все функциональные возможности, связанные с объектами. В частности, вариантам перечислений запрещено иметь состояние.
Доступны следующие функциональные возможности объекта, которые ведут себя так же, как и для любого другого объекта:
TARGET_CLASS включает сами перечисления.
Целевой фильтр TARGET_CLASS_CONST включает варианты перечислений.
__CLASS__ и __FUNCTION__ ведут себя как обычно.
Магическая константа ::class для типа перечисления оценивает имя типа,
включая любое пространство имён, точно так же, как объект.
Магическая константа ::class в экземпляре варианта также оценивается как тип перечисления,
поскольку она является экземпляром этого типа.
Кроме того, варианты перечисления не могут быть созданы напрямую с помощью new или с помощью
ReflectionClass::newInstanceWithoutConstructor(). Оба способа приведут к ошибке.
<?php
$clovers = new Suit();
// Error: Cannot instantiate enum Suit
$horseshoes = (new ReflectionClass(Suit::class))->newInstanceWithoutConstructor()
// Error: Cannot instantiate enum Suit
?>
И чистые перечисления, и типизированные перечисления реализуют внутренний интерфейс
с именем UnitEnum.
UnitEnum включает статический метод cases().
cases() возвращает упакованный массив всех определённых вариантов в порядке объявления.
<?php
Suit::cases();
// Produces: [Suit::Hearts, Suit::Diamonds, Suit::Clubs, Suit::Spades]
?>
Ручное определение метода cases() в перечислении приведёт к фатальной ошибке.
Перечисления сериализуются иначе, чем объекты. В частности, у них есть новый код сериализации,
"E", который указывает имя варианта перечисления.
Затем процедура десериализации может использовать это для установки переменной в существующее одноэлементное значение.
Это гарантирует, что:
<?php
Suit::Hearts === unserialize(serialize(Suit::Hearts));
print serialize(Suit::Hearts);
// E:11:"Suit:Hearts";
?>
При десериализации, если не удаётся найти перечисление и сопоставить с соответствующим сериализованным значением,
будет выдано предупреждение и будет возвращено false.
Если чистое перечисление сериализуется в JSON, будет выдана ошибка. Если типизированное перечисление сериализуется в JSON, оно будет представлено только его скаляром значений в соответствующем типе. Поведение обоих способов может быть изменено путём реализации JsonSerializable.
Для print_r() вывод варианта перечисления немного отличается от объектов, чтобы свести к минимуму путаницу.
<?php
enum Foo {
case Bar;
}
enum Baz: int {
case Beep = 5;
}
print_r(Foo::Bar);
print_r(Baz::Beep);
/* Выводит
Foo Enum (
[name] => Bar
)
Baz Enum:int {
[name] => Beep
[value] => 5
}
*/
?>У классов есть контракты на их методы:
<?php
class A {}
class B extends A {}
function foo(A $a) {}
function bar(B $b) {
foo($b);
}
?>Этот код безопасен для типов, поскольку B следует контракту A, и, благодаря магии ковариантности и контравариантности, любое ожидание, которое может быть у человека в отношении методов, будет сохранено, за исключением исключений.
У перечислений есть контракты их варианты, а не методы:
<?php
enum ErrorCode {
case SOMETHING_BROKE;
}
function quux(ErrorCode $errorCode)
{
// Кажется, что этот код охватывает все варианты
match ($errorCode) {
ErrorCode::SOMETHING_BROKE => true,
}
}
?>
Оператор match в функции quux может быть статически проанализирован,
чтобы охватить все случаи в ErrorCode.
Но представьте, что было бы разрешено расширять перечисления:
<?php
// Экспериментальный код, в котором перечисления не являются конечными.
// Обратите внимание, что это не будет работать в PHP.
enum MoreErrorCode extends ErrorCode {
case PEBKAC;
}
function fot(MoreErrorCode $errorCode) {
quux($errorCode);
}
fot(MoreErrorCode::PEBKAC);
?>Согласно обычным правилам наследования, класс, расширяющий другой класс, пройдёт проверку типа.
Проблема заключается в том, что оператор match в quux() уже не охватывает все случаи.
Поскольку оно не знает о MoreErrorCode::PEBKAC, match выбросит исключение.
Из-за этого перечисления являются окончательными и не могут быть расширены.
Пример #1 Основные ограниченные значения
<?php
enum SortOrder
{
case Asc;
case Desc;
}
function query($fields, $filter, SortOrder $order = SortOrder::Asc) { ... }
?>
Функция query() теперь может безопасно работать,
зная, что $order гарантированно будет либо SortOrder::Asc,
либо SortOrder::Desc.
Любое другое значение привело бы к TypeError,
поэтому дальнейшая проверка ошибок или тестирование не требуется.
Пример #2 Расширенные эксклюзивные значения
<?php
enum UserStatus: string
{
case Pending = 'P';
case Active = 'A';
case Suspended = 'S';
case CanceledByUser = 'C';
public function label(): string
{
return match($this) {
static::Pending => 'В ожидании',
static::Active => 'Активный',
static::Suspended => 'Приостановленный',
static::CanceledByUser => 'Отменено пользователем',
};
}
}
?>
В этом примере статус пользователя может быть одним из следующих:
UserStatus::Pending,
UserStatus::Active, UserStatus::Suspended или
UserStatus::CanceledByUser.
Функция может ввести параметр UserStatus и затем принять только эти четыре значения, точка.
У всех четырёх значений есть метод label(), который возвращает читаемую строку.
Эта строка не зависит от скалярной эквивалентной строки "machine name", которую можно использовать,
например, в поле базы данных или поле выбора HTML.
<?php
foreach (UserStatus::cases() as $case) {
printf('<option value="%s">%s</option>\n', $case->value, $case->label());
}
?>К сожалению, как бы мы ни были аккуратны при написании кода, ошибки являются частью нашей жизни. PHP будет сообщать об ошибках, предупреждениях и уведомлениях о самых распространённых проблемах кода и времени исполнения, но знания, как разобраться в ошибках и как их обработать, могут сильно упростить процесс отладки.
PHP сообщает об ошибках в ответ на некоторые внутренние ошибочные обстоятельства. Они могут быть использованы для уведомления о разных состояниях, а также могут выводиться на экран и записываться в логи по желанию.
Каждая ошибка, генерируемая PHP, обязательно содержит информацию о своём типе. В этом списке перечислены все типы ошибок, а также описания их поведений и провоцирующие их причины.
PHP, по умолчанию, может обрабатывать любые ошибки в соответствии со своей
конфигурацией, если обработчик ошибок не установлен. О каких ошибках сообщать
и какие ошибки игнорировать указывается в параметре error_reporting
конфигурации php.ini, или во время исполнения программы с помощью вызова
error_reporting(). Настоятельно рекомендуется заранее конфигурировать php.ini,
так как некоторые ошибки могут произойти до начала выполнения вашего скрипта.
На стадии разработки, обязательно настройте параметр
error_reporting
на значение E_ALL, так как вам необходимо знать обо всех ошибках
для их решения на этой стадии. Когда продукт готов, вы можете изменить значение на менее
подробное, вроде E_ALL & ~E_NOTICE & ~E_DEPRECATED,
но во многих случаях значение E_ALL также желательно, так как
оно может предупреждать заранее о других возможных ошибках.
Дальнейшая работа PHP с появившимися ошибками зависит от двух других параметров в php.ini.
Параметр display_errors
определяет, включать ли данные ошибки в вывод скрипта или нет. Когда продукт готов,
обязательно выключите этот параметр, так как в описании ошибки может содержаться
конфиденциальная информация, вроде паролей базы данных. Во время разработки данный
параметр лучше включить для решения проблем, провоцирующих ошибки.
Кроме отображения ошибок, их можно записывать в лог с помощью включённого параметра
log_errors.
Файл лога указывается в параметре error_log.
Данная функция незаменима на стадии конечного продукта, так как
позволяет видеть информацию об ошибках и составлять основанные на них
отчёты вдали от глаз пользователя.
Если вас не устраивает работа предустановленного обработчика ошибок, вы также можете обрабатывать множество видов ошибки с помощью своего обработчика, который можно установить вызовом функции set_error_handler(). Некоторые ошибки не могут обрабатываться пользовательским обработчиком, но те, которые могут, обрабатываются по вашему желанию: например, ваш скрипт может выдавать пользователю любую отдельную страницу ошибки, а подробную информацию записывать в лог или отсылать по почте.
В PHP 7 механизм сообщения об ошибках был сильно изменён. Традиционное оповещение об ошибке в PHP 5 было заменено новым механизмом, в котором большинство ошибок вызываются с помощью исключений класса Error.
Как и обычные исключения, исключения Error
вызываются до появления первого соответствующего блока
catch.
Если соответствующие блоки не предусмотрены,
то будет вызван любой обработчик исключений, установленный с помощью
set_exception_handler().
В случае отсутствия обработчика по умолчанию, исключение будет конвертировано
в фатальную ошибку и будет обработано как традиционная ошибка.
Поскольку класс Error не наследуется от класса Exception,
блок catch (Exception $e) { ... } для обработки неперехваченных исключений
PHP 5 не может перехватить исключения Error.
Для их перехвата используйте блок catch (Error $e) { ... } или
установите обработчик исключений с помощью set_exception_handler().
В PHP реализована модель исключений, аналогичная тем, что используются в других языках программирования.
Исключение в PHP может быть выброшено (throw) и поймано (catch).
Код может быть заключён в блок try, чтобы облегчить обработку потенциальных исключений.
У каждого блока try должен быть как минимум один соответствующий блок catch или finally.
Если выброшено исключение, а в текущей области видимости функции нет блока catch,
исключение будет "подниматься" по стеку вызовов к вызывающей функции, пока не найдёт подходящий блок catch.
Все блоки finally, которые встретятся на этом пути, будут выполнены.
Если стек вызовов разворачивается до глобальной области видимости, не встречая подходящего блока catch,
программа завершается с неисправимой ошибкой, если не был установлен глобальный обработчик исключений.
Выброшенный объект должен наследовать (instanceof) интерфейс Throwable.
Попытка выбросить объект, который таковым не является, приведёт к неисправимой ошибке PHP.
Начиная с PHP 8.0.0, ключевое слово throw является выражением и может быть использовано
в любом контексте выражения. В предыдущих версиях оно было утверждением
и должно было располагаться в отдельной строке.
catch
Блок catch определяет, как реагировать на выброшенное исключение.
Блок catch определяет один или несколько типов исключений или ошибок, которые он может обработать,
и, по желанию, переменную, которой можно присвоить исключение
(указание переменной было обязательно до версии PHP 8.0.0).
Первый блок catch, с которым столкнётся выброшенное исключение или ошибка
и соответствует типу выброшенного объекта, обработает объект.
Несколько блоков catch могут быть использованы для перехвата различных классов исключений.
Нормальное выполнение (когда исключение не выброшено в блоке try)
будет продолжаться после последнего блока catch, определённого в последовательности.
Исключения могут быть выброшены (throw) (или повторно выброшены) внутри блока catch.
В противном случае выполнение будет продолжено после блока catch, который был вызван.
При возникновении исключения, код, следующий за утверждением, не будет выполнен,
а PHP попытается найти первый подходящий блок catch.
Если исключение не поймано, будет выдана неисправимая ошибка PHP
с сообщением "Uncaught Exception ...",
если только обработчик не был определён с помощью функции set_exception_handler().
Начиная с версии PHP 7.1.0, в блоке catch можно указывать несколько исключений,
используя символ |. Это полезно, когда разные исключения
из разных иерархий классов обрабатываются одинаково.
Начиная с версии PHP 8.0.0, имя переменной для пойманного исключения является необязательным.
Если оно не указано, блок catch будет выполнен,
но не будет иметь доступа к выброшенному объекту.
finally
Блок finally также может быть указан после или вместо блоков catch.
Код в блоке finally всегда будет выполняться после блоков try и catch,
независимо от того, было ли выброшено исключение
и до возобновления нормального выполнения.
Одно из заметных взаимодействий происходит между блоком finally и оператором return.
Если оператор return встречается внутри блоков try или catch, блок finally
всё равно будет выполнен. Более того, оператор return выполнится, когда встретится,
но результат будет возвращён после выполнения блока finally.
Кроме того, если блок finally также содержит оператор return,
возвращается значение из блока finally.
Если исключению разрешено распространяться на глобальную область видимости,
оно может быть перехвачено глобальным обработчиком исключений, если он установлен.
Функция set_exception_handler() может задать функцию,
которая будет вызвана вместо блока catch, если не будет вызван никакой другой блок.
Эффект по сути такой же, как если бы вся программа была обёрнута в блок try-catch
с этой функцией в качестве catch.
Замечание:
Внутренние функции PHP в основном используют отчёт об ошибках, только современные объектно-ориентированные модули используют исключения. Однако ошибки можно легко перевести в исключения с помощью класса ErrorException. Однако эта техника работает только с исправляемыми ошибками.
Пример #1 Преобразование отчётов об ошибках в исключения
<?php
function exceptions_error_handler($severity, $message, $filename, $lineno) {
throw new ErrorException($message, 0, $severity, $filename, $lineno);
}
set_error_handler('exceptions_error_handler');
?>
Библиотека Стандартная библиотека PHP (SPL) предоставляет большое количество встроенных исключений.
Пример #2 Выбрасывание исключения
<?php
function inverse($x) {
if (!$x) {
throw new Exception('Деление на ноль.');
}
return 1/$x;
}
try {
echo inverse(5) . "\n";
echo inverse(0) . "\n";
} catch (Exception $e) {
echo 'Выброшено исключение: ', $e->getMessage(), "\n";
}
// Продолжение выполнения
echo "Привет, мир\n";
?>Результат выполнения данного примера:
0.2 Выброшено исключение: Деление на ноль. Привет, мир
Пример #3 Обработка исключений с помощью блока finally
<?php
function inverse($x) {
if (!$x) {
throw new Exception('Деление на ноль.');
}
return 1/$x;
}
try {
echo inverse(5) . "\n";
} catch (Exception $e) {
echo 'Поймано исключение: ', $e->getMessage(), "\n";
} finally {
echo "Первый блок finally.\n";
}
try {
echo inverse(0) . "\n";
} catch (Exception $e) {
echo 'Поймано исключение: ', $e->getMessage(), "\n";
} finally {
echo "Второй блок finally.\n";
}
// Продолжение нормального выполнения
echo "Привет, мир\n";
?>Результат выполнения данного примера:
0.2 Первый блок finally. Поймано исключение: Деление на ноль. Второй блок finally. Привет, мир
Пример #4 Взаимодействие между блоками finally и return
<?php
function test() {
try {
throw new Exception('foo');
} catch (Exception $e) {
return 'catch';
} finally {
return 'finally';
}
}
echo test();
?>Результат выполнения данного примера:
finally
Пример #5 Вложенные исключения
<?php
class MyException extends Exception { }
class Test {
public function testing() {
try {
try {
throw new MyException('foo!');
} catch (MyException $e) {
// повторный выброс исключения
throw $e;
}
} catch (Exception $e) {
var_dump($e->getMessage());
}
}
}
$foo = new Test;
$foo->testing();
?>Результат выполнения данного примера:
string(4) "foo!"
Пример #6 Обработка нескольких исключений в одном блоке catch
<?php
class MyException extends Exception { }
class MyOtherException extends Exception { }
class Test {
public function testing() {
try {
throw new MyException();
} catch (MyException | MyOtherException $e) {
var_dump(get_class($e));
}
}
}
$foo = new Test;
$foo->testing();
?>Результат выполнения данного примера:
string(11) "MyException"
Пример #7 Пример блока catch без указания переменной
Допустимо начиная с PHP 8.0.0
<?php
class SpecificException extends Exception {}
function test() {
throw new SpecificException('Ой!');
}
try {
test();
} catch (SpecificException) {
print "Было поймано исключение SpecificException, но нам безразлично, что у него внутри.";
}
?>Пример #8 Throw как выражение
Допустимо начиная с PHP 8.0.0
<?php
function test() {
do_something_risky() or throw new Exception('Всё сломалось');
}
try {
test();
} catch (Exception $e) {
print $e->getMessage();
}
?>Определённый пользователем класс исключения должен быть определён, как класс расширяющий (наследующий) встроенный класс Exception. Ниже приведены методы и свойства класса Exception, доступные дочерним классам.
Пример #1 Встроенный класс Exception
<?php
class Exception implements Throwable
{
protected $message = 'Unknown exception'; // сообщение об исключении
private $string; // свойство для __toString
protected $code = 0; // пользовательский код исключения
protected $file; // файл, в котором было выброшено исключение
protected $line; // строка, в которой было выброшено исключение
private $trace; // трассировка вызовов методов и функций
private $previous; // предыдущее исключение, если исключение вложенное
public function __construct($message = '', $code = 0, Throwable $previous = null);
final private function __clone(); // запрещает клонирования исключения
final public function getMessage(); // сообщение исключения
final public function getCode(); // код исключения
final public function getFile(); // файл, где выброшено исключение
final public function getLine(); // строка, на которой выброшено исключение
final public function getTrace(); // массив backtrace()
final public function getPrevious(); // предыдущее исключение
final public function getTraceAsString(); // отформатированная строка трассировки
// Переопределяемый
public function __toString(); // отформатированная строка для отображения
}
?>Если класс, наследуемый от Exception переопределяет конструктор, необходимо вызвать в конструкторе parent::__construct(), чтобы быть уверенным, что все доступные данные были правильно присвоены. Метод __toString() может быть переопределён, чтобы обеспечить нужный вывод, когда объект преобразуется в строку.
Замечание:
Исключения нельзя клонировать. Попытка клонировать исключение приведёт к неисправимой ошибке
E_ERROR.
Пример #2 Наследование класса Exception
<?php
/**
* Определим свой класс исключения
*/
class MyException extends Exception
{
// Переопределим исключение так, что параметр message станет обязательным
public function __construct($message, $code = 0, Throwable $previous = null) {
// некоторый код
// убедитесь, что все передаваемые параметры верны
parent::__construct($message, $code, $previous);
}
// Переопределим строковое представление объекта.
public function __toString() {
return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
}
public function customFunction() {
echo "Мы можем определять новые методы в наследуемом классе\n";
}
}
/**
* Создадим класс для тестирования исключения
*/
class TestException
{
public $var;
const THROW_NONE = 0;
const THROW_CUSTOM = 1;
const THROW_DEFAULT = 2;
function __construct($avalue = self::THROW_NONE) {
switch ($avalue) {
case self::THROW_CUSTOM:
// Выбрасываем собственное исключение
throw new MyException('1 - неправильный параметр', 5);
break;
case self::THROW_DEFAULT:
// Выбрасываем встроеное исключение
throw new Exception('2 - недопустимый параметр', 6);
break;
default:
// Никаких исключений, объект будет создан.
$this->var = $avalue;
break;
}
}
}
// Пример 1
try {
$o = new TestException(TestException::THROW_CUSTOM);
} catch (MyException $e) { // Будет перехвачено
echo "Поймано собственное переопределённое исключение\n", $e;
$e->customFunction();
} catch (Exception $e) { // Будет пропущено
echo "Поймано встроенное исключение\n", $e;
}
// Отсюда будет продолжено выполнение программы
var_dump($o); // Null
echo "\n\n";
// Пример 2
try {
$o = new TestException(TestException::THROW_DEFAULT);
} catch (MyException $e) { // Тип исключения не совпадёт
echo "Поймано переопределённое исключение\n", $e;
$e->customFunction();
} catch (Exception $e) { // Будет перехвачено
echo "Перехвачено встроенное исключение\n", $e;
}
// Отсюда будет продолжено выполнение программы
var_dump($o); // Null
echo "\n\n";
// Пример 3
try {
$o = new TestException(TestException::THROW_CUSTOM);
} catch (Exception $e) { // Будет перехвачено
echo "Поймано встроенное исключение\n", $e;
}
// Продолжение исполнения программы
var_dump($o); // Null
echo "\n\n";
// Пример 4
try {
$o = new TestException();
} catch (Exception $e) { // Будет пропущено, т.к. исключение не выбрасывается
echo "Поймано встроенное исключение\n", $e;
}
// Продолжение выполнения программы
var_dump($o); // TestException
echo "\n\n";
?>(PHP 8 >= 8.1.0)
Файберы представляют собой прерываемые функции полного цикла. Файберы могут быть приостановлены из любого места цикла, приостанавливая выполнение в файбере до тех пор, пока файбер не будет возобновлён в будущем.
Файберы приостанавливают весь цикл выполнения, поэтому вызывающему функцию напрямую не нужно менять способ её вызова.
Выполнение может быть прервано в любом месте цикла с помощью метода Fiber::suspend() (то есть вызов Fiber::suspend() может находиться в глубоко вложенной функции или даже вообще не существовать).
В отличие от генераторов (Generator) без стека, у каждого объекта Fiber есть свой собственный стек вызовов, позволяющий приостанавливать их внутри глубоко вложенных вызовов функций. Функция, объявляющая точку прерывания (то есть вызов метода Fiber::suspend()), не должна изменять свой возвращаемый тип, в отличие от функции, использующей yield, который должен возвращать экземпляр Generator.
Файберы могут быть приостановлены при вызове любой функции, включая те, которые вызываются из виртуальной машины PHP, например, функции, предоставляемые array_map(), или методы, вызываемые foreach для объекта Iterator.
После приостановки выполнение файбера может быть возобновлено с любым значением с помощью метода Fiber::resume() или путём передачи исключения в файбер с помощью Fiber::throw(). Значение возвращается (или выбрасывается исключение) из метода Fiber::suspend().
Замечание: Из-за текущих ограничений невозможно переключать файбер в деструкторе объекта.
Пример #1 Простой пример
<?php
$fiber = new Fiber(function (): void {
$value = Fiber::suspend('fiber');
echo "Значение возобновлённого файбера: ", $value, PHP_EOL;
});
$value = $fiber->start();
echo "Значение приостановленного файбера: ", $value, PHP_EOL;
$fiber->resume('test');
?>Результат выполнения данного примера:
Значение приостановленного файбера: fiber Значение возобновлённого файбера: test
(PHP 5 >= 5.5.0, PHP 7, PHP 8)
Генераторы предоставляют лёгкий способ реализации простых итераторов без использования дополнительных ресурсов или сложностей, связанных с реализацией класса, реализующего интерфейс Iterator.
Генератор позволяет вам писать код, использующий foreach для перебора набора данных без необходимости создания массива в памяти, что может привести к превышению лимита памяти, либо потребует довольно много времени для его создания. Вместо этого, вы можете написать функцию-генератор, которая, по сути, является обычной функцией, за исключением того, что вместо возврата единственного значения, генератор может возвращать (yield) столько раз, сколько необходимо для генерации значений, позволяющих перебрать исходный набор данных.
Наглядным примером вышесказанного может послужить использование функции range() как генератора. Стандартная функция range() генерирует массив, состоящий из значений, и возвращает его, что может привести к генерации огромных массивов данных. Например, вызов range(0, 1000000) приведёт к использованию более 100 МБ оперативной памяти.
В качестве альтернативы мы можем создать генератор xrange(),
который использует память только для создания объекта
Iterator и сохранения текущего состояния, что потребует
не больше 1 килобайта памяти.
Пример #1 Реализация range() как генератора
<?php
function xrange($start, $limit, $step = 1) {
if ($start <= $limit) {
if ($step <= 0) {
throw new LogicException('Шаг должен быть положительным');
}
for ($i = $start; $i <= $limit; $i += $step) {
yield $i;
}
} else {
if ($step >= 0) {
throw new LogicException('Шаг должен быть отрицательным');
}
for ($i = $start; $i >= $limit; $i += $step) {
yield $i;
}
}
}
/* Обратите внимание, что и range() и xrange() дадут один и тот же вывод */
echo 'Нечётные однозначные числа с помощью range(): ';
foreach (range(1, 9, 2) as $number) {
echo "$number ";
}
echo "\n";
echo 'Нечётные однозначные числа с помощью xrange(): ';
foreach (xrange(1, 9, 2) as $number) {
echo "$number ";
}
?>Результат выполнения данного примера:
Нечётные однозначные числа с помощью range(): 1 3 5 7 9 Нечётные однозначные числа с помощью xrange(): 1 3 5 7 9
Когда функция генератор вызывается, она вернёт объект встроенного класса Generator. Этот объект реализует интерфейс Iterator, станет однонаправленным объектом итератора и предоставит методы, с помощью которых можно управлять его состоянием, включая передачу в него и возвращения из него значений.
Генератор в целом выглядит как обычная функция, за исключением того, что вместо возвращения одного значения, генератор будет перебирать столько значений, сколько необходимо. Любая функция, содержащая yield, является функцией генератора.
Когда вызывается генератор, он возвращает объект, который можно итерировать. Когда вы итерируете этот объект (например, в цикле foreach), PHP вызывает методы итерации объекта каждый раз, когда вам нужно новое значение, после чего сохраняет состояние генератора и при следующем вызове возвращает следующее значение.
Когда все значения в генераторе закончились, генератор просто завершит работу, ничего не вернув. После этого основной код продолжит работу, как если бы в массиве закончились элементы для перебора.
Замечание:
Генераторы могут возвращать значения, которые можно получить с помощью Generator::getReturn().
Вся суть генератора заключается в ключевом слове yield. В самом простом варианте оператор "yield" можно рассматривать как оператор "return", за исключением того, что вместо прекращения работы функции, "yield" только приостанавливает её выполнение и возвращает текущее значение, и при следующем вызове функции она возобновит выполнение с места, на котором прервалась.
Пример #1 Простой пример выдачи значений
<?php
function gen_one_to_three() {
for ($i = 1; $i <= 3; $i++) {
// Обратите внимание, что $i сохраняет своё значение между вызовами.
yield $i;
}
}
$generator = gen_one_to_three();
foreach ($generator as $value) {
echo "$value\n";
}
?>Результат выполнения данного примера:
1 2 3
Замечание:
Последовательность целых чисел будет связана с получаемыми от генератора значениями, как будто перебирается неассоциативный массив.
PHP поддерживает ассоциативные массивы, и генераторы не являются исключением. Так же как можно получать простые значения, как показано выше, вы можете получать значения с ключами.
Синтаксис получения ключ/значение очень похож на синтаксис ассоциативных массивов, как показано ниже.
Пример #2 Получение пар ключ/значение
<?php
/* $input содержит пары ключ/значение разделённые точкой с запятой */
$input = <<<'EOF'
1;PHP;Любит знаки доллара
2;Python;Любит пробелы
3;Ruby;Любит блоки
EOF;
function input_parser($input) {
foreach (explode("\n", $input) as $line) {
$fields = explode(';', $line);
$id = array_shift($fields);
yield $id => $fields;
}
}
foreach (input_parser($input) as $id => $fields) {
echo "$id:\n";
echo " $fields[0]\n";
echo " $fields[1]\n";
}
?>Результат выполнения данного примера:
1:
PHP
Любит знаки доллара
2:
Python
Любит пробелы
3:
Ruby
Любит блоки
Для получения null нужно вызвать "yield" без аргументов. Ключ сгенерируется
автоматически.
Пример #3 Получение null
<?php
function gen_three_nulls() {
foreach (range(1, 3) as $i) {
yield;
}
}
var_dump(iterator_to_array(gen_three_nulls()));
?>Результат выполнения данного примера:
array(3) {
[0]=>
NULL
[1]=>
NULL
[2]=>
NULL
}
Генераторы могут отдавать значения по ссылке. Это делается так же, как возврат ссылок из функций: добавлением амперсанда (&) перед именем функции.
Пример #4 Получение значений по ссылке
<?php
function &gen_reference() {
$value = 3;
while ($value > 0) {
yield $value;
}
}
/* Обратите внимание, что мы можем изменять $number в цикле, и
* так как генератор возвращает ссылку, $value
* в gen_reference() также изменится. */
foreach (gen_reference() as &$number) {
echo (--$number).'... ';
}
?>Результат выполнения данного примера:
2... 1... 0...
Делегирование генератора позволяет вам получать значения из другого генератора, объекта Traversable, или массива, используя yield from. Внешний генератор будет возвращать значения из внутреннего генератора, объекта или массива, до того момента, пока они их отдают, после чего продолжится выполнение внешнего генератора.
Если генератор используется с yield from, то выражение yield from также будет возвращать значения из внутреннего генератора.
yield from не сбрасывает ключи. Ключи, возвращённые из объекта Traversable или массива, сохранятся. Таким образом, некоторые значения, могут пересекаться по ключам с другими yield или yield from, что, при записи в массив, повлечёт за собой перезапись прежних значений.
Общий случай, когда это имеет значение, это когда iterator_to_array()
возвращает массив с ключами по умолчанию. В этом случае можно получить
неожиданный результат. iterator_to_array() имеет второй параметр
preserve_keys, который можно установить в false, для
генерации собственных ключей и игнорирования ключей,
переданных из объекта Generator.
Пример #5 yield from с iterator_to_array()
<?php
function inner() {
yield 1; // ключ 0
yield 2; // ключ 1
yield 3; // ключ 2
}
function gen() {
yield 0; // ключ 0
yield from inner(); // ключи 0-2
yield 4; // ключ 1
}
// Задайте false вторым параметром для получения массива [0, 1, 2, 3, 4]
var_dump(iterator_to_array(gen()));
?>Результат выполнения данного примера:
array(3) {
[0]=>
int(1)
[1]=>
int(4)
[2]=>
int(3)
}
Пример #6 Основы использования yield from
<?php
function count_to_ten() {
yield 1;
yield 2;
yield from [3, 4];
yield from new ArrayIterator([5, 6]);
yield from seven_eight();
yield 9;
yield 10;
}
function seven_eight() {
yield 7;
yield from eight();
}
function eight() {
yield 8;
}
foreach (count_to_ten() as $num) {
echo "$num ";
}
?>Результат выполнения данного примера:
1 2 3 4 5 6 7 8 9 10
Пример #7 yield from и возвращаемые значения
<?php
function count_to_ten() {
yield 1;
yield 2;
yield from [3, 4];
yield from new ArrayIterator([5, 6]);
yield from seven_eight();
return yield from nine_ten();
}
function seven_eight() {
yield 7;
yield from eight();
}
function eight() {
yield 8;
}
function nine_ten() {
yield 9;
return 10;
}
$gen = count_to_ten();
foreach ($gen as $num) {
echo "$num ";
}
echo $gen->getReturn();
?>Результат выполнения данного примера:
1 2 3 4 5 6 7 8 9 10
Главное преимущество генераторов - это их простота. Гораздо меньше шаблонного кода надо написать, по сравнению с реализацией объекта класса Iterator, и этот код гораздо более простой и понятный. К примеру, эта функция и класс делают одно и то же.
<?php
function getLinesFromFile($fileName) {
if (!$fileHandle = fopen($fileName, 'r')) {
return;
}
while (false !== $line = fgets($fileHandle)) {
yield $line;
}
fclose($fileHandle);
}
// Против...
class LineIterator implements Iterator {
protected $fileHandle;
protected $line;
protected $i;
public function __construct($fileName) {
if (!$this->fileHandle = fopen($fileName, 'r')) {
throw new RuntimeException('Невозможно открыть файл "' . $fileName . '"');
}
}
public function rewind() {
fseek($this->fileHandle, 0);
$this->line = fgets($this->fileHandle);
$this->i = 0;
}
public function valid() {
return false !== $this->line;
}
public function current() {
return $this->line;
}
public function key() {
return $this->i;
}
public function next() {
if (false !== $this->line) {
$this->line = fgets($this->fileHandle);
$this->i++;
}
}
public function __destruct() {
fclose($this->fileHandle);
}
}
?>Однако за эту простоту, впрочем, приходится платить: генераторы могут быть только однонаправленными итераторами. Их нельзя перемотать назад после старта итерации. Это также означает, что один и тот же генератор нельзя использовать несколько раз: генератор необходимо пересоздавать каждый раз, снова вызвав функцию генератора.
(PHP 8)
Атрибуты предлагают возможность добавлять структурированные, машиночитаемые метаданные для следующих деклараций в коде: классы, методы, функции, параметры, свойства и константы класса. Привязанные метаданные можно получить во время исполнения, используя Reflection API. Таким образом, атрибуты можно рассматривать как язык конфигурации, встроенный непосредственно в код.
С помощью атрибутов можно разделить абстрактную реализацию какой-либо функциональности и особенности её использования в коде. В некотором смысле это можно сравнить с разделением интерфейса и его реализаций. Но интерфейсы и реализации - это про код, а атрибуты - про добавление дополнительной информации и конфигурацию. Интерфейсы могут реализовываться только классами, тогда как атрибуты также применимы для методов, функций, параметров, свойств и констант классов. Таким образом, они представляют собой гораздо более гибкий механизм, чем интерфейсы.
Давайте разберём использование атрибутов на простом примере реализации опциональных
методов для интерфейса. Допустим, что интерфейс ActionHandler описывает некую
операцию в приложении. Одни реализации этого интерфейса требуют
предварительной настройки, а другие - нет. И вместо того, чтобы вносить в
интерфейс ActionHandler дополнительный метод
setUp(), который для части реализаций будет пустым,
можно использовать атрибут. Одним из преимуществ этого подхода является то,
что мы можем использовать атрибут несколько раз.
Пример #1 Реализация опциональных методов интерфейса с помощью атрибутов
<?php
interface ActionHandler
{
public function execute();
}
#[Attribute]
class SetUp {}
class CopyFile implements ActionHandler
{
public string $fileName;
public string $targetDirectory;
#[SetUp]
public function fileExists()
{
if (!file_exists($this->fileName)) {
throw new RuntimeException("File does not exist");
}
}
#[SetUp]
public function targetDirectoryExists()
{
if (!file_exists($this->targetDirectory)) {
mkdir($this->targetDirectory);
} elseif (!is_dir($this->targetDirectory)) {
throw new RuntimeException("Target directory $this->targetDirectory is not a directory");
}
}
public function execute()
{
copy($this->fileName, $this->targetDirectory . '/' . basename($this->fileName));
}
}
function executeAction(ActionHandler $actionHandler)
{
$reflection = new ReflectionObject($actionHandler);
foreach ($reflection->getMethods() as $method) {
$attributes = $method->getAttributes(SetUp::class);
if (count($attributes) > 0) {
$methodName = $method->getName();
$actionHandler->$methodName();
}
}
$actionHandler->execute();
}
$copyAction = new CopyFile();
$copyAction->fileName = "/tmp/foo.jpg";
$copyAction->targetDirectory = "/home/user";
executeAction($copyAction);
Синтаксис атрибутов состоит из нескольких частей. Для начала декларация
атрибута всегда начинается с символа #[ и заканчивается
]. Внутри перечисление из одного или более, разделённых запятой, атрибутов.
Атрибуты можно задавать с помощью неполных, полных и абсолютных имён, как описано в разделе
Использование пространства имён: основы.
Аргументы атрибутов опциональны, но если они есть, то заключаются в скобки ().
Аргументы атрибутов могут быть либо конкретными значениями, либо константными выражениями. Для аргументов можно
использовать как позиционный синтаксис, так и синтаксис именованных аргументов.
Когда атрибут запрашивается с помощью Reflection API, его имя трактуется как имя класса, а аргументы передаются в его конструктор. Таким образом, для каждого атрибута должен существовать соответствующий класс.
Пример #1 Синтаксис атрибутов
<?php
// a.php
namespace MyExample;
use Attribute;
#[Attribute]
class MyAttribute
{
const VALUE = 'value';
private $value;
public function __construct($value = null)
{
$this->value = $value;
}
}
// b.php
namespace Another;
use MyExample\MyAttribute;
#[MyAttribute]
#[\MyExample\MyAttribute]
#[MyAttribute(1234)]
#[MyAttribute(value: 1234)]
#[MyAttribute(MyAttribute::VALUE)]
#[MyAttribute(array("key" => "value"))]
#[MyAttribute(100 + 200)]
class Thing
{
}
#[MyAttribute(1234), MyAttribute(5678)]
class AnotherThing
{
}Для доступа к атрибутам классов, методов, функций, параметров, свойств и констант класса, в Reflection API присутствует метод getAttributes() для каждого из перечисленных объектов рефлексии. Этот метод возвращает массив экземпляров ReflectionAttribute, у каждого из которых можно запросить имя атрибута и его аргументы, а также создать объект, представляющего атрибут.
Такое отделение свойств атрибута от явного создания объекта даёт программисту более полный контроль над обработкой ошибок, связанных с отсутствующим классом атрибута и некорректностью его аргументов. Объект атрибута будет создан и проверен на корректность аргументов только после вызова ReflectionAttribute::newInstance(), не раньше.
Пример #1 Чтение атрибутов с помощью Reflection API
<?php
#[Attribute]
class MyAttribute
{
public $value;
public function __construct($value)
{
$this->value = $value;
}
}
#[MyAttribute(value: 1234)]
class Thing
{
}
function dumpAttributeData($reflection) {
$attributes = $reflection->getAttributes();
foreach ($attributes as $attribute) {
var_dump($attribute->getName());
var_dump($attribute->getArguments());
var_dump($attribute->newInstance());
}
}
dumpAttributeData(new ReflectionClass(Thing::class));
/*
string(11) "MyAttribute"
array(1) {
["value"]=>
int(1234)
}
object(MyAttribute)#3 (1) {
["value"]=>
int(1234)
}
*/Вместо того, чтобы последовательно перебирать все атрибуты объекта рефлексии, можно указать имя класса в качестве аргумента и получить только подходящие атрибуты.
Пример #2 Чтение конкретных атрибутов с помощью Reflection API
<?php
function dumpMyAttributeData($reflection) {
$attributes = $reflection->getAttributes(MyAttribute::class);
foreach ($attributes as $attribute) {
var_dump($attribute->getName());
var_dump($attribute->getArguments());
var_dump($attribute->newInstance());
}
}
dumpMyAttributeData(new ReflectionClass(Thing::class));
Создавать классы для атрибутов не обязательно, но крайне рекомендуется.
В самом простом случае требуется просто пустой класс с атрибутом #[Attribute], который
можно импортировать из глобального пространства имён с помощью оператора use.
Пример #1 Простой класс с атрибутом
<?php
namespace Example;
use Attribute;
#[Attribute]
class MyAttribute
{
}
Для ограничения того, с каким типом деклараций можно использовать конкретный атрибут, можно передать
битовую маску первым параметром в #[Attribute].
Пример #2 Ограничение допустимых сущностей для использования атрибута
<?php
namespace Example;
use Attribute;
#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION)]
class MyAttribute
{
}После этого аннотирование атрибутом MyAttribute чего-либо, отличающегося от метода или функции, приведёт к выбрасыванию исключения при вызове ReflectionAttribute::newInstance().
Можно указать следующие сущности:
Attribute::TARGET_CLASSAttribute::TARGET_FUNCTIONAttribute::TARGET_METHODAttribute::TARGET_PROPERTYAttribute::TARGET_CLASS_CONSTANTAttribute::TARGET_PARAMETERAttribute::TARGET_ALL
По умолчанию атрибут можно использовать только один раз для каждой сущности. Если нужна возможность указывать
несколько одинаковых атрибутов для одной сущности - можно выставить соответствующий флаг в битовой маске
для декларации #[Attribute].
Пример #3 Использование IS_REPEATABLE для разрешения использовать атрибут в объявлении несколько раз
<?php
namespace Example;
use Attribute;
#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION | Attribute::IS_REPEATABLE)]
class MyAttribute
{
}Ссылки в PHP - это средство доступа к содержимому одной переменной под разными именами. Они не похожи на указатели C; например, вы не можете выполнять над ними адресную арифметику, они не являются реальными адресами в памяти и т.д. Для получения дополнительной информации смотрите Чем ссылки не являются. Вместо этого указатели в PHP - это псевдонимы в таблице имён переменных. В PHP имя переменной и её содержимое - это разные вещи, поэтому одно содержимое может иметь разные имена. Можно провести аналогию с именами файлов и файлами в Unix: имена переменных - записи в каталоге, а содержимое переменной - это сам файл. Ссылки в PHP - аналог жёстких ссылок в файловых системах Unix.
Есть три основных операции с использованием ссылок: присвоение по ссылке, передача по ссылке и возврат по ссылке. Данный раздел познакомит вас с этими операциями и предоставит ссылки для дальнейшего изучения.
Первая из них - ссылки PHP позволяют создать две переменные указывающие на одно и то же значение. Таким образом, когда выполняется следующее:
<?php
$a =& $b;
?>Замечание:
$a и $b здесь абсолютно эквивалентны, но это не означает, что $a указывает на $b или наоборот. Это означает, что $a и $b указывают на одно и то же значение.
Замечание:
При присвоении, передаче или возврате неинициализированной переменной по ссылке, происходит её создание.
Пример #1 Использование ссылок с неинициализированными переменными
<?php
function foo(&$var) { }
foo($a); // $a создана и равна null
$b = array();
foo($b['b']);
var_dump(array_key_exists('b', $b)); // bool(true)
$c = new stdClass;
foo($c->d);
var_dump(property_exists($c, 'd')); // bool(true)
?>
Такой же синтаксис может использоваться в функциях, возвращающими ссылки,
и с оператором new:
<?php
$foo =& find_var($bar);
?>Использование того же синтаксиса с функцией, которая не возвращает по ссылке, приведёт к ошибке, так же как и её использование с результатом оператора new. Хотя объекты передаются как указатели, это не то же самое, что ссылки, как описано в разделе Объекты и ссылки.
Если переменной, объявленной внутри функции как
global, будет присвоена ссылка, она будет видна только
в функции. Чтобы избежать этого, используйте массив $GLOBALS.
Пример #2 Присвоение ссылок глобальным переменным внутри функции
<?php
$var1 = "Пример переменной";
$var2 = "";
function global_references($use_globals)
{
global $var1, $var2;
if (!$use_globals) {
$var2 =& $var1; // только локально
} else {
$GLOBALS["var2"] =& $var1; // глобально
}
}
global_references(false);
echo "значение var2: '$var2'\n"; // значение var2: ''
global_references(true);
echo "значение var2: '$var2'\n"; // значение var2: 'Пример переменной'
?>global $var; как о сокращении от
$var =& $GLOBALS['var'];. Таким образом,
присвоение $var другой ссылки влияет лишь на локальную
переменную.
Замечание:
При использовании переменной-ссылки в foreach, изменяется содержание, на которое она ссылается.
Пример #3 Ссылки и foreach
<?php
$ref = 0;
$row =& $ref;
foreach (array(1, 2, 3) as $row) {
// сделать что-нибудь
}
echo $ref; // 3 - последнее значение, используемое в цикле
?>
Хотя в выражениях, создаваемых с помощью конструкции
array(),
нет явного присвоения по ссылке, тем не менее они могут вести себя как таковые,
если указать префикс & для элементов массива. Пример:
<?php
$a = 1;
$b = array(2, 3);
$arr = array(&$a, &$b[0], &$b[1]);
$arr[0]++; $arr[1]++; $arr[2]++;
/* $a == 2, $b == array(3, 4); */
?>Однако следует отметить, что ссылки в массивах являются потенциально опасными. При обычном (не по ссылке) присвоении массива, ссылки внутри этого массива сохраняются. Это также относится и к вызовам функций, когда массив передаётся по значению. Пример:
<?php
/* Присвоение скалярных переменных */
$a = 1;
$b =& $a;
$c = $b;
$c = 7; //$c не ссылка и не изменяет значений $a и $b
/* Присвоение массивов */
$arr = array(1);
$a =& $arr[0]; // $a и $arr[0] ссылаются на одно значение
$arr2 = $arr; // присвоение не по ссылке!
$arr2[0]++;
/* $a == 2, $arr == array(2) */
/* Содержимое $arr изменилось, хотя было присвоено не по ссылке! */
?>Второе, что делают ссылки - передача параметров по ссылке. При этом локальная переменная в функции и переменная в вызывающей области видимости ссылаются на одно и то же содержимое. Пример:
<?php
function foo(&$var) {
$var++;
}
$a = 5;
foo($a);
?>Третье, что могут делать ссылки - это возврат по ссылке.
Как уже было сказано, ссылки не являются указателями. Это означает, что следующая конструкция не будет делать то, что вы ожидаете:
<?php
function foo(&$var) {
$var =& $GLOBALS["baz"];
}
foo($bar);
?>Переменная $var в функции foo будет связана с $bar в вызывающем коде, но затем она будет перепривязана к $GLOBALS["baz"]. Нет способа связать $bar в области видимости вызывающем коде с чем-либо ещё путём использования механизма ссылок, поскольку $bar не доступна в функции foo (доступно лишь её значение через $var, но $var имеет только значение переменной и не имеет связи имя-значение в таблице имён переменных). Вы можете воспользоваться возвратом ссылок из функции для привязки внешней переменной к другому значению.
Вы можете передать переменную по ссылке в качестве аргумента в функцию, чтобы эта функция могла изменять значение переменной. Синтаксис выглядит следующим образом:
<?php
function foo(&$var) {
$var++;
}
$a = 5;
foo($a);
// $a здесь равно 6
?>Замечание: В вызове функции отсутствует знак ссылки - он есть только в определении функции. Этого достаточно для корректной передачи аргументов по ссылке.
По ссылке можно передавать:
foo($a)
Ссылки, возвращаемые функцией, например:
<?php
function foo(&$var) {
$var++;
}
function &bar() {
$a = 5;
return $a;
}
foo(bar());
?>Любое другое выражение не должно передаваться по ссылке, так как результат не определён. Например, следующая передача по ссылке является неправильной:
<?php
function foo(&$var) {
$var++;
}
function bar() { // Операция & отсутствует
$a = 5;
return $a;
}
foo(bar()); // Вызывает предупреждение
foo($a = 5); // Выражение, а не переменная
foo(5); // Константа, а не переменная
class Foobar
{
}
foo(new Foobar()) // Вызывает уведомление с PHP 7.0.7
// Notice: Only variables should be passed by reference
?>Возврат по ссылке используется в тех случаях, когда вы хотите использовать функцию для выбора переменной, с которой должна быть связана данная ссылка. Не используйте возврат по ссылке для увеличения производительности. Ядро PHP само занимается оптимизацией. Применяйте возврат по ссылке только имея технические причины на это. Для возврата по ссылке используйте такой синтаксис:
<?php
class foo {
public $value = 42;
public function &getValue() {
return $this->value;
}
}
$obj = new foo;
$myValue = &$obj->getValue(); // $myValue указывает на $obj->value, равное 42.
$obj->value = 2;
echo $myValue; // отобразит новое значение $obj->value, то есть 2.
?>Замечание: В отличие от передачи параметров по ссылке,
&здесь нужно использовать в обоих местах - для указания на то, что вы возвращаете ссылку, а не копию, как обычно, и для указания того, что происходит связывание по ссылке, а не обычное присвоение для $myValue.
Замечание: Если вы возвращаете ссылку из функции, используя следующий синтаксис:
return ($this->value);, это не будет работать, так как вы возвращаете по ссылке результат выражения, а не переменную. По ссылке можно возвращать только переменные и ничего больше.
Для использования возвращаемой ссылки вы должны применять присвоение по ссылке:
<?php
function &collector() {
static $collection = array();
return $collection;
}
$collection = &collector();
$collection[] = 'foo';
?><?php
function &collector() {
static $collection = array();
return $collection;
}
array_push(collector(), 'foo');
?>Замечание: Заметим, что
array_push(&collector(), 'foo');не сработает, а приведёт к неисправимой ошибке.
При сбросе ссылки, просто разрывается связь имени и содержимого переменной. Это не означает, что содержимое переменной будет уничтожено. Например:
<?php
$a = 1;
$b =& $a;
unset($a);
?>Опять же, можно провести аналогию с вызовом unlink (в Unix).
Многие синтаксические конструкции PHP реализованы через механизм ссылок, поэтому всё сказанное выше о ссылочном связывании применимо также и к этим конструкциям. Некоторые конструкции, вроде передающих и возвращающих по ссылке, рассмотрены ранее. Другие конструкции, использующие ссылки:
Если вы объявляете переменную как global $var, вы фактически создаёте ссылку на глобальную переменную. Это означает то же самое, что и:
<?php
$var =& $GLOBALS["var"];
?>Это значит, например, что сброс (unset) $var не приведёт к сбросу глобальной переменной.
PHP предоставляет всем скриптам большое количество предопределённых переменных. Эти переменные содержат всё, от внешних данных до переменных среды окружения, от текста сообщений об ошибках до последних полученных заголовков.
Суперглобальные переменные — Встроенные переменные, которые всегда доступны во всех областях
Некоторые предопределённые переменные в PHP являются "суперглобальными", что означает, что они доступны в любом месте скрипта. Нет необходимости использовать синтаксис global $variable; для доступа к ним в функциях и методах.
Суперглобальными переменными являются:
Замечание: Доступность переменных
По умолчанию все суперглобальные переменные доступны всегда, однако существуют настройки, которые могут на это влиять. За дальнейшей информацией обращайтесь к описанию директивы variables_order.
Замечание: Переменные переменных
Суперглобальные переменные не могут быть использованы в качестве переменных переменных внутри функций и методов.
(PHP 4, PHP 5, PHP 7, PHP 8)
$GLOBALS — Ссылки на все переменные глобальной области видимости
Ассоциативный массив (array), содержащий ссылки на все переменные, определённые в данный момент в глобальной области видимости скрипта. Имена переменных являются ключами массива.
Пример #1 Пример использования $GLOBALS
<?php
function test() {
$foo = "локальная переменная";
echo '$foo в глобальной области видимости: ' . $GLOBALS["foo"] . "\n";
echo '$foo в текущей области видимости: ' . $foo . "\n";
}
$foo = "Пример содержимого";
test();
?>Результатом выполнения данного примера будет что-то подобное:
$foo в глобальной области видимости: Пример содержимого $foo в текущей области видимости: локальная переменная
Начиная с PHP 8.1.0, доступ на запись ко всему массиву $GLOBALS больше не поддерживается:
Пример #2 запись всего $GLOBALS приведёт к ошибке
<?php
// Генерирует ошибку во время компиляции:
$GLOBALS = [];
$GLOBALS += [];
$GLOBALS =& $x;
$x =& $GLOBALS;
unset($GLOBALS);
array_pop($GLOBALS);
// ...и любые другие операции записи/чтения-записи в $GLOBALS
?>Замечание:
Это 'суперглобальная' или автоматическая глобальная переменная. Это просто означает, что она доступна во всех контекстах скрипта. Нет необходимости выполнять global $variable; для доступа к ней внутри метода или функции.
Замечание: Доступность переменной
В отличие от всех остальных суперглобальных переменных, $GLOBALS всегда доступна в PHP.
Замечание:
Начиная с PHP 8.1.0, массив $GLOBALS теперь является доступной только для чтения копией глобальной таблицы символов. То есть глобальные переменные не могут быть изменены с помощью его копии. Ранее массив $GLOBALS исключался из обычного поведения массивов PHP по значению и глобальные переменные можно было изменить с помощью его копии.
<?php
// До PHP 8.1.0
$a = 1;
$globals = $GLOBALS; // Как будто бы по значению копии
$globals['a'] = 2;
var_dump($a); // int(2)
// Начиная с PHP 8.1.0
// больше не изменяет значение $a. Предыдущее поведение нарушало семантику по значению
$globals = $GLOBALS;
$globals['a'] = 1;
// Чтобы восстановить предыдущее поведение, повторите его копию и присвойте каждому свойству значение $ GLOBALS.
foreach ($globals as $key => $value) {
$GLOBALS[$key] = $value;
}
?>
(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8)
$_SERVER — Информация о сервере и среде исполнения
Переменная $_SERVER - это массив (array), содержащий такую информацию, как заголовки, пути и местоположения скриптов. Записи в этом массиве создаются веб-сервером, поэтому нет гарантии, что каждый веб-сервер будет предоставлять любую из этих переменных; серверы могут опускать некоторые из них или предоставлять другие, не указанные здесь. Однако большинство из этих переменных учтены в спецификации » CGI/1.1 и, скорее всего, будут определены.
Замечание: При запуске PHP в командной строке большинство из этих записей будут недоступны или не будут иметь никакого значения.
В дополнение к перечисленным ниже элементам, PHP будет создавать дополнительные элементы
со значениями из заголовков запросов. У элементов будет имя HTTP_,
за которым следует имя заголовка, написанное с заглавной буквы и с подчёркиванием вместо дефиса.
Например, заголовок Accept-Language будет доступен как $_SERVER['HTTP_ACCEPT_LANGUAGE'].
'CGI/1.1'..
Замечание: В Apache 2 необходимо установить
UseCanonicalName = OnиServerName. В противном случае это значение отразит имя хоста, предоставленное клиентом, которое может быть подделано. Небезопасно полагаться на это значение в контексте, требующем безопасности.
'HTTP/1.0';
'GET',
'HEAD', 'POST', 'PUT'.
Замечание:
PHP-скрипт завершается после отправки заголовков (то есть после того, как осуществляется любой вывод без буферизации вывода), если метод запроса был
HEAD.
Замечание: Сервер должен быть настроен, чтобы создавать эту переменную. Для примера, в Apache необходимо присутствие директивы
HostnameLookups Onв файле httpd.conf, чтобы эта переменная создавалась. Смотрите также gethostbyaddr().
Абсолютный путь к исполняемому скрипту.
Замечание:
Если скрипт запускается в командной строке (CLI), используя относительный путь, такой как file.php или ../file.php, переменная $_SERVER['SCRIPT_FILENAME'] будет содержать относительный путь, указанный пользователем.
'80';
используя SSL, например, это значение будет таким, какое сконфигурировано
для соединений безопасного HTTP.
Замечание: Чтобы получить физический (реальный) порт в Apache 2, необходимо установить
UseCanonicalName = OnиUseCanonicalPhysicalPort = On, иначе это значение может быть подменено и не вернуть реальной значение физического порта. Полагаться на это значение небезопасно в контексте приложений, требующих усиленной безопасности.
Замечание: Пользователи Apache 2 могут использовать директиву
AcceptPathInfo = Onв конфигурационном файле httpd.conf для задания переменной PATH_INFO.
/index.html'.
/some/stuff.
Пример #1 Пример использования $_SERVER
<?php
echo $_SERVER['SERVER_NAME'];
?>Результатом выполнения данного примера будет что-то подобное:
www.example.com
Замечание:
Это 'суперглобальная' или автоматическая глобальная переменная. Это просто означает, что она доступна во всех контекстах скрипта. Нет необходимости выполнять global $variable; для доступа к ней внутри метода или функции.
(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8)
$_GET — Переменные HTTP GET
Ассоциативный массив переменных, переданных скрипту через параметры URL (известные также как строка запроса). Обратите внимание, что массив не только заполняется для GET-запросов, а скорее для всех запросов со строкой запроса.
Пример #1 Пример использования $_GET
<?php
echo 'Привет, ' . htmlspecialchars($_GET["name"]) . '!';
?>Подразумевается, что пользователь ввёл в браузере адрес http://example.com/?name=Иван
Результатом выполнения данного примера будет что-то подобное:
Привет, Иван!
Замечание:
Это 'суперглобальная' или автоматическая глобальная переменная. Это просто означает, что она доступна во всех контекстах скрипта. Нет необходимости выполнять global $variable; для доступа к ней внутри метода или функции.
Замечание:
Параметры GET обрабатываются urldecode().
(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8)
$_POST — Переменные HTTP POST
Ассоциативный массив данных, переданных скрипту через HTTP методом POST
при использовании application/x-www-form-urlencoded или multipart/form-data
в заголовке Content-Type запроса HTTP.
Пример #1 Пример использования $_POST
<?php
echo 'Привет ' . htmlspecialchars($_POST["name"]) . '!';
?>Подразумевается, что пользователь отправил через POST name=Иван
Результатом выполнения данного примера будет что-то подобное:
Привет, Иван!
Замечание:
Это 'суперглобальная' или автоматическая глобальная переменная. Это просто означает, что она доступна во всех контекстах скрипта. Нет необходимости выполнять global $variable; для доступа к ней внутри метода или функции.
(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8)
$_FILES — Переменные файлов, загруженных по HTTP
Ассоциативный массив (array) элементов, загруженных в текущий скрипт через метод HTTP POST. Структура этого массива описана в разделе Загрузка файлов методом POST.
Замечание:
Это 'суперглобальная' или автоматическая глобальная переменная. Это просто означает, что она доступна во всех контекстах скрипта. Нет необходимости выполнять global $variable; для доступа к ней внутри метода или функции.
(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8)
$_REQUEST — Переменные HTTP-запроса
Ассоциативный массив (array), который по умолчанию содержит данные переменных $_GET, $_POST и $_COOKIE.
Замечание:
Это 'суперглобальная' или автоматическая глобальная переменная. Это просто означает, что она доступна во всех контекстах скрипта. Нет необходимости выполнять global $variable; для доступа к ней внутри метода или функции.
Замечание:
При работе в командной строке переменные argv и argc не включаются в данный массив - они присутствуют в массиве $_SERVER.
Замечание:
Переменные в массиве $_REQUEST передаются в скрипт посредством методов GET, POST или COOKIE, поэтому им нельзя доверять, т.к. они могли быть изменены удалённым пользователем. Их наличие и порядок добавления данных в соответствующие массивы определяется директивой конфигурации PHP request_order и variables_order.
(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8)
$_SESSION — Переменные сессии
Ассоциативный массив, содержащий переменные сессии, которые доступны для текущего скрипта. Смотрите документацию по функциям сессии для получения дополнительной информации.
Замечание:
Это 'суперглобальная' или автоматическая глобальная переменная. Это просто означает, что она доступна во всех контекстах скрипта. Нет необходимости выполнять global $variable; для доступа к ней внутри метода или функции.
(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8)
$_ENV — Переменные окружения
Ассоциативный массив (array) значений, переданных скрипту через переменные окружения.
Эти значения импортируются в глобальное пространство имён PHP из системных переменных окружения, в котором запущен парсер PHP. Большинство значений передаётся из командной оболочки, под которой запущен PHP, и в разных системах, вероятно, используются разные типы оболочек поэтому окончательный список невозможно представить. Пожалуйста, изучите документацию к вашей командной оболочке для получения списка переменных окружения.
Некоторые переменные окружения включают CGI-переменные, причём их наличие не зависит от того, запущен ли PHP как модуль сервера или как препроцессор CGI.
Пример #1 Пример использования $_ENV
<?php
echo 'Моё имя пользователя: ' .$_ENV["USER"] . '!';
?>Допустим, скрипт запустил "bjori"
Результатом выполнения данного примера будет что-то подобное:
Моё имя пользователя: bjori!
Замечание:
Это 'суперглобальная' или автоматическая глобальная переменная. Это просто означает, что она доступна во всех контекстах скрипта. Нет необходимости выполнять global $variable; для доступа к ней внутри метода или функции.
(PHP 4, PHP 5, PHP 7)
$php_errormsg — Предыдущее сообщение об ошибке
Данная функциональность объявлена УСТАРЕВШЕЙ, начиная с PHP 7.2.0 и её крайне не рекомендуется использовать.
Используйте функцию error_get_last().
$php_errormsg является переменной, содержащей текст последней ошибки, сгенерированной PHP. Эта переменная будет доступна только в блоке кода, в котором случилась ошибка, и только если включена конфигурационная опция track_errors (по умолчанию отключена).
Если настроен пользовательский обработчик ошибок (set_error_handler()),
то $php_errormsg устанавливается только в том случае, если обработчик ошибки
возвращает false.
| Версия | Описание |
|---|---|
| 8.0.0 | Директива track_errors, из-за которой становится доступным $php_errormsg, была удалена. |
| 7.2.0 | Директива track_errors, из-за которой становится доступным $php_errormsg, была объявлена устаревшей. |
Пример #1 Пример использования $php_errormsg
<?php
@strpos();
echo $php_errormsg;
?>Результатом выполнения данного примера будет что-то подобное:
Wrong parameter count for strpos()
(PHP 4 >= 4.0.4, PHP 5, PHP 7, PHP 8)
$http_response_header — Заголовки ответов HTTP
Массив (array) $http_response_header похож на функцию get_headers(). При использовании обёртки HTTP, $http_response_header будет заполняться заголовками ответа HTTP. $http_response_header будет создан в локальной области видимости.
Пример #1 Пример $http_response_header
<?php
function get_contents() {
file_get_contents("http://example.com");
var_dump($http_response_header);
}
get_contents();
var_dump($http_response_header);
?>Результатом выполнения данного примера будет что-то подобное:
array(9) {
[0]=>
string(15) "HTTP/1.1 200 OK"
[1]=>
string(35) "Date: Sat, 12 Apr 2008 17:30:38 GMT"
[2]=>
string(29) "Server: Apache/2.2.3 (CentOS)"
[3]=>
string(44) "Last-Modified: Tue, 15 Nov 2005 13:24:10 GMT"
[4]=>
string(27) "ETag: "280100-1b6-80bfd280""
[5]=>
string(20) "Accept-Ranges: bytes"
[6]=>
string(19) "Content-Length: 438"
[7]=>
string(17) "Connection: close"
[8]=>
string(38) "Content-Type: text/html; charset=UTF-8"
}
NULL
(PHP 4, PHP 5, PHP 7, PHP 8)
$argc — Количество аргументов, переданных скрипту
Содержит количество аргументов, переданных текущему скрипту при запуске из командной строки.
Замечание: Имя файла скрипта всегда передаётся в качестве первого аргумента, таким образом минимальное значение $argc равно
1.
Замечание: Эта переменная недоступна, если register_argc_argv отключён.
Пример #1 Пример использования $argc
<?php
var_dump($argc);
?>Запустим пример в командной строке: php script.php arg1 arg2 arg3
Результатом выполнения данного примера будет что-то подобное:
int(4)
Замечание:
Также доступно как $_SERVER['argc'].
(PHP 4, PHP 5, PHP 7, PHP 8)
$argv — Массив переданных скрипту аргументов
Содержит массив (array) всех аргументов, переданных скрипту при запуске из командной строки.
Замечание: Первый аргумент $argv[0] всегда содержит имя файла запущенного скрипта.
Замечание: Эта переменная недоступна, если register_argc_argv отключён.
Пример #1 Пример использования $argv
<?php
var_dump($argv);
?>Запустим пример в командной строке: php script.php arg1 arg2 arg3
Результатом выполнения данного примера будет что-то подобное:
array(4) {
[0]=>
string(10) "script.php"
[1]=>
string(4) "arg1"
[2]=>
string(4) "arg2"
[3]=>
string(4) "arg3"
}
Замечание:
Также доступно как $_SERVER['argv'].
Смотрите также "Исключения SPL"
(PHP 5, PHP 7, PHP 8)
Exception — это базовый класс для всех пользовательских исключений.
Текст исключения
Код исключения
Имя файла, в котором было вызвано исключение
Номер строки, в которой было вызвано исключение
Ранее выброшенное исключение
Строковое представление трассировки стека
Трассировка стека в виде массива
(PHP 5, PHP 7, PHP 8)
Exception::__construct — Создать исключение
Создаёт исключение.
messageТекст сообщения.
codeКод исключения.
previousПредыдущее исключение. Используется при создания цепочки исключений.
Замечание: Вызов конструктора класса Exception из его подкласса, игнорирует аргументы по умолчанию, если свойства $code и $message уже установлены.
Замечание:
Параметр
messageне является бинарно-безопасным.
(PHP 5, PHP 7, PHP 8)
Exception::getMessage — Получает сообщение исключения
Возвращает сообщение исключения.
У этой функции нет параметров.
Возвращает сообщение исключения в виде строки.
Пример #1 Пример использования Exception::getMessage()
<?php
try {
throw new Exception("Какое-нибудь сообщение об ошибке");
} catch(Exception $e) {
echo $e->getMessage();
}
?>Результатом выполнения данного примера будет что-то подобное:
Какое-нибудь сообщение об ошибке
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Exception::getPrevious — Возвращает предыдущий объект, реализующий Throwable
Возвращает предыдущий объект, реализующий Throwable (переданный третьим параметром в Exception::__construct()).
У этой функции нет параметров.
Возвращает предыдущий объект, реализующий Throwable или null, если такового нет.
Пример #1 Пример использования Exception::getPrevious()
Проход и печать цепи исключений.
<?php
class MyCustomException extends Exception {}
function doStuff() {
try {
throw new InvalidArgumentException("Ты делаешь это неправильно!", 112);
} catch(Exception $e) {
throw new MyCustomException("Что-то случилось", 911, $e);
}
}
try {
doStuff();
} catch(Exception $e) {
do {
printf("%s:%d %s (%d) [%s]\n", $e->getFile(), $e->getLine(), $e->getMessage(), $e->getCode(), get_class($e));
} while($e = $e->getPrevious());
}
?>Результатом выполнения данного примера будет что-то подобное:
/home/bjori/ex.php:8 Что-то случилось (911) [MyCustomException] /home/bjori/ex.php:6 Ты делаешь это неправильно! (112) [InvalidArgumentException]
(PHP 5, PHP 7, PHP 8)
Exception::getCode — Получает код исключения
Возвращает код исключения.
У этой функции нет параметров.
Возвращает код исключения типа int у класса Exception, но у потомков класса Exception может быть другой тип (например, типа string в PDOException).
Пример #1 Пример использования Exception::getCode()
<?php
try {
throw new Exception("Какое-нибудь сообщение об ошибке", 30);
} catch(Exception $e) {
echo "Код исключения: " . $e->getCode();
}
?>Результатом выполнения данного примера будет что-то подобное:
Код исключения: 30
(PHP 5, PHP 7, PHP 8)
Exception::getFile — Получает файл, в котором возникло исключение
Получить имя файла, где исключение было создано.
У этой функции нет параметров.
Возвращает имя файла, в котором исключение было создано.
Пример #1 Пример использования Exception::getFile()
<?php
try {
throw new Exception;
} catch(Exception $e) {
echo $e->getFile();
}
?>Результатом выполнения данного примера будет что-то подобное:
/home/bjori/tmp/ex.php
(PHP 5, PHP 7, PHP 8)
Exception::getLine — Получает строку, в которой возникло исключение
Получить номер строки, где исключение было создано
У этой функции нет параметров.
Возвращает номер строки, где было создано исключение.
Пример #1 Пример использования Exception::getLine()
<?php
try {
throw new Exception("Какое-нибудь сообщение об ошибке");
} catch(Exception $e) {
echo "Исключение было создано на строке: " . $e->getLine();
}
?>Результатом выполнения данного примера будет что-то подобное:
Исключение было создано на строке: 3
(PHP 5, PHP 7, PHP 8)
Exception::getTrace — Получает трассировку стека
Возвращает трассировку стека исключения.
У этой функции нет параметров.
Возвращает трассировку стека исключения в виде массива (array).
Пример #1 Пример использования Exception::getTrace()
<?php
function test() {
throw new Exception;
}
try {
test();
} catch(Exception $e) {
var_dump($e->getTrace());
}
?>Результатом выполнения данного примера будет что-то подобное:
array(1) {
[0]=>
array(4) {
["file"]=>
string(22) "/home/bjori/tmp/ex.php"
["line"]=>
int(7)
["function"]=>
string(4) "test"
["args"]=>
array(0) {
}
}
}
(PHP 5, PHP 7, PHP 8)
Exception::getTraceAsString — Получает трассировку стека в виде строки
Возвращает трассировку стека исключения в виде строки.
У этой функции нет параметров.
Возвращает трассировку стека исключения в виде строки.
Пример #1 Пример использования Exception::getTraceAsString()
<?php
function test() {
throw new Exception;
}
try {
test();
} catch(Exception $e) {
echo $e->getTraceAsString();
}
?>Результатом выполнения данного примера будет что-то подобное:
#0 /home/bjori/tmp/ex.php(7): test()
#1 {main}
(PHP 5, PHP 7, PHP 8)
Exception::__toString — Строковое представление исключения
Возвращает исключение в виде строки (string).
У этой функции нет параметров.
Возвращает исключение в виде строки (string).
Пример #1 Пример использования Exception::__toString()
<?php
try {
throw new Exception("Какое-нибудь сообщение об ошибке");
} catch(Exception $e) {
echo $e;
}
?>Результатом выполнения данного примера будет что-то подобное:
exception 'Exception' with message 'Какое-нибудь сообщение об ошибке' in /home/bjori/tmp/ex.php:3
Stack trace:
#0 {main}
(PHP 5, PHP 7, PHP 8)
Exception::__clone — Клонировать исключение
Исключения Exception не могут быть клонированы, а попытка сделать это выбросит ошибку Error.
У этой функции нет параметров.
Функция не возвращает значения после выполнения.
Исключения не поддаются клонированию.
| Версия | Описание |
|---|---|
| 8.1.0 | Метод Exception::__clone() больше не является окончательным (final). |
(PHP 5 >= 5.1.0, PHP 7, PHP 8)
Исключение в случае возникновения ошибки.
$message = "",$code = 0,$severity = E_ERROR,$filename = null,$line = null,$previous = nullСерьёзность исключения
Пример #1 Использование set_error_handler() для изменения сообщений об ошибках в ErrorException.
<?php
function exception_error_handler($severity, $message, $file, $line) {
if (!(error_reporting() & $severity)) {
// Этот код ошибки не входит в error_reporting
return;
}
throw new ErrorException($message, 0, $severity, $file, $line);
}
set_error_handler("exception_error_handler");
/* вызываем исключение */
strpos();
?>Результатом выполнения данного примера будет что-то подобное:
Fatal error: Uncaught exception 'ErrorException' with message 'strpos() expects at least 2 parameters, 0 given' in /home/bjori/tmp/ex.php:12
Stack trace:
#0 [internal function]: exception_error_handler(2, 'strpos() expect...', '/home/bjori/php...', 12, Array)
#1 /home/bjori/php/cleandocs/test.php(12): strpos()
#2 {main}
thrown in /home/bjori/tmp/ex.php on line 12
(PHP 5 >= 5.1.0, PHP 7, PHP 8)
ErrorException::__construct — Создаёт исключение
$message = "",$code = 0,$severity = E_ERROR,$filename = null,$line = null,$previous = nullСоздаёт исключение.
messageТекст исключения.
codeКод исключения.
severityУровень серьёзности исключения.
Замечание:
В то время, как уровень серьёзности может быть любым целым числом (int), предполагается, что для её указания будут использованы константы ошибок.
filenameИмя файла, где вызвано исключение.
lineНомер строки, где вызвано исключение.
previousПредыдущее исключение. Используется для создания цепочки исключений.
| Версия | Описание |
|---|---|
| 8.0.0 |
filename и line теперь допускают значение null.
Ранее их значениями по умолчанию были __FILE__ и
__LINE__, соответственно.
|
(PHP 5 >= 5.1.0, PHP 7, PHP 8)
ErrorException::getSeverity — Получает серьёзность исключения
Возвращает серьёзность исключения.
У этой функции нет параметров.
Возвращает уровень серьёзности исключения.
Пример #1 Пример использования ErrorException::getSeverity()
<?php
try {
throw new ErrorException("Сообщение об исключении", 0, E_USER_ERROR);
} catch(ErrorException $e) {
echo "Серьёзность этого исключения равна: " . $e->getSeverity();
var_dump($e->getSeverity() === E_USER_ERROR);
}
?>Результатом выполнения данного примера будет что-то подобное:
Серьёзность этого исключения равна: 256 bool(true)
(PHP 7, PHP 8)
Error - базовый класс для всех внутренних ошибок PHP.
Сообщение об ошибке
Код ошибки
Имя файла, в котором произошла ошибка
Номер строки, в которой произошла ошибка
Ранее выброшенное исключение
Строковое представление трассировки стека
Трассировка стека в виде массива
(PHP 7, PHP 8)
Error::__construct — Создаёт объект класса Error
Создаёт объект класса Error.
messageСообщение об ошибке.
codeКод ошибки.
previousПредыдущий объект, реализующий интерфейс throwable, используется для создания цепочки исключений.
Замечание:
Значение
messageНЕ является безопасным для бинарных данных, то есть в тексте сообщения нельзя использовать символ с кодом \0.
(PHP 7, PHP 8)
Error::getMessage — Получает сообщение об ошибке
Возвращает сообщение об ошибке.
У этой функции нет параметров.
Возвращает сообщение об ошибке в виде строки.
Пример #1 Пример использования Error::getMessage()
<?php
try {
throw new Error("Страшная ошибка");
} catch(Error $e) {
echo $e->getMessage();
}
?>Результатом выполнения данного примера будет что-то подобное:
Страшная ошибка
(PHP 7, PHP 8)
Error::getPrevious — Возвращает предыдущий Throwable
Возвращает предыдущий объект Throwable (третий параметр конструктора Error::__construct()).
У этой функции нет параметров.
Возвращает предыдущий объект Throwable, если он есть,
и null, если его нет.
Пример #1 Пример использования Error::getPrevious()
Проход и печать цепи исключений.
<?php
class MyCustomError extends Error {}
function doStuff() {
try {
throw new InvalidArgumentError("Вы делаете это неправильно!", 112);
} catch(Error $e) {
throw new MyCustomError("Что-то случилось", 911, $e);
}
}
try {
doStuff();
} catch(Error $e) {
do {
printf("%s:%d %s (%d) [%s]\n", $e->getFile(), $e->getLine(), $e->getMessage(), $e->getCode(), get_class($e));
} while($e = $e->getPrevious());
}
?>Результатом выполнения данного примера будет что-то подобное:
/home/bjori/ex.php:8 Что-то случилось (911) [MyCustomError] /home/bjori/ex.php:6 Вы делаете это неправильно! (112) [InvalidArgumentError]
(PHP 7, PHP 8)
Error::getCode — Возвращает код ошибки
Возвращает код ошибки.
У этой функции нет параметров.
Возвращает код ошибки типа int
Пример #1 Пример использованияError::getCode()
<?php
try {
throw new Error("Какое-то сообщение об ошибке", 30);
} catch(Error $e) {
echo "Код ошибки: " . $e->getCode();
}
?>Результатом выполнения данного примера будет что-то подобное:
Код ошибки: 30
(PHP 7, PHP 8)
Error::getFile — Получает файл, в котором произошла ошибка
Получить имя файла, в котором произошла ошибка.
У этой функции нет параметров.
Возвращает имя файла, в котором произошла ошибка.
Пример #1 Пример использования Error::getFile()
<?php
try {
throw new Error;
} catch(Error $e) {
echo $e->getFile();
}
?>Результатом выполнения данного примера будет что-то подобное:
/home/bjori/tmp/ex.php
(PHP 7, PHP 8)
Error::getLine — Получает номер строки, в которой произошла ошибка
Получить номер строки, в которой произошла ошибка.
У этой функции нет параметров.
Возвращает номер строки, в которой произошла ошибка.
Пример #1 Пример использованияError::getLine()
<?php
try {
throw new Error("Какое-то сообщение об ошибке");
} catch(Error $e) {
echo "Ошибка создана в строке: " . $e->getLine();
}
?>Результатом выполнения данного примера будет что-то подобное:
Ошибка создана в строке: 3
(PHP 7, PHP 8)
Error::getTrace — Получает трассировку стека
Возвращает трассировку стека.
У этой функции нет параметров.
Возвращает трассировку стека в виде массива (array).
Пример #1 Пример использования Error::getTrace()
<?php
function test() {
throw new Error;
}
try {
test();
} catch(Error $e) {
var_dump($e->getTrace());
}
?>Результатом выполнения данного примера будет что-то подобное:
array(1) {
[0]=>
array(4) {
["file"]=>
string(22) "/home/bjori/tmp/ex.php"
["line"]=>
int(7)
["function"]=>
string(4) "test"
["args"]=>
array(0) {
}
}
}
(PHP 7, PHP 8)
Error::getTraceAsString — Получает трассировку стека в виде строки
Возвращает трассировку стека в виде строки.
У этой функции нет параметров.
Возвращает трассировку стека в виде строки.
Пример #1 Пример использования Error::getTraceAsString()
<?php
function test() {
throw new Error;
}
try {
test();
} catch(Error $e) {
echo $e->getTraceAsString();
}
?>Результатом выполнения данного примера будет что-то подобное:
#0 /home/bjori/tmp/ex.php(7): test()
#1 {main}
(PHP 7, PHP 8)
Error::__toString — Строковое представление ошибки
Возвращает строковое (string) представление ошибки.
У этой функции нет параметров.
Возвращает строковое (string) представление ошибки.
Пример #1 Пример использования Error::__toString()
<?php
try {
throw new Error("Сообщение об ошибке");
} catch(Error $e) {
echo $e;
}
?>Результатом выполнения данного примера будет что-то подобное:
Error: Сообщение об ошибке in /home/bjori/tmp/ex.php:3
Stack trace:
#0 {main}
(PHP 7, PHP 8)
Error::__clone — Клонирует ошибку
Объект класса Error нельзя клонировать, так что эта функция вызовет фатальную ошибку.
У этой функции нет параметров.
Функция не возвращает значения после выполнения.
Объект класса Error нельзя клонировать.
| Версия | Описание |
|---|---|
| 8.1.0 | Метод Error::__clone() больше не является окончательным (final). |
(PHP 7 >= PHP 7.1.0, PHP 8)
ArgumentCountError выбрасывается, когда в пользовательский метод или функцию передано недостаточное количество аргументов.
Эта ошибка также выбрасывается, если в невариативную встроенную функцию передаётся слишком много аргументов.
(PHP 7, PHP 8)
ArithmeticError выбрасывается, когда возникает ошибка при выполнении математических операций. Такие ошибки возможно спровоцировать побитовым смещением на отрицательное значение или вызовом функции intdiv(), приводящей значение, не входящее в допустимый интервал целых чисел (int).
(PHP 7, PHP 8)
AssertionError выбрасывается, когда утверждение, сделанное с помощью assert(), терпит неудачу.
(PHP 7, PHP 8)
DivisionByZeroError выбрасывается при попытке поделить число на ноль.
(PHP 7 > 7.3.0, PHP 8)
Исключение CompileError выбрасывается при некоторых ошибках компиляции, которые ранее выдавали фатальную ошибку.
(PHP 7, PHP 8)
ParseError выбрасывается, когда возникает ошибка при разборе PHP-кода, например, когда вызывается функция eval().
Замечание: Начиная с PHP 7.3.0, класс ParseError наследуется от CompileError. Ранее этот класс расширял класс Error.
(PHP 7, PHP 8)
Исключение TypeError может быть выброшено, если:
| Версия | Описание |
|---|---|
| 7.1.0 | Исключение TypeError больше не выбрасывается, когда во встроенную PHP-функцию в режиме strict type передаётся недопустимое количество аргументов. Вместо этого выбрасывается ArgumentCountError. |
(PHP 8)
Ошибка ValueError выбрасывается, если тип аргумента правильный, но его значение неверно. Например, передача отрицательного целого числа, когда функция ожидает положительное, или передача пустой строки/массива, когда функция ожидает, что он не будет пустым.
(PHP 8)
UnhandledMatchError выбрасывается, если субъект, переданный в выражение match, не обрабатывается ни одной из сторон выражения match.
(PHP 8 >= 8.1.0)
FiberError выбрасывает, если в объекте Fiber выполняется недопустимая операция.
Смотрите также Интерфейсы SPL и Предопределённые классы.
(PHP 5, PHP 7, PHP 8)
Интерфейс, определяющий, является ли класс обходимым (traversable) с использованием foreach.
Абстрактный базовый интерфейс, который не может быть реализован сам по себе. Вместо этого должен реализовываться IteratorAggregate или Iterator.
Этот интерфейс не имеет методов, его единственная цель - быть базовым интерфейсом для всех обходимых классов.
| Версия | Описание |
|---|---|
| 7.4.0 | Интерфейс Traversable теперь может быть реализован абстрактными классами. Расширяемые классы должны реализовывать интерфейс Iterator или IteratorAggregate. |
Замечание:
Внутренние (встроенные) классы, реализующие этот интерфейс, могут быть использованы в конструкции foreach и не обязаны реализовывать интерфейс IteratorAggregate или Iterator.
Замечание:
До версии PHP 7.4.0 этот внутренний интерфейс движка не мог быть реализован в PHP-скриптах. Вместо него следует использовать либо интерфейс IteratorAggregate, либо Iterator.
(PHP 5, PHP 7, PHP 8)
Интерфейс для внешних итераторов или объектов, которые могут повторять себя изнутри.
PHP уже предоставляет некоторые итераторы для многих ежедневных задач. Смотрите список итераторов SPL для более детальной информации.
Пример #1 Основы использования
Этот пример демонстрирует в каком порядке вызываются методы, когда используется с итератором оператор foreach.
<?php
class myIterator implements Iterator {
private $position = 0;
private $array = array(
"firstelement",
"secondelement",
"lastelement",
);
public function __construct() {
$this->position = 0;
}
public function rewind(): void {
var_dump(__METHOD__);
$this->position = 0;
}
#[\ReturnTypeWillChange]
public function current() {
var_dump(__METHOD__);
return $this->array[$this->position];
}
#[\ReturnTypeWillChange]
public function key() {
var_dump(__METHOD__);
return $this->position;
}
public function next(): void {
var_dump(__METHOD__);
++$this->position;
}
public function valid(): bool {
var_dump(__METHOD__);
return isset($this->array[$this->position]);
}
}
$it = new myIterator;
foreach($it as $key => $value) {
var_dump($key, $value);
echo "\n";
}
?>Результатом выполнения данного примера будет что-то подобное:
string(18) "myIterator::rewind" string(17) "myIterator::valid" string(19) "myIterator::current" string(15) "myIterator::key" int(0) string(12) "firstelement" string(16) "myIterator::next" string(17) "myIterator::valid" string(19) "myIterator::current" string(15) "myIterator::key" int(1) string(13) "secondelement" string(16) "myIterator::next" string(17) "myIterator::valid" string(19) "myIterator::current" string(15) "myIterator::key" int(2) string(11) "lastelement" string(16) "myIterator::next" string(17) "myIterator::valid"
Смотрите также раздел Итераторы объектов.
(PHP 5, PHP 7, PHP 8)
Iterator::current — Возврат текущего элемента
У этой функции нет параметров.
Может возвращать любой тип.
(PHP 5, PHP 7, PHP 8)
Iterator::key — Возвращает ключ текущего элемента
У этой функции нет параметров.
Возвращает скалярное значение (scalar) в случае успешного выполнения или null в случае возникновения ошибки.
Создаёт ошибку уровня E_NOTICE в случае возникновения ошибки.
(PHP 5, PHP 7, PHP 8)
Iterator::next — Переходит к следующему элементу
Передвигает текущую позицию к следующему элементу.
Замечание:
Метод вызывается после каждой итерации foreach.
У этой функции нет параметров.
Любое возвращаемое значение игнорируется.
(PHP 5, PHP 7, PHP 8)
Iterator::rewind — Возвращает итератор на первый элемент
Возвращает итератор обратно на первый элемент.
Замечание:
В начале цикла foreach этот метод вызывается первым. Метод не будет вызван после цикла foreach.
У этой функции нет параметров.
Любое возвращаемое значение игнорируется.
(PHP 5, PHP 7, PHP 8)
Iterator::valid — Проверяет корректность текущей позиции
Метод вызывается после функций Iterator::rewind() и Iterator::next() чтобы проверить, допустима ли текущая позиция.
У этой функции нет параметров.
Возвращаемое значение будет приведено к логическому типу (bool) и затем использовано.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PHP 5, PHP 7, PHP 8)
Интерфейс для создания внешнего итератора.
Пример #1 Основы использования
<?php
class myData implements IteratorAggregate {
public $property1 = "Первое общедоступное свойство";
public $property2 = "Второе общедоступное свойство";
public $property3 = "Третье общедоступное свойство";
public $property4 = "";
public function __construct() {
$this->property4 = "последнее свойство";
}
public function getIterator(): Traversable {
return new ArrayIterator($this);
}
}
$obj = new myData;
foreach($obj as $key => $value) {
var_dump($key, $value);
echo "\n";
}
?>Результатом выполнения данного примера будет что-то подобное:
string(9) "property1" string(56) "Первое общедоступное свойство" string(9) "property2" string(56) "Второе общедоступное свойство" string(9) "property3" string(56) "Третье общедоступное свойство" string(9) "property4" string(35) "последнее свойство"
(PHP 5, PHP 7, PHP 8)
IteratorAggregate::getIterator — Получает внешний итератор
У этой функции нет параметров.
Возвращает экземпляр объекта, реализующий Iterator или Traversable
Выбрасывает исключение Exception в случае возникновения ошибки.
(PHP 8)
Класс для упрощения реализации интерфейса IteratorAggregate для внутренних классов.
(PHP 8)
InternalIterator::__construct — Закрытый конструктор для запрета прямой инициализации
У этой функции нет параметров.
(PHP 8)
InternalIterator::current — Возвращает текущий элемент
У этой функции нет параметров.
Возвращает текущий элемент.
(PHP 8)
InternalIterator::key — Возвращает ключ текущего элемента
У этой функции нет параметров.
Возвращает ключ текущего элемента.
(PHP 8)
InternalIterator::next — Переходит к следующему элементу
Перемещает текущую позицию к следующему элементу.
У этой функции нет параметров.
Функция не возвращает значения после выполнения.
(PHP 8)
InternalIterator::rewind — Перематывает итератор к первому элементу
Возвращается к первому элементу итератора.
У этой функции нет параметров.
Функция не возвращает значения после выполнения.
(PHP 8)
InternalIterator::valid — Проверяет, действительна ли текущая позиция
Проверяет, действительна ли текущая позиция.
У этой функции нет параметров.
Возвращает, действительна ли текущая позиция.
(PHP 7, PHP 8)
Throwable является родительским интерфейсом для всех
объектов, выбрасывающихся с помощью выражения throw, включая классы
Error и Exception.
Замечание:
Классы PHP не могут напрямую реализовать интерфейс Throwable. Вместо этого они могут наследовать подкласс Exception.
| Версия | Описание |
|---|---|
| 8.0.0 | Класс Throwable теперь реализует интерфейс Stringable. |
(PHP 7, PHP 8)
Throwable::getMessage — Получает сообщение ошибки
Возвращает сообщение ошибки данного выброшенного объекта.
У этой функции нет параметров.
Возвращает строковое сообщение.
(PHP 7, PHP 8)
Throwable::getCode — Возвращает код исключения
Возвращает код ошибки выброшенного объекта, к которому применена функция.
У этой функции нет параметров.
Возвращает код исключения в виде целого числа (int) в Exception, но возможен и другой возвращаемый тип в классах, наследующих Exception (например, в виде строки (string), если тип ошибки PDOException).
(PHP 7, PHP 8)
Throwable::getFile — Возвращает файл, в котором выброшено исключение
Возвращает имя файла, в котором данный объект был выброшен.
У этой функции нет параметров.
Возвращает строковое значение имени файла.
(PHP 7, PHP 8)
Throwable::getLine — Получает строку скрипта, в которой данный объект был выброшен
Возвращает номер строки, в которой данный объект был выброшен.
У этой функции нет параметров.
Возвращает целочисленное значение строки.
(PHP 7, PHP 8)
Throwable::getTrace — Возвращает трассировку стека
Возвращает трассировку стека в виде массива.
У этой функции нет параметров.
Возвращает трассировку стека в виде массива в таком же формате, что и debug_backtrace().
(PHP 7, PHP 8)
Throwable::getTraceAsString — Получает результаты трассировки стека в виде строки
У этой функции нет параметров.
Возвращает результаты трассировки стека в виде строки.
(PHP 7, PHP 8)
Throwable::getPrevious — Возвращает предыдущий Throwable
Возвращает любой предыдущий Throwable (для примера, переданное третьим параметром в Exception::__construct()).
У этой функции нет параметров.
Возвращает предыдущий Throwable, если он доступен, или
null в противном случае.
(PHP 7, PHP 8)
Throwable::__toString — Получает строковое представление выброшенного объекта
У этой функции нет параметров.
Возвращает строковое (string) представление выброшенного объекта.
(PHP 5, PHP 7, PHP 8)
Интерфейс обеспечивает доступ к объектам в виде массивов.
Пример #1 Основы использования
<?php
class Obj implements ArrayAccess {
public $container = [
"one" => 1,
"two" => 2,
"three" => 3,
];
public function offsetSet($offset, $value): void {
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function offsetExists($offset): bool {
return isset($this->container[$offset]);
}
public function offsetUnset($offset): void {
unset($this->container[$offset]);
}
public function offsetGet($offset): mixed {
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
}
$obj = new Obj;
var_dump(isset($obj["two"]));
var_dump($obj["two"]);
unset($obj["two"]);
var_dump(isset($obj["two"]));
$obj["two"] = "A value";
var_dump($obj["two"]);
$obj[] = 'Append 1';
$obj[] = 'Append 2';
$obj[] = 'Append 3';
print_r($obj);
?>Результатом выполнения данного примера будет что-то подобное:
bool(true)
int(2)
bool(false)
string(7) "A value"
obj Object
(
[container:obj:private] => Array
(
[one] => 1
[three] => 3
[two] => A value
[0] => Append 1
[1] => Append 2
[2] => Append 3
)
)
(PHP 5, PHP 7, PHP 8)
ArrayAccess::offsetExists — Определяет, существует ли заданное смещение (ключ)
Определяет, существует или нет данное смещение (ключ).
Данный метод выполняется при использовании isset() или empty() на объектах, реализующих интерфейс ArrayAccess.
Замечание:
При использовании функции empty(), вызывается метод ArrayAccess::offsetGet() и проверка на пустоту произойдёт, только если метод ArrayAccess::offsetExists() вернёт
true.
offsetСмещение (ключ) для проверки.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Замечание:
Возвращаемое значение будет приведено к логическому типу (bool), если возвращаемое значение не является логическим.
Пример #1 Пример использования ArrayAccess::offsetExists()
<?php
class obj implements ArrayAccess {
public function offsetSet($offset, $value): void {
var_dump(__METHOD__);
}
public function offsetExists($var): bool {
var_dump(__METHOD__);
if ($var == "foobar") {
return true;
}
return false;
}
public function offsetUnset($var): void {
var_dump(__METHOD__);
}
#[\ReturnTypeWillChange]
public function offsetGet($var) {
var_dump(__METHOD__);
return "value";
}
}
$obj = new obj;
echo "Выполняется obj::offsetExists()\n";
var_dump(isset($obj["foobar"]));
echo "\nВыполняется obj::offsetExists() и obj::offsetGet()\n";
var_dump(empty($obj["foobar"]));
echo "\nВыполняется obj::offsetExists(), но *не* obj:offsetGet(), поскольку нечего возвращать\n";
var_dump(empty($obj["foobaz"]));
?>Результатом выполнения данного примера будет что-то подобное:
Выполняется obj::offsetExists() string(17) "obj::offsetExists" bool(true) Выполняется obj::offsetExists() и obj::offsetGet() string(17) "obj::offsetExists" string(14) "obj::offsetGet" bool(false) Выполняется obj::offsetExists(), но *не* obj:offsetGet(), поскольку нечего возвращать string(17) "obj::offsetExists" bool(true)
(PHP 5, PHP 7, PHP 8)
ArrayAccess::offsetGet — Возвращает заданное смещение (ключ)
Возвращает заданное смещение (ключ).
Данный метод выполняется, когда проверяется смещение (ключ) на пустоту с помощью функции empty().
offsetСмещение (ключ) для возврата.
Может возвращать значение любого типа.
Замечание:
Возможна реализация данного метода с возвращением по ссылке. Это делает возможным косвенную модификацию для величин массива перегруженного объекта ArrayAccess.
Явная модификация - это такая модификация, при которой полностью заменяется значение величины массива, как в случае
$obj[6] = 7. С другой стороны, при косвенной модификации заменяется только часть величины, или происходит попытка присвоения величины по ссылке другой переменной, как в случае$obj[6][7] = 7или$var =& $obj[6]. Увеличение с использованием оператора++и уменьшение с использованием оператора--также реализуются с помощью способа, который требует косвенную модификацию.В то время как, явная модификация запускает вызов метода ArrayAccess::offsetSet(), косвенная модификация запускает вызов метода ArrayAccess::offsetGet(). В таком случае, реализация метода ArrayAccess::offsetGet() должна быть в состоянии возвращать результат по ссылке, в противном случае будет вызвано сообщение об ошибке уровня
E_NOTICE.
(PHP 5, PHP 7, PHP 8)
ArrayAccess::offsetSet — Присваивает значение заданному смещению
Присваивает значение указанному смещению (ключу).
offsetСмещение (ключ), которому будет присваиваться значение.
valueЗначение для присвоения.
Функция не возвращает значения после выполнения.
Замечание:
Параметр
offsetбудет установлен вnull, если другое значение недоступно, как показано в следующем примере.<?php
$arrayaccess[] = "первое значение";
$arrayaccess[] = "второе значение";
print_r($arrayaccess);
?>Результат выполнения данного примера:
Array ( [0] => first value [1] => second value )
Замечание:
Данный метод не вызывается при присвоениях по ссылке и других косвенных изменений величин массива перегруженного объекта ArrayAccess (косвенные в том смысле, что они произведены не прямой заменой величины, а путём изменения часть элемента или свойства элемента массива, или присвоением элемента массива по ссылке другой переменой). Вместо этого, вызывается метод ArrayAccess::offsetGet(). Данная операция будет успешна только в том случае, если метод возвращает по ссылке.
(PHP 5, PHP 7, PHP 8)
ArrayAccess::offsetUnset — Удаляет смещение
Удаляет смещение (ключ).
Замечание:
Этот метод не будет вызван при приведении типа к (unset)
offsetСмещение (ключ) для удаления.
Функция не возвращает значения после выполнения.
(PHP 5 >= 5.1.0, PHP 7, PHP 8)
Интерфейс для индивидуальной сериализации.
Классы, реализующие этот интерфейс, больше не поддерживают __sleep() и __wakeup(). Метод serialize вызывается всякий раз, когда необходима сериализация экземпляру класса. Этот метод не вызывает __destruct() и не имеет никаких побочных действий кроме тех, которые запрограммированы внутри него. Когда данные десериализуются, класс известен и соответствующий метод unserialize() вызывается как конструктор вместо вызова __construct(). Если вам необходимо вызвать стандартный конструктор, вы можете это сделать в этом методе.
Начиная с PHP 8.1.0, класс, который реализует Serializable без реализации __serialize() и __unserialize() выдаст предупреждение об устаревании.
Пример #1 Основы использования
<?php
class obj implements Serializable {
private $data;
public function __construct() {
$this->data = "Мои закрытые данные";
}
public function serialize() {
return serialize($this->data);
}
public function unserialize($data) {
$this->data = unserialize($data);
}
public function getData() {
return $this->data;
}
}
$obj = new obj;
$ser = serialize($obj);
var_dump($ser);
$newobj = unserialize($ser);
var_dump($newobj->getData());
?>Результатом выполнения данного примера будет что-то подобное:
string(59) "C:3:"obj":44:{s:36:"Мои закрытые данные";}"
string(36) "Мои закрытые данные"
(PHP 5 >= 5.1.0, PHP 7, PHP 8)
Serializable::serialize — Представляет объект в виде строки
Возвращает строковое представление объекта.
У этой функции нет параметров.
Возвращает строковое представление объекта или null.
Выбрасывает исключение Exception при возвращении типов, отличных от строки или null.
(PHP 5 >= 5.1.0, PHP 7, PHP 8)
Serializable::unserialize — Создаёт объект
$data): voidВызывается во время десериализации объекта.
Замечание:
Метод действует как конструктор объекта. Метод __construct() не вызывается после этого метода.
dataСтроковое представление объекта.
Возвращаемое значение метода игнорируется.
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Класс, используемый для создания анонимных функций.
Анонимные функции выдают объекты этого типа. Класс получил методы, позволяющие контролировать анонимную функцию после её создания.
Кроме методов, описанных здесь, этот класс также имеет метод __invoke.
Данный метод необходим только для совместимости с другими классами, в которых
реализован магический вызов, так как
этот метод не используется при вызове функции.
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Closure::__construct — Конструктор, запрещающий создание экземпляра
Этот метод существует только, чтобы запретить создание новых объектов класса Closure. Объекты этого класса создаются способом, описанным на странице анонимных функций.
У этой функции нет параметров.
(PHP 5 >= 5.4.0, PHP 7, PHP 8)
Closure::bind — Дублирует замыкание с указанием конкретного связанного объекта и области видимости класса
$closure, ?object $newThis, object|string|null $newScope = "static"): ?ClosureЭтот метод является статическим вариантом Closure::bindTo(). Смотрите документацию к указанному методу для подробной информации.
closureАнонимная функция для привязывания к объекту.
newThis
Объект, к которому будет привязана переданная анонимная функция, или
null для отсоединения функции от её текущего объекта.
newScopeОбласть видимости класса, с которой должно быть связано замыкание или 'static' для сохранения текущей области видимости. Если передан объект, то будет использован его класс. Этот параметр определяет видимость protected (защищённых) и private (закрытых) методов привязанного объекта. Запрещено в качестве этого параметра передавать (объектом) внутренний класс.
Возвращает новый объект Closure или null в случае возникновения ошибки.
Пример #1 Пример Closure::bind()
<?php
class A {
private static $sfoo = 1;
private $ifoo = 2;
}
$cl1 = static function() {
return A::$sfoo;
};
$cl2 = function() {
return $this->ifoo;
};
$bcl1 = Closure::bind($cl1, null, 'A');
$bcl2 = Closure::bind($cl2, new A(), 'A');
echo $bcl1(), "\n";
echo $bcl2(), "\n";
?>Результатом выполнения данного примера будет что-то подобное:
1 2
(PHP 5 >= 5.4.0, PHP 7, PHP 8)
Closure::bindTo — Дублирует замыкание с указанием связанного объекта и области видимости класса
Создаёт и возвращает новую анонимную функцию с тем же телом функции и связанными переменными, но с другим связанным объектом или новой областью видимости класса.
"Связанный объект" определяет значение $this,
которое будет доступно в теле функции, а "область видимости класса"
представляет собой класс, который определяет к каким protected (защищённым)
и private (закрытым) элементам этого объекта будет иметь доступ анонимная функция.
Если точнее, то это те элементы, как если бы анонимная функция была бы
методом класса, переданного в параметре newScope.
Статические замыкания не могут иметь привязанный объект (значение параметра
newThis должно быть равно null), но эта функция может всё равно
использоваться для изменения его области видимости класса.
Данный метод гарантирует, что у нестатического замыкания с привязанным
объектом будет задана область видимости и наоборот.
Для выполнения этого условия применяются следующие правила:
Для нестатического замыкания с указанной областью видимости и с null
вместо объекта, будет создано статическое замыкание.
Для нестатического замыкания с незаданной областью видимости, но с указанием
объекта, создаётся замыкание с неуказанной областью видимости.
Замечание:
Если вам необходимо только дублировать анонимную функцию, то вы можете вместо данного метода использовать клонирование.
newThis
Объект, к которому будет привязана переданная анонимная функция, или
null для отсоединения замыкания от её текущего объекта.
newScopeОбласть видимости класса, с которой должно быть связано замыкание или 'static' для сохранения текущей области видимости. Если передан объект, то будет использован его класс. Этот параметр определяет видимость protected (защищённых) и private (закрытых) методов привязанного объекта. Запрещается передавать в этот параметр внутренний класс (объект класса).
Возвращает новый объект Closure
или null в случае возникновения ошибки.
Пример #1 Пример Closure::bindTo()
<?php
class A {
private $val;
function __construct($val) {
$this->val = $val;
}
function getClosure() {
//возвращает замыкание, связанное с текущими объектом и областью видимости
return function() { return $this->val; };
}
}
$ob1 = new A(1);
$ob2 = new A(2);
$cl = $ob1->getClosure();
echo $cl(), "\n";
$cl = $cl->bindTo($ob2);
echo $cl(), "\n";
?>Результатом выполнения данного примера будет что-то подобное:
1 2
(PHP 7, PHP 8)
Closure::call — Связывает и запускает замыкание
Временно связывает замыкание с newThis и вызывает его с
заданными параметрами.
newThisОбъект (object) для привязки к замыканию на время его вызова.
argsНоль или больше параметров, которые передаются замыканию.
Возвращает возвращаемое значение замыкания
Пример #1 Пример Closure::call()
<?php
class Value {
protected $value;
public function __construct($value) {
$this->value = $value;
}
public function getValue() {
return $this->value;
}
}
$three = new Value(3);
$four = new Value(4);
$closure = function ($delta) { var_dump($this->getValue() + $delta); };
$closure->call($three, 4);
$closure->call($four, 4);
?>Результат выполнения данного примера:
int(7) int(8)
(PHP 7 >= 7.1.0)
Closure::fromCallable — Конвертирует callable в замыкание
Создаёт и возвращает новую анонимную
функцию из заданного callback, используя текущую
область видимости. Этот метод проверяет, что callback является
типом callable в текущей области видимости и выбрасывает исключение
TypeError, если это не так.
Замечание:
Начиная с PHP 8.1.0, у Callback-функций как объектов первого класса та же семантика, что и у этого метода.
callbackОбъект типа callable.
Возвращает новый объект класса Closure или выбрасывает
исключение TypeError, если callback
не является объектом типа callable в текущей области видимости.
(PHP 4, PHP 5, PHP 7, PHP 8)
Пустой класс общего назначения с динамическими свойствами.
Объекты класса могут быть инициализированы с помощью оператора new или созданы с помощью преобразования в объект. Некоторые функции PHP также создают экземпляры этого класса, например, функции json_decode(), mysqli_fetch_object() или PDOStatement::fetchObject().
Несмотря на отсутствие реализации магических методов
__get()/__set(),
класс позволяет использовать динамические свойства
и не требует атрибута #[\AllowDynamicProperties].
Это не базовый класс, поскольку в PHP нет понятия универсального базового класса. Однако можно создать пользовательский класс, который расширяет stdClass и в результате наследует функциональность динамических свойств.
У класса нет методов или свойств по умолчанию.
Пример #1 Создание в результате преобразования в объект
<?php
$obj = (object) array('foo' => 'bar');
var_dump($obj);Результат выполнения данного примера:
object(stdClass)#1 (1) {
["foo"]=>
string(3) "bar"
}
Пример #2 Создание в результате работы функции json_decode()
<?php
$json = '{"foo":"bar"}';
var_dump(json_decode($json));Результат выполнения данного примера:
object(stdClass)#1 (1) {
["foo"]=>
string(3) "bar"
}
Пример #3 Объявление динамических свойств
<?php
$obj = new stdClass();
$obj->foo = 42;
$obj->{1} = 42;
var_dump($obj);Результат выполнения данного примера:
object(stdClass)#1 (2) {
["foo"]=>
int(42)
["1"]=>
int(42)
}
(PHP 5 >= 5.5.0, PHP 7, PHP 8)
Создание объектов типа Generator описано в разделе Генераторы.
Объекты Generator не могут быть созданы с помощью оператора new.
Смотрите также раздел Итераторы объектов.
(PHP 5 >= 5.5.0, PHP 7, PHP 8)
Generator::current — Получить текущее значение генератора
У этой функции нет параметров.
Возвращает текущее значение.
(PHP 7, PHP 8)
Generator::getReturn — Получить значение, возвращаемое генератором
У этой функции нет параметров.
Получает возвращаемое значение генератора, после его завершения.
Пример #1 Пример использования Generator::getReturn()
<?php
$gen = (function() {
yield 1;
yield 2;
return 3;
})();
foreach ($gen as $val) {
echo $val, PHP_EOL;
}
echo $gen->getReturn(), PHP_EOL;Результат выполнения данного примера:
1 2 3
(PHP 5 >= 5.5.0, PHP 7, PHP 8)
Generator::key — Получить ключ сгенерированного элемента
У этой функции нет параметров.
Возвращает ключ сгенерированного элемента.
Пример #1 Пример использования Generator::key()
<?php
function Gen()
{
yield 'key' => 'value';
}
$gen = Gen();
echo "{$gen->key()} => {$gen->current()}";Результат выполнения данного примера:
key => value
(PHP 5 >= 5.5.0, PHP 7, PHP 8)
Generator::next — Возобновить работу генератора
Вызов Generator::next()
имеет тот же эффект, что и вызов
Generator::send() с null
в качестве аргумента.
У этой функции нет параметров.
Функция не возвращает значения после выполнения.
(PHP 5 >= 5.5.0, PHP 7, PHP 8)
Generator::rewind — Перемотать итератор
Если итерация уже начата, то выбрасывает исключение.
У этой функции нет параметров.
Функция не возвращает значения после выполнения.
(PHP 5 >= 5.5.0, PHP 7, PHP 8)
Generator::send — Передать значение в генератор
Передача заданного значения в генератор как результат текущего выражения yield и возобновление его работы.
Если генератор ещё не дошёл до первого вызова оператора yield, он выполнится до момента первого вызова yield, прежде чем передаст в него значение. Так что нет необходимости вызывать генератор с помощью Generator::next() перед вызовом этого метода (как это делается в Python).
valueЗначение, которое отправляется в генератор. Это значение будет текущим возвращаемым значением выражения yield генератора.
Возвращает сгенерированное значение.
Пример #1 Использование Generator::send() для внедрения значений
<?php
function printer() {
echo "I'm printer!".PHP_EOL;
while (true) {
$string = yield;
echo $string.PHP_EOL;
}
}
$printer = printer();
$printer->send('Hello world!');
$printer->send('Bye world!');
?>Результат выполнения данного примера:
I'm printer! Hello world! Bye world!
(PHP 5 >= 5.5.0, PHP 7, PHP 8)
Generator::throw — Бросить исключение в генератор
Выбрасывает исключение в генератор и возобновляет его выполнение.
Поведение будет таким, как будто текущее значение yield заменили на
выражение throw $exception.
Если к моменту вызова этого метода генератор закрыт, исключение будет выброшено в контексте вызывающего кода.
exceptionИсключение, которое надо выбросить в генератор.
Возвращает сгенерированное значение.
Пример #1 Выбрасывание исключения в итератор
<?php
function gen() {
echo "Foo\n";
try {
yield;
} catch (Exception $e) {
echo "Exception: {$e->getMessage()}\n";
}
echo "Bar\n";
}
$gen = gen();
$gen->rewind();
$gen->throw(new Exception('Test'));
?>Результат выполнения данного примера:
Foo Exception: Test Bar
(PHP 5 >= 5.5.0, PHP 7, PHP 8)
Generator::valid — Проверка, закрыт ли итератор
У этой функции нет параметров.
Возвращает false, если итератор закрыт и true в обратном случае.
(PHP 5 >= 5.5.0, PHP 7, PHP 8)
Generator::__wakeup — Callback-функция сериализации
Выбрасывает исключение, поскольку генераторы не могут быть сериализованы.
У этой функции нет параметров.
Функция не возвращает значения после выполнения.
(PHP 8 >= 8.1.0)
Файберы представляют собой прерываемые функции полного цикла. Файберы могут быть приостановлены из любого места цикла, приостанавливая выполнение в файбере до тех пор, пока файбер не будет возобновлён в будущем.
(PHP 8 >= 8.1.0)
Fiber::__construct — Создаёт новый экземпляр Fiber
callbackcallable-функция для вызова при запуске файбера. Аргументы для Fiber::start() будут предоставляется в качестве аргументов для данного вызываемого объекта.
(PHP 8 >= 8.1.0)
Fiber::start — Начинает выполнение файбера
Переменный список аргументов, передаваемый вызываемому объекту, используемый при построении файбера.
Если при вызове метода файбер уже был запущен, будет выброшено FiberError.
argsАргументы, которые следует использовать при вызове вызываемого объекта, передаваемого конструктору файбера.
Значение, предоставленное при первом вызове Fiber::suspend() или null в случае возврата файбера.
Если файбер выбросил исключение перед приостановкой, оно будет выброшено из вызова этого метода.
(PHP 8 >= 8.1.0)
Fiber::resume — Возобновляет выполнение файбера со значением
Возобновляет файбер, используя заданное значение в результате текущего вызова Fiber::suspend().
Если файбер не приостановлен при вызове метода, будет выброшена ошибка FiberError.
valueЗначение для возобновления файбера. Значение будет возвращаемым значением текущего вызова Fiber::suspend().
Значение, предоставленное для следующего вызова Fiber::suspend() или null в случае возврата файбера.
Если файбер выбросил исключение перед приостановкой, оно будет выброшено из вызова этого метода.
(PHP 8 >= 8.1.0)
Fiber::throw — Возобновляет выполнение файбера с исключением
Возобновляет выполнение файбера, выбрасывая данное исключение из текущего вызова Fiber::suspend().
Если файбер не приостановлен при вызове метода, будет выброшена ошибка FiberError.
exceptionИсключение, которое нужно передать в файбер из текущего вызова Fiber::suspend().
Значение, предоставленное при первом вызове Fiber::suspend() или null в случае возврата файбера.
Если файбер выбросил исключение перед приостановкой, оно будет выброшено из вызова этого метода.
(PHP 8 >= 8.1.0)
Fiber::getReturn — Получает значение, возвращаемое файбером
У этой функции нет параметров.
Возвращает значение, возвращаемое callable-функцией, предоставленной в Fiber::__construct(). Если файбер не вернул значение, либо потому, что он не было запущен, либо не был завершён, либо выбросил исключение, будет выброшено исключение FiberError.
(PHP 8 >= 8.1.0)
Fiber::isStarted — Определяет, запущен ли файбер
У этой функции нет параметров.
Возвращает true только после того, как файбер был запущен,
в противном случае возвращает false.
(PHP 8 >= 8.1.0)
Fiber::isSuspended — Определяет, приостановлен ли файбер
У этой функции нет параметров.
Возвращает true, если файбер в данный момент приостановлен,
в противном случае возвращает false.
(PHP 8 >= 8.1.0)
Fiber::isRunning — Определяет, работает ли файбер
У этой функции нет параметров.
Возвращает true только если файбер работает. Файбер считается работающим после вызова
Fiber::start(), Fiber::resume() или
Fiber::throw(), который ещё не был возвращён.
Возвращает false, если файбер не работает.
(PHP 8 >= 8.1.0)
Fiber::isTerminated — Определяет, завершён ли файбер
У этой функции нет параметров.
Возвращает true только после того, как файбер завершился, либо путём возврата, либо выбросив исключение,
в противном случае возвращает false.
(PHP 8 >= 8.1.0)
Fiber::suspend — Приостанавливает выполнение текущего файбера
Приостанавливает выполнение текущего файбера. Значение, предоставленное этому методу, будет возвращено из вызова Fiber::start(), Fiber::resume() или Fiber::throw(), который переключил выполнение текущего файбера.
Когда выполнение файбера возобновляется, метод возвращает значение, предоставленное в Fiber::resume(). Если выполнение файбера возобновляется с использованием Fiber::throw, исключение, переданное этому методу, будет выброшено при вызове метода.
Если этот метод вызывается извне файбера, будет выброшена ошибка FiberError.
valueЗначение, возвращаемое при вызове Fiber::start(), Fiber::resume() или Fiber::throw(), которые переключают выполнение текущего файбера.
Значение, предоставленное Fiber::resume().
(PHP 8 >= 8.1.0)
Fiber::getCurrent — Получает текущий выполняющийся экземпляр Fiber
У этой функции нет параметров.
Возвращает выполняющийся в данный момент экземпляр Fiber
или null, если метод вызывается извне файбера.
(PHP 7 >= 7.4.0, PHP 8)
Класс WeakReference предоставляет способ доступа к объекту, не влияя при этом на количество ссылок на него, таким образом сборщик мусора сможет освободить этот объект.
Объект класса WeakReference не может быть сериализован.
Пример #1 Пример #1. Простое использование WeakReference
<?php
$obj = new stdClass;
$weakref = WeakReference::create($obj);
var_dump($weakref->get());
unset($obj);
var_dump($weakref->get());
?>Результатом выполнения данного примера будет что-то подобное:
object(stdClass)#1 (0) {
}
NULL
(PHP 7 >= 7.4.0, PHP 8)
WeakReference::__construct — Конструктор, который запрещает реализацию
Метод существует только для запрета создания экземпляров класса WeakReference. Слабые ссылки должны быть созданы с помощью фабричного метода WeakReference::create().
У этой функции нет параметров.
(PHP 7 >= 7.4.0, PHP 8)
WeakReference::create — Создаёт новую слабую ссылку
Создаёт новый WeakReference.
objectОбъект для слабой ссылки.
Возвращает только что созданный объект.
(PHP 7 >= 7.4.0, PHP 8)
WeakReference::get — Получает объект со слабой ссылкой
Получает объект со слабой ссылкой.
Если объект уже был уничтожен, возвращается null.
У этой функции нет параметров.
Возвращает ссылку object или null, если объект был уничтожен.
(PHP 8)
WeakMap - это коллекция (map) или словарь, который принимает объекты в качестве ключей. Однако, в отличие от аналогичного в остальном SplObjectStorage, объект в ключе WeakMap не влияет на счётчик ссылок объекта. То есть, если в какой-то момент единственной оставшейся ссылкой на объект является ключ WeakMap, объект будет собран сборщиком мусора и удалён из WeakMap. Его основной вариант использования - создание кешей данных, полученных из объекта, которым не нужно жить дольше, чем объект.
WeakMap реализует ArrayAccess, Iterator и Countable, поэтому в большинстве случаев его можно использовать так же, как ассоциативный массив.
Пример #1 Пример использования Weakmap
<?php
$wm = new WeakMap();
$o = new stdClass;
class A {
public function __destruct() {
echo "Уничтожено!\n";
}
}
$wm[$o] = new A;
var_dump(count($wm));
echo "Сброс...\n";
unset($o);
echo "Готово\n";
var_dump(count($wm));Результат выполнения данного примера:
int(1) Сброс... Уничтожено! Готово int(0)
(PHP 8)
WeakMap::count — Подсчитывает количество живых записей в коллекции (map)
Подсчитывает количество живых записей в коллекции (map).
У этой функции нет параметров.
Возвращает количество живых записей в коллекции (map).
(PHP 8)
WeakMap::getIterator — Получает внешний итератор
У этой функции нет параметров.
Экземпляр объекта, реализующего Iterator или Traversable
Выбрасывает Exception в случае возникновения ошибки.
(PHP 8)
WeakMap::offsetExists — Проверяет, есть ли в коллекции (map) определённый объект
$object): boolПроверяет, есть ли ссылка на переданный объект в коллекции (map).
objectОбъект для проверки.
Возвращает true, если объект содержится в коллекции (map) или false в противном случае.
(PHP 8)
WeakMap::offsetGet — Возвращает значение, на которое указывает определённый объект
Возвращает значение, на которое указывает определённый объект.
objectКакой-то объект содержится в качестве ключа в коллекции (map).
Возвращает значение, связанное с объектом, переданным в качестве аргумента
или null в противном случае.
(PHP 8)
WeakMap::offsetSet — Обновляет коллекцию (map) новой парой ключ-значение
Обновляет коллекцию (map) новой парой ключ-значение. Если ключ уже существует в коллекции, старое значение заменяется новым.
objectОбъект, служащий ключом пары ключ-значение.
valueПроизвольные данные, служащие значением пары ключ-значение.
Функция не возвращает значения после выполнения.
(PHP 8)
WeakMap::offsetUnset — Удаляет запись из коллекции (map)
$object): voidУдаляет запись из коллекции (map).
objectОбъект, служащий ключом для записи, которую нужно удалить из коллекции.
Функция не возвращает значения после выполнения.
(PHP 8)
Интерфейс Stringable обозначает класс, реализующий метод __toString(). В отличие от большинства интерфейсов, Stringable неявно присутствует в любом классе, в котором определён магический метод __toString(), хотя он может и должен быть объявлен явно.
Его основное значение - разрешить функциям выполнять проверку типа на соответствие типу union
string|Stringable, чтобы принимать либо строковый примитив,
либо объект, который может быть преобразован в строку.
Пример #1 Простой пример использования Stringable
<?php
class IPv4Address implements Stringable {
private string $oct1;
private string $oct2;
private string $oct3;
private string $oct4;
public function __construct(string $oct1, string $oct2, string $oct3, string $oct4) {
$this->oct1 = $oct1;
$this->oct2 = $oct2;
$this->oct3 = $oct3;
$this->oct4 = $oct4;
}
public function __toString(): string {
return "$this->oct1.$this->oct2.$this->oct3.$this->oct4";
}
}
function showStuff(string|Stringable $value) {
// Здесь Stringable будет преобразован в строку путем вызова
// __toString.
print $value;
}
$ip = new IPv4Address('123', '234', '42', '9');
showStuff($ip);
?>Результатом выполнения данного примера будет что-то подобное:
123.234.42.9
(PHP 8)
Stringable::__toString — Получает строковое представление объекта
У этой функции нет параметров.
Возвращает строковое (string) представление объекта.
(PHP 8 >= 8.1.0)
Интерфейс UnitEnum автоматически применяется движком ко всем перечислениям. Он не может быть реализован пользовательскими классами. Перечисления не могут переопределять его методы, поскольку реализации по умолчанию предоставляются движком. Доступен только для проверки типа.
(PHP 8 >= 8.1.0)
UnitEnum::cases — Возвращает список вариантов перечисления
Метод возвращает упакованный массив всех вариантов перечисления в порядке объявления.
У этой функции нет параметров.
Массив всех определённых вариантов перечисления в порядке объявления.
Пример #1 Простой пример использования
В следующем примере показано, как возвращаются варианты перечисления.
<?php
enum Suit
{
case Hearts;
case Diamonds;
case Clubs;
case Spades;
}
var_dump(Suit::cases());
?>Результат выполнения данного примера:
array(4) {
[0]=>
enum(Suit::Hearts)
[1]=>
enum(Suit::Diamonds)
[2]=>
enum(Suit::Clubs)
[3]=>
enum(Suit::Spades)
}
(PHP 8 >= 8.1.0)
Интерфейс BackedEnum автоматически применяется движком к типизированным перечислениям. Он не может быть реализован пользовательскими классами. Перечисления не могут переопределять его методы, поскольку реализации по умолчанию предоставляются движком. Доступен только для проверки типа.
(PHP 8 >= 8.1.0)
BackedEnum::from — Сопоставляет скаляр с экземпляром перечисления
$value): staticМетод from() переводит строку (string) или число (int) в соответствующее значение перечисления, если такое имеется. Если соответствующее значение не определено, выбрасывается ValueError.
valueСкалярное значение для сопоставления с перечислением.
Случайный экземпляр этого перечисления.
Пример #1 Простой пример использования
В следующем примере показано, как возвращаются варианты перечисления.
<?php
enum Suit: string
{
case Hearts = 'H';
case Diamonds = 'D';
case Clubs = 'C';
case Spades = 'S';
}
$h = Suit::from('H');
var_dump($h);
$b = Suit::from('B');
?>Результат выполнения данного примера:
enum(Suit::Hearts) Fatal error: Uncaught ValueError: "B" is not a valid backing value for enum "Suit" in /file.php:15
(PHP 8 >= 8.1.0)
BackedEnum::tryFrom — Сопоставляет скаляр с экземпляром перечисления или null
$value): ?staticМетод tryFrom() переводит строку (string) или число (int) в соответствующее значение перечисления, если такое имеется. Если соответствующее значение не определено, возвращается null.
valueСкалярное значение для сопоставления с перечислением.
Экземпляр перечисления или null, если экземпляр не найден.
Пример #1 Простой пример использования
В следующем примере показано, как возвращаются варианты перечисления.
<?php
enum Suit: string
{
case Hearts = 'H';
case Diamonds = 'D';
case Clubs = 'C';
case Spades = 'S';
}
$h = Suit::tryFrom('H');
var_dump($h);
$b = Suit::tryFrom('B') ?? Suit::Spades;
var_dump($b);
?>Результат выполнения данного примера:
enum(Suit::Hearts) enum(Suit::Spades)
(PHP 8 >= 8.2.0)
Класс SensitiveParameterValue позволяет обернуть чувствительные значения, чтобы защитить их от случайного раскрытия.
Значения параметров с атрибутом SensitiveParameter будут автоматически обёрнуты внутри объекта SensitiveParameterValue в трассировках стека.
Чувствительное значение, которое необходимо защитить от случайного воздействия.
(PHP 8 >= 8.2.0)
SensitiveParameterValue::__construct — Создаёт новый объект SensitiveParameterValue
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
valueПроизвольное значение, которое должно храниться внутри объекта SensitiveParameterValue.
(PHP 8 >= 8.2.0)
SensitiveParameterValue::__debugInfo — Защита чувствительных значений от случайного воздействия
Возвращает пустой массив (array) для защиты чувствительного значения от случайного раскрытия при использовании функции var_dump().
У этой функции нет параметров.
Пустой массив (array).
Пример #1 Передача объекта SensitiveParameterValue в функцию var_dump()
<?php
$s = new \SensitiveParameterValue('secret');
var_dump($s);
?>Результат выполнения данного примера:
object(SensitiveParameterValue)#1 (0) {
}
(PHP 8 >= 8.2.0)
SensitiveParameterValue::getValue — Возвращает чувствительное значение
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
Чувствительное значение.
Пример #1 Пример использования SensitiveParameterValue::getValue()
<?php
$s = new \SensitiveParameterValue('secret');
echo "Защищённое значение: ", $s->getValue(), "\n";
?>Результат выполнения данного примера:
Защищённое значение: secret
PHP предоставляет некоторые предопределённые атрибуты, которые можно использовать.
(PHP 8)
Атрибуты дают возможность добавлять структурированную, машиночитаемую информацию метаданных о декларациях в коде: целью атрибута могут быть классы, методы, функции, параметры, свойства и константы класса. Метаданные, определённые атрибутами, могут быть проверены во время выполнения с помощью Reflection API. Поэтому атрибуты можно рассматривать как язык конфигурации, встроенный непосредственно в код.
Attribute::TARGET_CLASSAttribute::TARGET_FUNCTIONAttribute::TARGET_METHODAttribute::TARGET_PROPERTYAttribute::TARGET_CLASS_CONSTANTAttribute::TARGET_PARAMETERAttribute::TARGET_ALLAttribute::IS_REPEATABLE(PHP 8)
Attribute::__construct — Создаёт новый экземпляр Attribute
$flags = Attribute::TARGET_ALL)Создаёт новый экземпляр Attribute.
flags
(PHP 8 >= 8.2.0)
Атрибут используется для маркировки классов, которые позволяют использовать динамические свойства.
Динамические свойства устарели, начиная с PHP 8.2.0, поэтому их использование без маркировки класса этим атрибутом приведёт к появлению уведомления об устаревании.
<?php
class DefaultBehaviour { }
#[\AllowDynamicProperties]
class ClassAllowsDynamicProperties { }
$o1 = new DefaultBehaviour();
$o2 = new ClassAllowsDynamicProperties();
$o1->nonExistingProp = true;
$o2->nonExistingProp = true;
?>Результат выполнения данного примера в PHP 8.2:
Deprecated: Creation of dynamic property DefaultBehaviour::$nonExistingProp is deprecated in file on line 10
(PHP 8 >= 8.2.0)
AllowDynamicProperties::__construct — Создаёт новый экземпляр атрибута AllowDynamicProperties
Создаёт новый экземпляр AllowDynamicProperties.
У этой функции нет параметров.
(PHP 8 >= 8.1.0)
Большинство неокончательных внутренних методов теперь требуют, чтобы переопределяющие
методы объявляли совместимый тип возвращаемого значения, иначе при проверке наследования
будет выдано уведомление об устаревании.
В случае если тип возвращаемого значения не может быть объявлен для переопределяемого метода
из-за проблем совместимости с кросс-версиями PHP, может быть добавлен атрибут #[\ReturnTypeWillChange],
чтобы заглушить уведомление об устаревании.
(PHP 8 >= 8.1.0)
ReturnTypeWillChange::__construct — Создаёт новый экземпляр атрибута ReturnTypeWillChange
У этой функции нет параметров.
(PHP 8 >= 8.2.0)
Атрибут используется для обозначения параметра, который является чувствительным и его значение должно быть отредактировано, если оно присутствует в трассировке стека.
<?php
function defaultBehavior(
string $secret,
string $normal
) {
throw new Exception('Error!');
}
function sensitiveParametersWithAttribute(
#[\SensitiveParameter]
string $secret,
string $normal
) {
throw new Exception('Error!');
}
try {
defaultBehavior('password', 'normal');
} catch (Exception $e) {
echo $e, PHP_EOL, PHP_EOL;
}
try {
sensitiveParametersWithAttribute('password', 'normal');
} catch (Exception $e) {
echo $e, PHP_EOL, PHP_EOL;
}
?>Результат выполнения данного примера в PHP 8.2 аналогичен:
Exception: Error! in example.php:7
Stack trace:
#0 example.php(19): defaultBehavior('password', 'normal')
#1 {main}
Exception: Error! in example.php:15
Stack trace:
#0 example.php(25): sensitiveParametersWithAttribute(Object(SensitiveParameterValue), 'normal')
#1 {main}
(PHP 8 >= 8.2.0)
SensitiveParameter::__construct — Создаёт новый экземпляр атрибута SensitiveParameter
У этой функции нет параметров.
PHP предлагает различные контекстные опции и параметры, которые могут быть использованы со всеми файловыми системами и обёртками потоков. Контекст создаётся с помощью функции stream_context_create(). Опции устанавливаются с помощью stream_context_set_option(), а параметры с помощью stream_context_set_params().
Контекстные опции сокета — Список контекстных опций сокета
Контекстные опции доступны для всех обёрток, которые работают через сокеты, такие как
tcp, http и
ftp.
| Версия | Описание |
|---|---|
| 7.1.0 |
Добавлено tcp_nodelay.
|
| 7.0.1 |
Добавлено ipv6_v6only.
|
Пример #1 Пример использования bindto
<?php
// Соединение с сетью, используя IP '192.168.0.100'
$opts = array(
'socket' => array(
'bindto' => '192.168.0.100:0',
),
);
// Соединение с сетью, используя IP '192.168.0.100' и порт '7000'
$opts = array(
'socket' => array(
'bindto' => '192.168.0.100:7000',
),
);
// Соединение с сетью, используя IPv6 адрес '2001:db8::1'
// и порт '7000'
$opts = array(
'socket' => array(
'bindto' => '[2001:db8::1]:7000',
),
);
// Соединение с сетью через порт '7000'
$opts = array(
'socket' => array(
'bindto' => '0:7000',
),
);
// Создаём контекст...
$context = stream_context_create($opts);
// ...и используем его для получения данных
echo file_get_contents('http://www.example.com', false, $context);
?>Опции контекста HTTP — Список опций контекста HTTP
Опции контекста для транспортных протоколов http:// и
https://.
Пример #1 Извлечь страницу и отправить данные методом POST
<?php
$postdata = http_build_query(
array(
'var1' => 'некоторое содержимое',
'var2' => 'doh'
)
);
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $postdata
)
);
$context = stream_context_create($opts);
$result = file_get_contents('http://example.com/submit.php', false, $context);
?>
Пример #2 Игнорировать переадресации, но извлечь заголовки и содержимое
<?php
$url = "http://www.example.org/header.php";
$opts = array('http' =>
array(
'method' => 'GET',
'max_redirects' => '0',
'ignore_errors' => '1'
)
);
$context = stream_context_create($opts);
$stream = fopen($url, 'r', false, $context);
// информация о заголовках, а также
// метаданные о потоке
var_dump(stream_get_meta_data($stream));
// актуальная информация по ссылке $url
var_dump(stream_get_contents($stream));
fclose($stream);
?>Замечание: Опции контекста нижележащего потока в сокете
Дополнительные опции контекста могут поддерживаться нижележащим транспортным протоколом. Для потоковhttp://, это относится к опциям контекста для транспортного протоколаtcp://. Для потоковhttps://, это относится к опциям контекста для транспортного протоколаssl://.
Замечание: Строка статуса HTTP
Когда эта обёртка потока следует по переадресации,wrapper_data, возвращаемый функцией stream_get_meta_data(), необязательно содержит строку статуса HTTP, которая на самом деле относится к содержанию данных по индексу0.Первый запрос вернул кодarray ( 'wrapper_data' => array ( 0 => 'HTTP/1.0 301 Moved Permanently', 1 => 'Cache-Control: no-cache', 2 => 'Connection: close', 3 => 'Location: http://example.com/foo.jpg', 4 => 'HTTP/1.1 200 OK', ...301(постоянное перенаправление), так что обёртка потока автоматически последовала этому перенаправлению, чтобы получить ответ200(индекс =4).
Параметры контекста FTP — Список параметров контекста FTP
Параметры контекста для транспортных протоколов ftp:// и ftps://
Замечание: Опции контекста нижележащего потока в сокете
Дополнительные опции контекста могут поддерживаться нижележащим транспортным протоколом. Для потоковftp://, это относится к опциям контекста для транспортного протоколаtcp://. Для потоковftps://, это относится к опциям контекста для транспортного протоколаssl://.
Опции контекста SSL — Список опций контекста SSL
Опции контекста для протоколов ssl:// и tls://
| Версия | Описание |
|---|---|
| 7.2.0 |
Добавлен security_level. Требуется OpenSSL >= 1.1.0.
|
Замечание: Так как
ssl://- это нижележащий транспортный протокол для обёртокhttps://иftps://, то любые опции контекста, которые применяются кssl://будут также применяться кhttps://иftps://.
Замечание: Чтобы была доступна возможность указания имени сервера (SNI, Server Name Indication), PHP должен быть скомпилирован с OpenSSL 0.9.8j или более поздней. Используйте константу
OPENSSL_TLSEXT_SERVER_NAMEчтобы определить, поддерживается ли SNI.
Контекстные опции Phar — Список контекстных опций Phar
Контекстные опции для обёртки phar://.
Параметры контекста — Список параметров контекста
Данные параметры могут быть заданы для контекста с помощью функции stream_context_set_params().
Опции контекста Zip — Список опций контекста Zip
Опции контекста Zip доступны для обёрток zip.
| Версия | Описание |
|---|---|
| PHP 7.2.0, PECL zip 1.14.0 |
Добавлен параметр password.
|
Пример #1 Простой пример использования password
<?php
// Читаем зашифрованный архив
$opts = array(
'zip' => array(
'password' => 'secret',
),
);
// создаём контекст...
$context = stream_context_create($opts);
// ...и используем его для получения данных
echo file_get_contents('zip://test.zip#test.txt', false, $context);
?>Zlib context options — Перечисление опций контекста Zlib
Опции контекста Zlib доступны для обёрток zlib.
| Версия | Описание |
|---|---|
| 7.3.0 |
Добавлен параметр level.
|
PHP поставляется со множеством встроенных обёрток для различных URL-протоколов для использования с функциями файловой системы, таких как fopen(), copy(), file_exists() и filesize(). В дополнение к этим обёрткам, можно регистрировать собственные обёртки, используя функцию stream_wrapper_register().
Замечание: URL синтаксис, используемый для описания обёртки, может быть только вида
scheme://.... Варианты синтаксисаscheme:/иscheme:не поддерживаются.
file:// — Доступ к локальной файловой системе
Файловая система - это стандартная обёртка для PHP, представляющая файловую систему на локальном компьютере. Когда задан относительный путь (путь, который не начинается с символов "/", "\", "\\" или с буквы жёсткого диска в Windows), он будет применён к текущей рабочей директории. В большинстве случаев это директория, в которой находится сценарий, если она не была изменена. При использовании CLI SAPI директорией по умолчанию будет та, из которой вызвано исполнение сценария.
В некоторых функциях, таких как fopen() и file_get_contents(),
поиск файла может дополнительно производиться в include_path.
http:// -- https:// — Доступ к URL-адресам по протоколу HTTP(s)
Предоставляет доступ только для чтения файлов/ресурсов через HTTP.
По умолчанию используется HTTP 1.0 GET. Для поддержки виртуальных хостов на основе имён
вместе с запросом посылается заголовок Host:.
Если вы сконфигурировали строку
user_agent, используя
ваш файл php.ini или контекст потока, то она также будет включена
в запрос.
Этот поток также позволяет получить доступ к содержимому ресурса; заголовки сохраняются в переменной $http_response_header.
Если важно знать URL, с которого был получен документ (после всех переадресаций, которые были произведены), то вам необходимо обработать серию заголовков ответов, возвращаемых потоком.
INI-директива from будет использоваться для заголовка
From:, если установлена и не переопределена в контексте
Контекстные опции и параметры.
Пример #1 Определение URL, с которого был забран документ после переадресаций
<?php
$url = 'http://www.example.com/redirecting_page.php';
$fp = fopen($url, 'r');
$meta_data = stream_get_meta_data($fp);
foreach ($meta_data['wrapper_data'] as $response) {
/* Были ли мы переадресованы? */
if (strtolower(substr($response, 0, 10)) == 'location: ') {
/* Сохранить в $url адрес, куда нас переадресовали */
$url = substr($response, 10);
}
}
?>Замечание: Протокол HTTPS поддерживается только когда модуль openssl включён.
Соединения HTTP предназначены только для чтения; запись данных или копирование файлов в HTTP-ресурс не поддерживается.
Отправка запросов POST и PUT, например, может быть выполнена с помощью HTTP-контекста.
ftp:// -- ftps:// — Доступ к URL-адресам по протоколу FTP(s)
Позволяет читать существующие файлы и создавать новые файлы через FTP. Если сервер FTP не поддерживает пассивный режим, соединение будет невозможно.
Вы можете открыть файл либо для чтения, либо для записи, но не
одновременно для того и другого. Если файл на сервере FTP уже существует,
и вы пытаетесь открыть его для записи, но не указали опцию контекста
overwrite, соединение будет невозможно.
Если вам необходимо перезаписать существующие файлы на FTP,
укажите опцию overwrite в контексте
и откройте файл для записи. Кроме того, вы можете использовать
модуль FTP.
Если вы установили директиву from в файле php.ini, то это значение будет отправлено как пароль при анонимном подключении к FTP.
Замечание:
FTPS поддерживается только тогда, когда включена поддержка модуля OpenSSL.
Если сервер не поддерживает SSL, то соединение переключается обратно на обычный нешифрованный протокол FTP.
Замечание: Дополнение
Файлы могут быть дописаны с помощью URL-обёрткиftp://.
php:// — Доступ к различным потокам ввода-вывода
PHP предоставляет несколько разнообразных потоков ввода-вывода, которые позволяют получить доступ к собственным потокам ввода-вывода PHP, к дескрипторам стандартного ввода, вывода и потока ошибок, к временным файловым потокам в памяти и на диске, и фильтрам, которые могут манипулировать другими файловыми ресурсами по мере их считывания или записи.
php://stdin, php://stdout и
php://stderr позволяют получить прямой доступ к соответствующим
потокам ввода или вывода процесса PHP. Поток указывает на копию файлового
дескриптора, таким образом, если вы откроете php://stdin
и потом закроете его, вы закроете только вашу копию дескриптора. Актуальный
поток, на который ссылается STDIN, остаётся неизменным.
Рекомендуется просто использовать константы STDIN,
STDOUT и STDERR вместо ручного
открытия потоков, используя эти обёртки.
Поток php://stdin предназначен только для чтения, тогда как php://stdout и php://stderr предназначены только для записи.
php://input является потоком только для чтения, который позволяет вам
читать необработанные данные из тела запроса.
php://input недоступен в POST-запросах с
enctype="multipart/form-data", если
опция enable_post_data_reading включена.
php://output является потоком только для записи, который позволяет вам записать данные в выходной буфер аналогично, как это делают функции print и echo.
php://fd предоставляет прямой доступ к указанному файловому дескриптору. Например, php://fd/3 относится к файловому дескриптору 3.
php://memory и php://temp являются потоками для чтения/записи и позволяют сохранять временные данные в файлоподобной обёртке. Единственная разница между ними заключается в том, что php://memory будет всегда хранить данные в оперативной памяти, тогда как php://temp будет использовать временный файл в том случае, когда объем хранимой информации достигнет заданного лимита (по умолчанию 2 Мб). Расположение этого временного файла определяется аналогично функции sys_get_temp_dir().
Размер лимита для php://temp может устанавливаться путём
добавления /maxmemory:NN, где NN - это
максимальный размер данных в байтах для хранения в памяти перед использованием временного
файла.
php://filter - это вид мета-обёртки, предназначенный для разрешения применения фильтров к потоку во время открытия. Это полезно для функционально полных файловых функций, таких как readfile(), file() и file_get_contents(), где нет возможности применить фильтр к потоку до того, как содержимое будет прочитано.
Поток php://filter принимает следующие параметры как часть своего пути. В одном пути можно указать несколько цепочек фильтров. Пожалуйста, ознакомьтесь с примерами и особенностями при использовании этих параметров.
| Название | Описание |
|---|---|
resource=<поток для фильтрации>
|
Этот параметр является необходимым. Он указывает потоку, что его необходимо отфильтровать. |
read=<список фильтров для применения к цепочке чтения>
|
Этот параметр является необязательным. Одно или несколько имён фильтров может быть указано
здесь, разделённых вертикальной чертой (|).
|
write=<список фильтров для применения к цепочке записи>
|
Этот параметр является необязательным. Одно или несколько имён фильтров может быть указано
здесь, разделённых вертикальной чертой (|).
|
<список фильтров для применения к обеим цепочкам чтения и записи>
|
Любой список фильтров, которые используются без префиксов read=
или write=, будет применён к обоим потокам на чтение и на запись
при необходимости.
|
Пример #1 php://temp/maxmemory
Этот необязательный параметр позволяет установить лимит памяти до того, как php://temp начнёт использовать временный файл.
<?php
// Установка предела в 5 MB.
$fiveMBs = 5 * 1024 * 1024;
$fp = fopen("php://temp/maxmemory:$fiveMBs", 'r+');
fputs($fp, "hello\n");
// Читаем то, что мы записали.
rewind($fp);
echo stream_get_contents($fp);
?>Пример #2 php://filter/resource=<поток для фильтрации>
Этот параметр должен быть расположен в конце вашей спецификации php://filter и должен указывать на поток, который вы хотите фильтровать.
<?php
/* Это просто эквивалентно:
readfile("http://www.example.com");
так как на самом деле фильтры не указаны */
readfile("php://filter/resource=http://www.example.com");
?>Пример #3 php://filter/read=<список фильтров для применения к цепочке чтения>
Этот параметр принимает один или более
имён фильтров, разделённых вертикальной чертой |.
<?php
/* Этот скрипт выведет содержимое
www.example.com полностью в верхнем регистре */
readfile("php://filter/read=string.toupper/resource=http://www.example.com");
/* Этот скрипт делает тоже самое, что вверхний, но
будет также кодировать алгоритмом ROT13 */
readfile("php://filter/read=string.toupper|string.rot13/resource=http://www.example.com");
?>Пример #4 php://filter/write=<список фильтров для применения к цепочке записи>
Этот параметр принимает один или более
имён фильтров, разделённых вертикальной чертой |.
<?php
/* Этот скрипт будет фильтровать строку "Hello World"
через фильтр rot13, затем записывать результат в
файл example.txt в текущей директории */
file_put_contents("php://filter/write=string.rot13/resource=example.txt","Hello World");
?>Пример #5 php://memory и php://temp нельзя переиспользовать
php://memory и php://temp нельзя переиспользовать, то есть после закрытия потоков невозможно сослаться на них снова.
file_put_contents('php://memory', 'PHP');
echo file_get_contents('php://memory'); // ничего не напечатаетzlib:// -- bzip2:// -- zip:// — Сжатые потоки
compress.zlib:// и compress.bzip2://
zlib: работает как gzopen() за исключением того, что этот поток может использоваться функцией fread() и другими функциями, работающими с файловой системой. Устарела, ввиду неоднозначности при наличии файлов, содержащих ':'; используйте взамен compress.zlib://.
compress.zlib:// и compress.bzip2:// эквиваленты gzopen() и bzopen() соответственно и работают даже в системах, не поддерживающих fopencookie.
Модуль ZIP добавляет обёртку zip:.
Начиная с PHP 7.2.0 и libzip 1.2.0+, была добавлена поддержка паролей для зашифрованных архивов, позволяя предоставлять пароли, используя контексты потоков.
Пароли могут быть установлены с помощью контекстной опции 'password'.
data:// — Схема Data (RFC 2397)
data: (» RFC 2397) - это обёртка потоков.
Пример #1 Вывод содержимого data://
<?php
// выводит "I love PHP"
echo file_get_contents('data://text/plain;base64,SSBsb3ZlIFBIUAo=');
?>Пример #2 Получение типа потока
<?php
$fp = fopen('data://text/plain;base64,', 'r');
$meta = stream_get_meta_data($fp);
// выводит "text/plain"
echo $meta['mediatype'];
?>glob:// — Нахождение путей, соответствующих шаблону
Обёртка потока glob:.
Пример #1 Основы использования
<?php
// Просмотреть все файлы *.php в директории ext/spl/examples/
// и напечатать имена файлов и их размеры
$it = new DirectoryIterator("glob://ext/spl/examples/*.php");
foreach($it as $f) {
printf("%s: %.1FK\n", $f->getFilename(), $f->getSize()/1024);
}
?>tree.php: 1.0K findregex.php: 0.6K findfile.php: 0.7K dba_dump.php: 0.9K nocvsdir.php: 1.1K phar_from_dir.php: 1.0K ini_groups.php: 0.9K directorytree.php: 0.9K dba_array.php: 1.1K class_tree.php: 1.8K
phar:// — PHP-архив
Обёртка потока phar://. Смотрите раздел Обёртка потока Phar для более детального описания.
ssh2:// — Secure Shell 2
ssh2.shell:// ssh2.exec:// ssh2.tunnel:// ssh2.sftp:// ssh2.scp:// (PECL)
Замечание: Эта обёртка не включена по умолчанию
Для того, чтобы использовать обёртки ssh2.*:// вам необходимо установить модуль » SSH2, доступный в репозитории » PECL.
Кроме получения традиционных данных для входа к URI, обёртки ssh2 также будут повторно использовать открытые соединения, передавая ресурс соединения в хост-часть URL.
Пример #1 Открытие потока из активного соединения
<?php
$session = ssh2_connect('example.com', 22);
ssh2_auth_pubkey_file($session, 'username', '/home/username/.ssh/id_rsa.pub',
'/home/username/.ssh/id_rsa', 'secret');
$stream = fopen("ssh2.tunnel://$session/remote.example.com:1234", 'r');
?>Пример #2 Переменная $session должна быть доступна!
Если вы хотите использовать какую-либо из обёрток ssh2.*://$session, необходимо сохранить доступным ресурс, хранящийся в переменной $session. Следующий код не будет иметь желаемого эффекта:
<?php
$session = ssh2_connect('example.com', 22);
ssh2_auth_pubkey_file($session, 'username', '/home/username/.ssh/id_rsa.pub',
'/home/username/.ssh/id_rsa', 'secret');
$connection_string = "ssh2.sftp://$session/";
unset($session);
$stream = fopen($connection_string . "path/to/file", 'r');
?>unset() закрывает сессию, потому что $connection_string не является ссылкой на переменную $session, а только её текстовым представлением. Это также происходит и в случае неявного вызова unset() при выходе из области видимости (например, из функции).
rar:// — RAR
Эта обёртка принимает URL-кодированный путь к RAR-архиву (относительный или абсолютный),
необязательный символ звёздочки (*), необязательный символ решётки
(#) и необязательное URL-кодированное имя такое, как хранится
в архиве. Для указания имени содержимого требуется символ решётки, начальный обратный слеш
в названии содержимого необязателен.
Эта обёртка может открывать файлы и директории. Когда открываются директории, знак звёздочки требует, чтобы имена объектов директории были закодированы unencode. Если такой знак не указан, они будут возвращены в URL-кодировке. Смысл этого в том, чтобы позволить обёртке корректно использовать встроенную функциональность, такую как RecursiveDirectoryIterator когда присутствуют имена файлов, которые кажутся как url-закодированные данные.
Если символ решётки и часть имени записи не включена, будет отображён корень архива. Это отличается от обычных директорий тем, что результирующий поток не будет содержать такую информацию, как время модификации, так как корневая директория не сохраняется как отдельная запись в архиве. Использование обёртки с RecursiveDirectoryIterator требует, чтобы символ решётки был включён в URL, когда происходит доступ к корню, так чтобы URL потомков мог быть сконструирован правильно.
Замечание: Эта обёртка не включена по умолчанию
Для того, чтобы использовать обёртку rar://, вам необходимо установить модуль » rar, доступный из репозитория » PECL.
rar:// Доступно начиная с PECL rar 3.0.0
Пример #1 Обход RAR-архива
<?php
class MyRecDirIt extends RecursiveDirectoryIterator {
function current() {
return rawurldecode($this->getSubPathName()) .
(is_dir(parent::current())?" [DIR]":"");
}
}
$f = "rar://" . rawurlencode(dirname(__FILE__)) .
DIRECTORY_SEPARATOR . 'dirs_and_extra_headers.rar#';
$it = new RecursiveTreeIterator(new MyRecDirIt($f));
foreach ($it as $s) {
echo $s, "\n";
}
?>Результатом выполнения данного примера будет что-то подобное:
|-allow_everyone_ni [DIR]
|-file1.txt
|-file2_אּ.txt
|-with_streams.txt
\-אּ [DIR]
|-אּ\%2Fempty%2E [DIR]
| \-אּ\%2Fempty%2E\file7.txt
|-אּ\empty [DIR]
|-אּ\file3.txt
|-אּ\file4_אּ.txt
\-אּ\אּ_2 [DIR]
|-אּ\אּ_2\file5.txt
\-אּ\אּ_2\file6_אּ.txt
Пример #2 Открытие зашифрованного файла (шифрование заголовка)
<?php
$stream = fopen("rar://" .
rawurlencode(dirname(__FILE__)) . DIRECTORY_SEPARATOR .
'encrypted_headers.rar' . '#encfile1.txt', "r", false,
stream_context_create(
array(
'rar' =>
array(
'open_password' => 'samplepassword'
)
)
)
);
var_dump(stream_get_contents($stream));
/* дата создания и дата последнего доступа включается опционально в WinRAR, поэтому у
* большинства файлов их нет */
var_dump(fstat($stream));
?>Результатом выполнения данного примера будет что-то подобное:
string(26) "Encrypted file 1 contents."
Array
(
[0] => 0
[1] => 0
[2] => 33206
[3] => 1
[4] => 0
[5] => 0
[6] => 0
[7] => 26
[8] => 0
[9] => 1259550052
[10] => 0
[11] => -1
[12] => -1
[dev] => 0
[ino] => 0
[mode] => 33206
[nlink] => 1
[uid] => 0
[gid] => 0
[rdev] => 0
[size] => 26
[atime] => 0
[mtime] => 1259550052
[ctime] => 0
[blksize] => -1
[blocks] => -1
)
ogg:// — Аудиопотоки
Файлы, открываемые для чтения с использованием обёртки ogg://,
рассматриваются как сжатый аудиопоток, кодируемый с использованием кодека OGG/Vorbis.
Аналогично, файлы, открытые для записи или добавления через обёртку
ogg://, записываются как сжатые звуковые данные.
Функция stream_get_meta_data(), когда используется с файлами OGG/Vorbis
открытыми для чтения, будет возвращать разнообразную информацию о потоке, включая
тег производителя vendor, комментарии
comments, число каналов
channels, частоту дискретизации rate,
и диапазон частоты кодирования, описываемый:
bitrate_lower, bitrate_upper,
bitrate_nominal и bitrate_window.
ogg:// (PECL)
Замечание: Данная обёртка не доступна по умолчанию
Для того чтобы использовать обёртку ogg:// вы должны установить модуль » OGG/Vorbis доступный в » PECL.
expect:// — Потоки для взаимодействия с процессами
Потоки, открытые с помощью обёртки expect://, предоставляют доступ к процессам stdio, stdout и stderr через PTY.
Замечание: Эта обёртка отключена по умолчанию
Для того, чтобы использовать обёртку expect://, необходимо установить модуль » Expect, доступный в » PECL.
expect:// (PECL)
PHP является мощным языком программирования и интерпретатором, взаимодействующим с веб-сервером как модуль либо как независимое бинарное CGI приложение. PHP способен обращаться к файлам, выполнять различные команды на сервере и открывать сетевые соединения. Именно поэтому все скрипты, исполняемые на сервере, являются потенциально опасными. PHP изначально разрабатывался как более защищённый (относительно Perl, C) язык для написания CGI-приложений. При помощи ряда настроек во время компиляции, а также динамических настроек приложения, вы всегда сможете найти подходящее сочетание свободы действий и безопасности.
Поскольку существует много различных способов использования PHP, имеется и множество опций, управляющих его поведением. Широкий выбор опций гарантирует вам возможность использовать PHP в разных целях, но также означает, что некоторые комбинации опций делают сервер незащищённым.
Гибкость конфигурирования PHP можно сравнить с гибкостью самого языка. PHP можно использовать для создания полноценных серверных приложений, использующих доступные для указанного пользователя возможности операционной системы, либо в качестве простых подключаемых файлов, хранящихся на сервере с минимальным риском в жёстко контролируемой среде. То, как настроено данное окружение, а также качество его безопасности, в большей части зависит от PHP-разработчика.
Эта глава начинается с рассмотрения некоторых общих вопросов безопасности, различных конфигурационных опций и их комбинаций, а также ситуаций, когда их использование является безопасным. Кроме того, приводятся некоторые рассуждения касательно безопасного кодирования.
Так как абсолютно безопасные системы являются не более, чем мифом, на практике приходится балансировать между комфортом и безопасностью. Если каждая переменная, вводимая пользователем, будет требовать две биометрические проверки (например, сканирование сетчатки глаза и отпечатки пальцев), то вы получите предельно высокую достоверность данных. Но поскольку заполнение сложной формы будет занимать около получаса, у пользователей такой системы непременно возникнет желание обойти навязчивую защиту.
Правильно поставленная защита должна соответствовать основным требованиям безопасности, не ухудшая при этом работу пользователя и не усложняя самому программисту разработку продукта. Вместе с тем, некоторые атаки могут основываться именно на таком подходе к защите, что приводит к её постепенному ослаблению.
Следует помнить хорошую поговорку: надёжность системы определяется её самым слабым звеном. Например, если все транзакции логируются по времени, месторасположению, типу транзакции и ряду других параметров, но авторизация пользователя происходит всего лишь по куке (cookie), то связь конкретной записи в логе с пользователем системы весьма сомнительна.
При тестировании следует помнить, что вы не можете проверить все возможные варианты даже для простейшей страницы. Данные, которые вы ожидаете, могут совершенно не соответствовать тому, что введёт раздражённый служащий, хакер со стажем или домашний кот, разгуливающий по клавиатуре. Поэтому лучше логически подумать над вопросом: в каком месте могут быть введены неожиданные данные, как их можно модифицировать, усечь, либо, наоборот, дополнить.
Интернет наполнен людьми, которые хотят сделать себе имя на том, что взломают ваш код, разрушат сайт, опубликуют на нем неуместный контент или просто сделают ваш день интереснее. И не важно, маленький у вас сайт или большой, если у вас есть онлайн-сервер - вы уже потенциальная жертва. Многие программы-взломщики не смотрят на размер, они просто перебирают массивы IP-адресов, выискивая очередную жертву. Постарайтесь не стать одной из них.
Использование PHP как бинарного CGI-приложения является одним из вариантов, когда по каким-либо причинам нежелательно интегрировать PHP в веб-сервер (например, Apache) в качестве модуля, либо предполагается использование различных CGI-обёрток и таких утилит, как chroot и setuid для организации безопасного окружения работы скриптов. Такая установка обычно сопровождается копированием исполняемого файла PHP в директорию cgi-bin веб-сервера. CERT (организация, следящая за угрозами безопасности) » CA-96.11 рекомендует не помещать какие-либо интерпретаторы в каталог cgi-bin. Даже если PHP используется как самостоятельный интерпретатор, он спроектирован так, чтобы предотвратить возможность следующих атак:
В случае, если на вашем сервере отсутствуют файлы, доступ к которым ограничен паролем либо фильтром по IP-адресам, нет никакой необходимости использовать данные опции. Если ваш веб-сервер не разрешает выполнять перенаправления, либо не имеет возможности взаимодействовать с исполняемым PHP-модулем на необходимом уровне безопасности, вы можете включить ini-директиву cgi.force_redirect. Но при этом вы всё ещё должны убедиться, что альтернативные способы вызова скрипта, такие как непосредственный вызов http://my.host/cgi-bin/php/dir/script.php либо с переадресацией http://my.host/dir/script.php, недоступны.
В веб-сервере Apache перенаправление может быть сконфигурировано при помощи директив AddHandler и Action (описано ниже).
cgi.force_redirectКонфигурационная директива cgi.force_redirect предотвращает попытки непосредственного вызова PHP по адресу вида http://my.host/cgi-bin/php/secretdir/script.php. Вместо этого PHP будет обрабатывать пришедший запрос только в том случае, если он был перенаправлен веб-сервером.
Обычно перенаправление в конфигурации Apache настраивается при помощи следующих опций:
Action php-script /cgi-bin/php AddHandler php-script .php
Эта опция проверена только с веб-сервером Apache, её работа основывается на установке в случае перенаправления нестандартной переменной REDIRECT_STATUS, находящейся в CGI-окружении. В случае, если ваш веб-сервер не предоставляет возможности однозначно идентифицировать, является ли данный запрос перенаправленным, вы не можете использовать описываемую в данном разделе опцию и должны воспользоваться любым другим методом работы с CGI-приложениями.
Размещение динамического контента, такого как скрипты или любых других исполняемых файлов, в директории веб-сервера делает его потенциально опасным. В случае, если в конфигурации сервера допущена ошибка, возможна ситуация, когда скрипты не выполняются, а отображаются в браузере, как обычные HTML-документы, что может привести к утечке конфиденциальной информации (например, паролей), либо информации, являющейся интеллектуальной собственностью. Исходя из таких соображений, многие системные администраторы предпочитают использовать для хранения скриптов отдельную директорию, работая со всеми размещёнными в ней файлами по CGI-интерфейсу.
В случае, если невозможно гарантировать, что запросы не перенаправляются, как было показано в предыдущем разделе, необходимо указывать переменную doc_root, которая отличается от корневой директории веб-документов.
Вы можете установить корневую директорию для PHP-скриптов, настроив
параметр doc_root в
конфигурационном файле,
либо установив переменную окружения PHP_DOCUMENT_ROOT.
В случае, если PHP используется посредством CGI,
полный путь к открываемому файлу будет построен на основании
значения переменной doc_root и указанного
в запросе пути. Таким образом, вы можете быть уверены,
что скрипты будут выполняться только внутри указанной вами директории
(кроме директории user_dir, которая описана ниже).
Ещё одна используемая при настройке безопасности опция -
user_dir. В случае, если
переменная user_dir не установлена, путь к открываемому файлу
строится относительно doc_root. Запрос
вида http://my.host/~user/doc.php
приводит к выполнению скрипта, находящегося не в домашнем каталоге
соответствующего пользователя, а находящегося в подкаталоге doc_root
скрипта ~user/doc.php (да, имя
директории начинается с символа ~).
Но если 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,
таким образом вы можете контролировать корневую директорию веб-сервера
и пользовательские директории независимо друг от друга.
Один из способов существенно повысить уровень безопасности - поместить исполняемый модуль PHP вне дерева веб-документов, например в /usr/local/bin. Единственным недостатком такого подхода является то, что первая строка каждого скрипта должна иметь вид:
#!/usr/local/bin/php
#! в начале файла для запуска самого себя.
Для корректной обработки PHP переменных PATH_INFO и PATH_TRANSLATED директива ini cgi.discard_path должна быть включена.
Если PHP используется как модуль Apache, он наследует права пользователя, с которыми был запущен веб-сервер (обычно это пользователь "nobody"). Это влияет на обеспечение безопасности и реализацию авторизации. Например, если вы используете PHP для доступа к базе данных, которая не имеет встроенного механизма разграничения доступа, вам придётся обеспечить доступ к БД для пользователя 'nobody'. В таком случае вредоносный скрипт может получить доступ к базе данных и модифицировать её, даже не зная логина и пароля. Вполне возможна ситуация, при которой веб-паук неверными запросами на страницу администратора базы данных может уничтожить все ваши базы данных. Вы можете избежать такой ситуации при помощи авторизации Apache или разработав собственную модель доступа, используя LDAP, файлы .htaccess или любые другие технологии, внедряя соответствующий код в ваши PHP-скрипты.
Достаточно часто используются такие настройки безопасности, при которых PHP (имеется в виду пользователь, с правами которого выполняется Apache) имеет минимальные привилегии, например, отсутствует возможность записи в пользовательские директории с помощью PHP. Или, например, отсутствует возможность работать с базой данных. При этом система безопасности не позволяет записывать как "хорошие", так и "плохие" файлы, или провести "хорошие" или "плохие" транзакции.
Распространённой ошибкой является запуск Apache с правами суперпользователя или любое другое расширение полномочий веб-сервера.
Расширение привилегий веб-сервера до полномочий суперпользователя угрожает работоспособности всей системы, поэтому такие команды, как sudo, chroot и другие способы запуска с правами суперпользователя должны выполняться исключительно теми, кто профессионально разбирается в вопросах безопасности.
Существует несколько простых решений. Используя open_basedir, вы можете ограничить дерево доступных директорий для PHP. Вы так же можете определить область доступа Apache, ограничив все действия, совершаемые из веба не пользовательскими или несистемными файлами.
Крайне важно обеспечивать безопасность HTTP-сессий. Подробное описание, какими средствами этого можно достичь, читайте в секции Безопасность сессий руководства Сессии.
PHP является одним из важных моментов в вопросе безопасности сервера, поскольку PHP-скрипты могут манипулировать файлами и каталогами на диске. В связи с этим существуют конфигурационные настройки, указывающие, какие файлы могут быть доступны и какие операции с ними можно выполнять. Необходимо проявлять осторожность, поскольку любой из файлов, с полными правами чтения ("world readable") может быть прочитан каждым, кто имеет доступ к файловой системе.
Поскольку в PHP изначально предполагался полноправный пользовательский доступ к файловой системе, можно написать PHP-скрипт, который позволит читать системные файлы, такие как /etc/passwd, управлять сетевыми соединениями, отправлять задания принтеру, и так далее. Как следствие, вы всегда должны быть уверены в том, что файлы, которые вы читаете или модифицируете, являются именно теми, которые вы подразумевали.
Рассмотрим следующий пример, в котором пользователь создал скрипт, удаляющий файл из его домашней директории. Предполагается ситуация, когда веб-интерфейс, написанный на PHP, регулярно используется для работы с файлами, и настройки безопасности позволяют удалять файлы в домашнем каталоге.
Пример #1 Недостаточная проверка внешних данных ведёт к...
<?php
// Удаление файла из домашней директории пользователя
$username = $_POST['user_submitted_name'];
$userfile = $_POST['user_submitted_filename'];
$homedir = "/home/$username";
unlink("$homedir/$userfile");
echo "Файл был удалён!";
?>Пример #2 ... атаке на файловую систему
<?php
// Удаление любого файла, доступного из PHP-скрипта.
// В случае, если PHP работает с правами пользователя root:
$username = $_POST['user_submitted_name']; // "../etc"
$userfile = $_POST['user_submitted_filename']; // "passwd"
$homedir = "/home/$username"; // "/home/../etc"
unlink("$homedir/$userfile"); // "/home/../etc/passwd"
echo "Файл был удалён!";
?>Пример #3 Более безопасная проверка имени файла
<?php
// Удаление любого файла, к которому имеет доступ пользователь,
// под которым запущен PHP.
$username = $_SERVER['REMOTE_USER']; // использование авторизации
$userfile = basename($_POST['user_submitted_filename']);
$homedir = "/home/$username";
$filepath = "$homedir/$userfile";
if (file_exists($filepath) && unlink($filepath)) {
$logstring = "$filepath удалён\n";
} else {
$logstring = "Не удалось удалить $filepath\n";
}
$fp = fopen("/home/logging/filedelete.log", "a");
fwrite($fp, $logstring);
fclose($fp);
echo htmlentities($logstring, ENT_QUOTES);
?>Пример #4 Более строгая проверка имени файла
<?php
$username = $_SERVER['REMOTE_USER']; // использование авторизации
$userfile = $_POST['user_submitted_filename'];
$homedir = "/home/$username";
$filepath = "$homedir/$userfile";
if (!ctype_alnum($username) || !preg_match('/^(?:[a-z0-9_-]|\.(?!\.))+$/iD', $userfile)) {
die("Неправильное имя пользователя или файл");
}
//etc...
?>В зависимости от используемой вами операционной системы необходимо предусматривать возможность атаки на разнообразные файлы, включая системные файлы устройств (/dev/ или COM1), конфигурационные файлы (например /etc/ или файлы с расширением .ini), хорошо известные области хранения данных (/home/, My Documents), и так далее. Исходя из этого, как правило, легче реализовать такую политику безопасности, в которой запрещено все, исключая то, что явно разрешено.
Так как для работы с файловой системой PHP использует нижележащие C-функции, то в этом случае возможна крайне неожиданная обработка нулевого байта. Так как нулевой байт означает конец строки в C, то строки, содержащие такой байт, не будут трактоваться полностью, а только до той позиции, в которой находится этот байт. Следующий пример содержит уязвимый код, демонстрирующий эту проблему:
Пример #1 Скрипт, уязвимый к нулевому байту
<?php
$file = $_GET['file']; // "../../etc/passwd\0"
if (file_exists('/home/wwwrun/'.$file.'.php')) {
// file_exists возвратит true, т.к. /home/wwwrun/../../etc/passwd существует
include '/home/wwwrun/'.$file.'.php';
// будет подключён файл /etc/passwd
}
?>Таким образом, любая испорченная строка, используемая в операциях с файловой системой должна быть соответствующим образом проверена. Вот улучшенная версия предыдущего примера:
Пример #2 Корректная проверка входных данных
<?php
$file = $_GET['file'];
// Белый список возможных значений
switch ($file) {
case 'main':
case 'foo':
case 'bar':
include '/home/wwwrun/include/'.$file.'.php';
break;
default:
include '/home/wwwrun/include/main.php';
}
?>На сегодняшний день базы данных являются ключевыми компонентами большинства веб-приложений, позволяя предоставлять на сайтах динамический контент. Поскольку в таких БД может храниться очень деликатная или конфиденциальная информация, необходимо очень серьёзно относиться к защите базы данных.
Для извлечения или сохранения любых данных вам необходимо открыть соединение с базой данных, отправить корректный запрос, извлечь результат и закрыть соединение. В настоящее время наиболее распространённым стандартом общения является язык структурированных запросов (SQL). Всегда следует помнить о возможности атаки посредством SQL-запроса.
Очевидно, что сам по себе PHP не может защитить вашу базу данных. В этом разделе документации описаны самые основы безопасного доступа и управления данными баз данных в PHP-скриптах.
Запомните простое правило: максимальная защита. Чем больше потенциально опасных участков системы вы проработаете, тем сложнее будет потенциальному взломщику получить доступ к базе данных или повредить её. Хорошее проектирование базы данных и программных приложений поможет вам справиться с вашими страхами.
Первый шаг - это всегда создание БД, исключая тот случай, когда вы хотите использовать готовую базу, предоставляемую третьими лицами. После того, как база данных создана, она назначается пользователю, который выполнил создавший БД запрос. Как правило, только владелец (или суперпользователь) может выполнять различные действия с объектами, хранимыми в базе данных. Для того, чтобы и другие пользователи имели к ней доступ, их необходимо наделить соответствующими привилегиями.
Приложения никогда не должны соединяться с базой данных, используя учётную запись владельца или суперпользователя, потому что они смогут выполнить любой запрос, например, модифицировать структуру таблиц (например, удалить некоторые таблицы) или даже удалить все содержимое БД целиком.
Вы можете создать различные учётные записи пользователей БД для каждой индивидуальной потребности приложения с сильно ограниченными функциональными ограничениями. Рекомендуется назначать только самые необходимые привилегии, также вы должны избегать ситуаций, когда один и тот же пользователь может взаимодействовать с базой данных несколькими способами. Вы должны понимать, что если злоумышленник сможет воспользоваться какой-либо учётной записью вашей БД, он сможет вносить в базу все те изменения, что и программа, которая использует текущую учётную запись.
Вы можете использовать безопасные SSL или ssh соединения, для шифрования данных, которыми обмениваются клиент и сервер. При реализации чего-либо из вышеперечисленного мониторинг трафика и сбор данных о вашей базе данных существенно усложнится для потенциального взломщика .
Вы можете установить соединения через SSL для шифрования связи клиент/сервер для повышения безопасности, или вы можете использовать ssh для шифрования сетевого соединения между клиентами и сервером базы данных. Если любой из них используется, то мониторинг вашего трафика и получение информации о вашей базы данных будет трудным для потенциального злоумышленника.
В случае, если взломщик получил непосредственный доступ к БД (в обход веб-сервера), он может извлечь интересующие данные или нарушить их целостность, если информация не защищена на уровне самой БД. Шифрование данных - хороший способ предотвратить такую ситуацию, но лишь незначительное количество БД предоставляют такую возможность.
Наиболее простое решение этой проблемы - установить вначале обыкновенный программный пакет для шифрования данных, а затем использовать его в ваших PHP-скриптах. PHP может вам помочь с этой задачей с помощью таких модулей как OpenSSL и Sodium, реализующих довольно большое число алгоритмов шифрования. При таком подходе скрипт вначале шифрует сохраняемые данные, а затем дешифрует их при запросе. Ниже приведены примеры того, как работает шифрование данных в PHP-скриптах.
В случае работы со скрытыми служебными данными, если не требуется их нешифрованное представление (т.е. его не нужно показывать), то, как следствие, можно использовать хеширование. Хорошо известный пример хеширования - хранение криптографического хеша от пароля в БД, вместо хранения оригинального значения.
Функция password позволяет удобно хешировать конфиденциальные данные и работать с этими хешами.
password_hash() позволяет хешировать заданную строку самым сильным из доступных алгоритмом и password_verify() проверяет, что заданный пароль совпадает с сохранённым в БД хешем.
Пример #1 Хеширование полей с паролями
<?php
// Сохраняем хеш пароля
$query = sprintf("INSERT INTO users(name,pwd) VALUES('%s','%s');",
pg_escape_string($username),
password_hash($password, PASSWORD_DEFAULT));
$result = pg_query($connection, $query);
// проверка введённого пользователем пароля на корректность
$query = sprintf("SELECT pwd FROM users WHERE name='%s';",
pg_escape_string($username));
$row = pg_fetch_assoc(pg_query($connection, $query));
if ($row && password_verify($password, $row['pwd'])) {
echo 'Добро пожаловать, ' . htmlspecialchars($username) . '!';
} else {
echo 'Ошибка авторизации, ' . htmlspecialchars($username) . '.';
}
?>SQL-инъекция - это техника, при которой злоумышленник использует недостатки в коде приложения, отвечающего за построение динамических SQL-запросов. Злоумышленник может получить доступ к привилегированным разделам приложения, получить всю информацию из базы данных, подменить существующие данные или даже выполнить опасные команды системного уровня на узле базы данных. Уязвимость возникает, когда разработчики конкатенируют или интерполируют произвольный ввод в SQL-запросах.
Пример #1 Постраничный вывод результата и создание суперпользователя в PostgreSQL
В следующем примере пользовательский ввод напрямую интерполируется в SQL-запрос, что позволяет злоумышленнику получить учётную запись суперпользователя в базе данных.
<?php
$offset = $_GET['offset']; // осторожно, нет валидации ввода!
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
$result = pg_query($conn, $query);
?>0; insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd) select 'crack', usesysid, 't','t','crack' from pg_shadow where usename='postgres'; --
0; использовано
для того, чтобы задать правильное смещение для первого запроса и
корректно его завершить.
Замечание:
Это распространённый приём, чтобы заставить синтаксический анализатор SQL игнорировать остальную часть запроса, написанного разработчиком с помощью
--, который является знаком комментария в SQL.
Ещё один вероятный способ получить пароли учётных записей в БД - атака страниц,
предоставляющих поиск по базе. Злоумышленнику нужно лишь проверить, используется
ли в запросе передаваемая на сервер и необрабатываемая надлежащим образом переменная.
Это может быть один из устанавливаемых на предыдущей странице фильтров,
таких как WHERE, ORDER BY, LIMIT и OFFSET,
используемых при построении запросов SELECT.
В случае, если используемая вами база данных поддерживает
конструкцию UNION, злоумышленник может присоединить
к оригинальному запросу ещё один дополнительный, для извлечения пользовательских
паролей. Настоятельно рекомендуем использовать только зашифрованные
пароли.
Пример #2 Листинг статей... и некоторых паролей (для любой базы данных)
<?php
$query = "SELECT id, name, inserted, size FROM products
WHERE size = '$size'";
$result = odbc_exec($conn, $query);
?>SELECT-запросом, который выведет все пароли:
' union select '1', concat(uname||'-'||passwd) as name, '1971-01-01', '0' from usertable; --
Выражения UPDATE и INSERT также подвержены таким атакам.
Пример #3 От сброса пароля до получения дополнительных привилегий (любой сервер баз данных)
<?php
$query = "UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';";
?>' or uid like'%admin%' для переменной $uid для
изменения пароля администратора или просто присвоить переменной $pwd значение
hehehe', trusted=100, admin='yes
для получения дополнительных привилегий. При выполнении запросы переплетаются:
<?php
// $uid: ' or uid like '%admin%
$query = "UPDATE usertable SET pwd='...' WHERE uid='' or uid like '%admin%';";
// $pwd: hehehe', trusted=100, admin='yes
$query = "UPDATE usertable SET pwd='hehehe', trusted=100, admin='yes' WHERE
...;";
?>Хотя остаётся очевидным, что для проведения успешной атаки злоумышленник должен обладать хотя бы некоторыми знаниями об архитектуре базы данных, получить эту информацию зачастую очень просто. Например, код может быть частью программного обеспечения с открытым исходным кодом и находиться в открытом доступе. Эта информация также может быть раскрыта закрытым кодом - даже если он закодирован, обфусцирован или скомпилирован, и даже вашим собственным кодом через отображение сообщений об ошибках. Другие методы включают использование типичных имён таблиц и столбцов. Например, форма входа в систему, использующая таблицу 'users' с именами столбцов 'id', 'username' и 'password'.
Пример #4 Атака на операционную систему сервера базы данных (MSSQL Server)
Пугающий пример того, как команды уровня операционной системы могут быть доступны на некоторых узлах баз данных.
<?php
$query = "SELECT * FROM products WHERE id LIKE '%$prod%'";
$result = mssql_query($query);
?>a%' exec master..xp_cmdshell 'net user test testpass /ADD' --
в $prod, то $query будет:
<?php
$query = "SELECT * FROM products
WHERE id LIKE '%a%'
exec master..xp_cmdshell 'net user test testpass /ADD' --%'";
$result = mssql_query($query);
?>sa
и служба MSSQLSERVER была запущена с достаточными привилегиями,
у злоумышленника появилась бы учётная запись, с помощью которой
он мог бы получить доступ к этой машине.
Замечание:
Некоторые примеры, приведённые выше, привязаны к конкретному серверу баз данных, но это не означает, что подобная атака невозможна на другие продукты. Ваш сервер баз данных может быть аналогично уязвим и другим способом.
Рекомендуемый способ избежать SQL-инъекций - связывание всех данных с помощью подготовленных запросов.
Использование подготовленных запросов недостаточно для полного предотвращения SQL-инъекций,
но это самый простой и безопасный способ обеспечить ввод данных в SQL-запросы.
Все динамические литералы данных в выражениях WHERE, SET и VALUES
должны быть заменены заполнителями. Фактические данные будут связаны во время выполнения
и отправлены отдельно от команды SQL.
Привязка параметров может использоваться только для данных. Другие динамические части SQL-запроса должны быть отфильтрованы по известному списку допустимых значений.
Пример #5 Избегание SQL-инъекций с помощью подготовленных операторов PDO
<?php
// Динамическая часть SQL проверяется на соответствие ожидаемым значениям
$sortingOrder = $_GET['sortingOrder'] === 'DESC' ? 'DESC' : 'ASC';
$productId = $_GET['productId'];
// SQL подготавливается с заполнителем
$stmt = $pdo->prepare("SELECT * FROM products WHERE id LIKE ? ORDER BY price {$sortingOrder}");
// Значение предоставляется с подстановочными знаками LIKE
$stmt->execute(["%{$productId}%"]);
?>Подготовленные операторы предоставляются PDO, MySQLi, а также другими библиотеками баз данных.
Атаки SQL-инъекций в основном основаны на использовании кода, написанного без учёта требований безопасности. Никогда не доверяйте любому вводу, особенно со стороны клиента, даже если он поступает из поля выбора, скрытого поля ввода или cookie. Первый пример показывает, что такой простой запрос может привести к катастрофе.
Стратегия "защита в глубину" включает в себя несколько эффективных методов написания кода:
Помимо всего вышесказанного, вы можете логировать запросы в вашем скрипте либо на уровне базы данных, если она это поддерживает. Очевидно, что логирование не может предотвратить нанесение ущерба, но может помочь при трассировке взломанного приложения. Лог-файл полезен не сам по себе, а информацией, которая в нем содержится. Причём, в большинстве случаев полезно логировать все возможные детали.
С точки зрения безопасности вывод сообщений об ошибках несёт в себе как плюсы, так и минусы.
Одна из стандартных методик, применяемых в атаках - ввод некорректных данных с последующим анализом содержания и характера сообщений об ошибках. Это даёт взломщику возможность проверить скрипты и данные сервера на наличие потенциальных дыр. Например, если взломщик получил некоторую информацию о странице на основании отправки формы, он попробует предопределить некоторые передаваемые значения или модифицировать их:
Пример #1 Атака на переменные в 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() в целях отладки, но на работающих сайтах это может открыть информацию о скрытых переменных, непроверенном синтаксисе и других потенциально опасных моментах. Особенно опасно наличие кода со встроенным механизмом отладки в публичных частях сайта. Взломщик может попытаться запустить отладочный механизм, подбирая основные признаки отладки:
Пример #2 Использование стандартных отладочных переменных
<form method="post" action="attacktarget?errors=Y&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-скрипты. Если взломщик анализирует обычную страницу сайта с расширением .html и пытается узнать систему, с помощью которой работает сайт (для дальнейшего поиска уязвимых мест), то подавая на ввод неверные данные он может обнаружить, что система использует PHP.
Также уведомление об ошибке может дать информацию об используемой базе данных, или, к примеру, как построена логика работы скриптов. Это, в свою очередь, может позволить взломщику подключиться к открытому порту базы данных, либо найти определённые ошибки в коде. Пробуя поочерёдно различные неверные блоки данных, злоумышленник может определить порядок аутентификации в скрипте (например, по номерам строк с ошибками) или проверять на наличие дыр различные участки кода.
Вывод стандартных ошибок или ошибок, связанных с файловой системой, может указать, с какими привилегиями запущен веб-сервер, и как организованы каталоги сайта. Обработка подобных ошибок, написанная разработчиками приложения, может только усугубить проблему, если взломщиком будет найден способ обнаружить "скрытую" отладочную информацию.
Существует три основных способа решения этой проблемы. Первый заключается в том, чтобы структурировать все функции и попытаться компенсировать объем выдаваемых ошибок. Второй способ - полностью отключить в работающем коде вывод сообщений об ошибках. И, наконец, третий способ - использовать специальные средства PHP для создания собственного обработчика ошибок. В зависимости от используемой вами политики безопасности вы можете применить в вашей конкретной ситуации все три способа.
Один из возможных способов обезопасить ваш код перед его публикацией
в общий доступ - это использование функции PHP error_reporting(),
которая может помочь выявить потенциально опасные переменные.
Тестируя код перед выпуском релиза при помощи значения
E_ALL, вы достаточно легко можете обнаружить участки
кода, в которых переменные могут быть подменены либо модифицированы.
После окончания тестирования, вы можете либо полностью отключить
все сообщения об ошибках установив error_reporting()
в 0, либо отключить их вывод с помощью директивы php.ini
display_errors, изолировав таким образом ваш
код от прощупывания. Если вы решили использовать последний способ,
то необходимо также указать путь к лог-файлу с помощью директивы
error_log и включить директиву
log_errors.
Пример #3 Поиск потенциально опасных переменных при помощи E_ALL
<?php
if ($username) { // Переменная не инициализируется или не проверяется перед использованием
$good_login = 1;
}
if ($good_login == 1) { // Если предыдущая проверка потерпела неудачу, переменная оказывается неинициализированной
readfile ("/highly/sensitive/data/index.html");
}
?>Наиболее опасные уязвимости во многих PHP-скриптах возникают не столько из-за самого языка, сколько из-за кода, написанного без учёта соответствующих требований безопасности. Как следствие, вы всегда должны выделять время на исследование разрабатываемого участка кода, чтобы оценить потенциальную угрозу от ввода переменной с нестандартным значением.
Пример #1 Потенциально опасное использование переменных
<?php
// удалить файлы из домашней директории пользователя...
// а может, из ещё какой-нибудь?
unlink ($evil_var);
// записать в лог-файл выполняемое действие...
// а может быть в /etc/passwd?
fwrite ($fp, $evil_var);
// выполнение тривиальных действий... или rm -rf *?
system ($evil_var);
exec ($evil_var);
?>Вы должны тщательно проверять ваш код и быть абсолютно уверены в том, что все данные, передаваемые веб-браузером, проверяются надлежащим образом. Попробуйте ответить для себя на следующие вопросы:
Ответив на эти вопросы во время написания скрипта, а не после, вы, возможно, предотвратите последующую доработку скрипта в целях повышения его безопасности. Начиная разработку с этих вопросов, вы не гарантируете полную безопасность вашей системы, но сможете значительно повысить её.
Вы также можете рассмотреть отключение таких конфигурационных опций, как register_globals, magic_quotes и некоторых других, которые могут приводить к сомнениям относительно происхождения или значения получаемых переменных. Использование при написании PHP-кода режима error_reporting(E_ALL) может помочь предупредить вас об использовании переменных до инициализации или проверки (что предотвратит работу с данными, отличными от ожидаемых).
В общем случае внесение неясности ненамного улучшает защищённость системы. Но бывают случаи, когда следует использовать малейшую возможность.
Несколько несложных методик могут помочь вам скрыть PHP,
что усложняет работу потенциального взломщика, который пытается
найти брешь в вашей системе. Установив опцию expose_php в off в
конфигурационном файле php.ini, вы уменьшите количество
доступной хакеру информации.
Ещё одна методика заключается в настройке веб-сервера таким образом, чтобы он обрабатывал файлы с различными расширениями как PHP-скрипты. Это можно указать как в .htaccess файлах, так и конфигурационном файле Apache. В таком случае вы сможете использовать при написании кода нестандартные расширения:
Пример #1 Маскировка PHP под другие языки программирования
# Теперь PHP-скрипты могут иметь те же расширения, что и другие языки программирования AddType application/x-httpd-php .asp .py .pl
Пример #2 Использование неизвестных расширений для PHP-скриптов
# Теперь PHP-скрипты могут иметь неизвестные типы файлов AddType application/x-httpd-php .bop .foo .133t
Пример #3 Маскировка PHP-файлов под HTML
# Теперь PHP-скрипты выглядят как обыкновенный HTML AddType application/x-httpd-php .htm .html
PHP, как и любая другая большая система, постоянно проверяется и улучшается. Каждая новая версия содержит множество как существенных, так и мелких изменений, которые, в том числе, касаются повышения безопасности, расширения конфигурационных возможностей, а также стабильности вашей системы.
Как и в других программах и языках программирования, рекомендуется регулярно обновлять PHP и быть в курсе изменений, сделанных в последних версиях.
Возможно использовать функцию header() для
отправки сообщения "Authentication Required"
браузеру, заставив его показать окошко для ввода логина и пароля.
Как только пользователь заполнит логин и пароль, ссылка, содержащая
PHP-скрипт будет вызвана ещё раз с
предопределёнными переменными
PHP_AUTH_USER, PHP_AUTH_PW
и AUTH_TYPE, установленными в логин, пароль
и тип аутентификации соответственно. Эти предопределённые
переменные хранятся в массиве $_SERVER.
Поддерживаются только: "Basic" и "Digest". Подробнее
смотрите функцию header().
Пример фрагмента скрипта, который вынуждает клиента авторизоваться для просмотра страницы:
Пример #1 Пример Basic HTTP-аутентификации
<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
echo 'Текст, отправляемый в том случае,
если пользователь нажал кнопку Cancel';
exit;
} else {
echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
echo "<p>Вы ввели пароль {$_SERVER['PHP_AUTH_PW']}.</p>";
}
?>
Пример #2 Пример Digest HTTP-аутентификации
Это пример реализации простого скрипта Digest HTTP-аутентификации. За подробностями обращайтесь к » RFC 2617.
<?php
$realm = 'Запретная зона';
//user => password
$users = array('admin' => 'mypass', 'guest' => 'guest');
if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.
'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');
die('Текст, отправляемый в том случае, если пользователь нажал кнопку Cancel');
}
// анализируем переменную PHP_AUTH_DIGEST
if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) ||
!isset($users[$data['username']]))
die('Неправильные данные!');
// генерируем корректный ответ
$A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]);
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
$valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);
if ($data['response'] != $valid_response)
die('Неправильные данные!');
// все хорошо, логин и пароль верны
echo 'Вы вошли как: ' . $data['username'];
// функция разбора заголовка http auth
function http_digest_parse($txt)
{
// защита от отсутствующих данных
$needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
$data = array();
$keys = implode('|', array_keys($needed_parts));
preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $txt, $matches, PREG_SET_ORDER);
foreach ($matches as $m) {
$data[$m[1]] = $m[3] ? $m[3] : $m[4];
unset($needed_parts[$m[1]]);
}
return $needed_parts ? false : $data;
}
?>Замечание: Замечание касательно совместимости
Будьте особенно внимательны при указании HTTP-заголовков. Для того, чтобы гарантировать максимальную совместимость с наибольшим количеством различных клиентов, слово "Basic" должно быть написано с большой буквы "B", регион (realm) должен быть взят в двойные (не одинарные!) кавычки, и ровно один пробел должен предшествовать коду 401 в заголовке HTTP/1.0 401. Параметры аутентификации должны разделяться запятыми, как это было показано в примере Digest аутентификации выше.
Вместо простого отображения на экране переменных PHP_AUTH_USER и PHP_AUTH_PW, вам, возможно, понадобится проверить их корректность. Используйте для этого запрос к базе данных или поиск пользователя в dbm-файле.
Вы можете пронаблюдать особенности работы браузера Internet Explorer.
Он очень требователен к параметру передаваемых заголовков. Трюк с указанием
заголовка WWW-Authenticate перед отправкой статуса
HTTP/1.0 401 пока что работает для него.
Замечание: Замечание касательно конфигурации
PHP использует указание директивы
AuthTypeдля указания того, используется внешняя аутентификация или нет.
Следует заметить, что все вышесказанное не предотвращает похищения паролей к страницам, требующим авторизацию, кем-либо, кто контролирует страницы без авторизации, расположенные на том же сервере.
И Netscape Navigator и Internet Explorer очищают кеш аутентификации текущего окна для заданного региона (realm) при получении от сервера статуса 401. Это может использоваться для реализации принудительного выхода пользователя и повторного отображения диалогового окна для ввода имени пользователя и пароля. Некоторые разработчики используют это для ограничения авторизации по времени или для предоставления кнопки "Выход".
Пример #3 Пример HTTP-аутентификации с принудительным вводом новой пары логин/пароль
<?php
function authenticate() {
header('WWW-Authenticate: Basic realm="Test Authentication System"');
header('HTTP/1.0 401 Unauthorized');
echo "Вы должны ввести корректный логин и пароль для получения доступа к ресурсу \n";
exit;
}
if (!isset($_SERVER['PHP_AUTH_USER']) ||
($_POST['SeenBefore'] == 1 && $_POST['OldAuth'] == $_SERVER['PHP_AUTH_USER'])) {
authenticate();
} else {
echo "<p>Добро пожаловать: " . htmlspecialchars($_SERVER['PHP_AUTH_USER']) . "<br />";
echo "Предыдущий логин: " . htmlspecialchars($_REQUEST['OldAuth']);
echo "<form action='' method='post'>\n";
echo "<input type='hidden' name='SeenBefore' value='1' />\n";
echo "<input type='hidden' name='OldAuth' value=\"" . htmlspecialchars($_SERVER['PHP_AUTH_USER']) . "\" />\n";
echo "<input type='submit' value='Авторизоваться повторно' />\n";
echo "</form></p>\n";
}
?>
Это поведение не регламентируется стандартами HTTP Basic-аутентификации,
следовательно, вы не должны зависеть от этого. Тестирование браузера Lynx
показало, что Lynx не очищает кеш авторизации при получении от сервера
статуса 401, и, нажав последовательно "Back", а затем "Forward" возможно
открыть такую страницу, при условии, что требуемые атрибуты авторизации не изменились.
Однако, пользователь может нажать клавишу '_' для очистки кеша аутентификации.
Для того, чтобы добиться корректной работы HTTP-аутентификации в IIS сервере с
CGI версией PHP, вы должны отредактировать
конфигурационную настройку IIS под названием "Directory Security".
Щёлкните на надписи "Edit" и установите опцию
"Anonymous Access",
все остальные поля должны остаться неотмеченными.
Замечание: Замечание касательно IIS:
Для того, чтобы HTTP-аутентификация корректно работала в IIS, в конфигурации PHP-опция cgi.rfc2616_headers должна быть установлена значением0(значение по умолчанию).
Сессии PHP представляют собой различные способы сохранения данных для дальнейшего доступа к ним. Они позволяют создавать более гибкие приложения и улучшают привлекательность вашего сайта. Подробная информация находится в справочнике сессий.
» XForms являются альтернативой традиционным веб-формам, и позволяют использовать их на множестве платформ и браузеров, а также реализовывать нестандартные представления форм, например, в виде PDF-документа.
Первое существенное отличие XForms заключается в том, как форма отсылается клиенту. Руководство » XForms for HTML Authors содержит детальное описание создания XForms. Для того, чтобы очертить основную идею руководства, приведём несколько простых примеров.
Пример #1 Простая поисковая форма XForms
<h:html xmlns:h="http://www.w3.org/1999/xhtml"
xmlns="http://www.w3.org/2002/xforms">
<h:head>
<h:title>Поиск</h:title>
<model>
<submission action="http://example.com/search"
method="post" id="s"/>
</model>
</h:head>
<h:body>
<h:p>
<input ref="q"><label>Что искать?</label></input>
<submit submission="s"><label>Найти</label></submit>
</h:p>
</h:body>
</h:html>
Приведённая выше форма отображает текстовое поле для ввода
(названное q) и кнопку для отправки формы,
при нажатии на которую все введённые данные будут отправлены
скрипту, указанному в поле action.
Тут мы подошли к ещё одному существенному различию с точки зрения
вашего веб-приложения. Стандартная HTML-форма отправляет данные
как application/x-www-form-urlencoded, а XForms
для передачи данных использует разметку XML.
Если вы решили работать с XForms, скорее всего вы захотите получить отправленные пользователем данные в формате XML. В таком случае обратите внимание на переменную $HTTP_RAW_POST_DATA, в ней содержится XML-документ, сгенерированный браузером, который в дальнейшем можно обработать предпочитаемым вами движком XSLT или парсером документа.
Если разметка вас не интересует, и вы хотите, чтобы передаваемые
данные были помещены в стандартный массив $_POST,
вы можете указать клиентскому браузеру на необходимость
отправлять данные в формате application/x-www-form-urlencoded.
Для этого установите атрибут method значением
urlencoded-post.
Пример #2 Использование XForm совместно с массивом $_POST
<h:html xmlns:h="http://www.w3.org/1999/xhtml"
xmlns="http://www.w3.org/2002/xforms">
<h:head>
<h:title>Поиск</h:title>
<model>
<submission action="http://example.com/search"
method="urlencoded-post" id="s"/>
</model>
</h:head>
<h:body>
<h:p>
<input ref="q"><label>Что искать?</label></input>
<submit submission="s"><label>Найти</label></submit>
</h:p>
</h:body>
</h:html>
Замечание: В дополнение к вышесказанному следует заметить, что большое количество браузеров не поддерживают XForms. Если приведённые примеры потерпели неудачу, проверьте версию используемого вами браузера.
Данная возможность позволяет загружать как текстовые, так и бинарные файлы. С помощью PHP-функций аутентификации и работы с файлами вы имеете полный контроль над тем, кому разрешено загружать файлы и что делать с файлом после его загрузки.
PHP способен получать загруженные файлы из любого браузера, совместимого со стандартом RFC-1867.
Замечание: Смежные замечания по конфигурации
Также ознакомьтесь с описанием директив file_uploads, upload_max_filesize, upload_tmp_dir, post_max_size и max_input_time конфигурационного файла php.ini
Также следует заметить, что PHP поддерживает загрузку файлов методом PUT, который используется в клиентах Netscape Composer и W3C Amaya. Для получения более детальной документации обратитесь к разделу поддержка метода PUT.
Пример #1 Форма для загрузки файлов
Страница для загрузки файлов может быть реализована при помощи специальной формы, которая выглядит примерно так:
<!-- Тип кодирования данных, enctype, ДОЛЖЕН БЫТЬ указан ИМЕННО так -->
<form enctype="multipart/form-data" action="__URL__" method="POST">
<!-- Поле MAX_FILE_SIZE должно быть указано до поля загрузки файла -->
<input type="hidden" name="MAX_FILE_SIZE" value="30000" />
<!-- Название элемента input определяет имя в массиве $_FILES -->
Отправить этот файл: <input name="userfile" type="file" />
<input type="submit" value="Отправить файл" />
</form>
В приведённом выше примере __URL__ необходимо заменить ссылкой
на PHP-скрипт.
Скрытое поле MAX_FILE_SIZE (значение
необходимо указывать в байтах) должно предшествовать полю
для выбора файла, и его значение является максимально
допустимым размером принимаемого файла в PHP.
Рекомендуется всегда использовать эту переменную, так как она
предотвращает тревожное ожидание пользователей при передаче
огромных файлов, только для того, чтобы узнать, что файл
слишком большой и передача фактически не состоялась.
Имейте в виду, что обойти это ограничение на стороне браузера достаточно
просто, следовательно, вы не должны полагаться на то, что
все файлы большего размера будут блокированы при помощи этой
возможности. Это по большей части удобная возможность для
пользователей клиентской части вашего приложения.
Однако настройки PHP (на сервере) касательно
максимального размера обойти невозможно.
Замечание:
Также следует убедиться, что форма загрузки имеет атрибут
enctype="multipart/form-data", в противном случае загрузка файлов на сервер не произойдёт.
Глобальный массив $_FILES содержит всю информацию о загруженных файлах. Его содержимое для нашего примера приводится ниже. Обратите внимание, что здесь предполагается использование имени userfile для поля выбора файла, как и в приведённом выше примере. На самом деле имя поля может быть любым.
Оригинальное имя файла на компьютере клиента.
Mime-тип файла, в случае, если браузер предоставил такую
информацию. В качестве примера можно привести "image/gif". Этот
mime-тип не проверяется на стороне PHP, так что не полагайтесь
на его значение без проверки.
Размер в байтах принятого файла.
Временное имя, с которым принятый файл был сохранён на сервере.
Код ошибки, которая может возникнуть при загрузке файла.
Полный путь, представленный браузером. Это значение не всегда содержит реальную структуру каталогов и ему нельзя доверять. Доступно, начиная с PHP 8.1.0.
По умолчанию принятые файлы сохраняются на сервере в стандартной временной папке до тех пор, пока не будет задана другая директория при помощи директивы upload_tmp_dir конфигурационного файла php.ini. Директорию сервера по умолчанию можно сменить, установив переменную TMPDIR для окружения, в котором выполняется PHP. Установка этой переменной при помощи функции putenv() внутри PHP-скрипта работать не будет. Эта переменная окружения также может использоваться для того, чтобы удостовериться, что другие операции также работают с принятыми файлами.
Пример #2 Проверка загружаемых на сервер файлов
Для получения более детальной информации вы можете ознакомиться с описанием функций is_uploaded_file() и move_uploaded_file(). Следующий пример принимает и обрабатывает загруженный при помощи формы файл.
<?php
$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
echo '<pre>';
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "Файл корректен и был успешно загружен.\n";
} else {
echo "Возможная атака с помощью файловой загрузки!\n";
}
echo 'Некоторая отладочная информация:';
print_r($_FILES);
print "</pre>";
?>PHP-скрипт, принимающий загруженный файл, должен реализовывать логику, необходимую для определения дальнейших действий над принятым файлом. Например, вы можете проверить переменную $_FILES['userfile']['size'], чтобы отсечь слишком большие или слишком маленькие файлы. Также вы можете использовать переменную $_FILES['userfile']['type'] для исключения файлов, которые не удовлетворяют критерию касательно типа файла, однако, принимайте во внимание, что это поле полностью контролируется клиентом, используйте его только в качестве первой из серии проверок. Также вы можете использовать $_FILES['userfile']['error'] и коды ошибок при реализации вашей логики. Независимо от того, какую модель поведения вы выбрали, вы должны удалить файл из временной папки или переместить его в другую директорию.
В случае, если при отправке формы файл выбран не был, PHP установит переменную $_FILES['userfile']['size'] значением 0, а переменную $_FILES['userfile']['tmp_name'] - none.
По окончанию работы скрипта, если загруженный файл не был переименован или перемещён, он будет автоматически удалён из временной папки.
Пример #3 Загрузка массива файлов
PHP поддерживает возможность передачи массива из HTML в том числе и с файлами.
<form action="" method="post" enctype="multipart/form-data"> <p>Изображения: <input type="file" name="pictures[]" /> <input type="file" name="pictures[]" /> <input type="file" name="pictures[]" /> <input type="submit" value="Отправить" /> </p> </form>
<?php
foreach ($_FILES["pictures"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["pictures"]["tmp_name"][$key];
// basename() может спасти от атак на файловую систему;
// может понадобиться дополнительная проверка/очистка имени файла
$name = basename($_FILES["pictures"]["name"][$key]);
move_uploaded_file($tmp_name, "data/$name");
}
}
?>Полоса прогресса загрузки файлов может быть реализована с помощью "отслеживания прогресса загрузки файлов с помощью сессий".
PHP возвращает код ошибки наряду с другими
атрибутами принятого файла. Он расположен в массиве, создаваемом PHP
при загрузке файла, и может быть получен при обращении по ключу
error. Другими словами, код ошибки можно
найти в $_FILES['userfile']['error'].
UPLOAD_ERR_OKЗначение: 0; Ошибок не возникло, файл был успешно загружен на сервер.
UPLOAD_ERR_INI_SIZEЗначение: 1; Размер принятого файла превысил максимально допустимый размер, который задан директивой upload_max_filesize конфигурационного файла php.ini.
UPLOAD_ERR_FORM_SIZEЗначение: 2; Размер загружаемого файла превысил значение MAX_FILE_SIZE, указанное в HTML-форме.
UPLOAD_ERR_PARTIALЗначение: 3; Загружаемый файл был получен только частично.
UPLOAD_ERR_NO_FILEЗначение: 4; Файл не был загружен.
UPLOAD_ERR_NO_TMP_DIRЗначение: 6; Отсутствует временная папка.
UPLOAD_ERR_CANT_WRITEЗначение: 7; Не удалось записать файл на диск.
UPLOAD_ERR_EXTENSIONЗначение: 8; Модуль PHP остановил загрузку файла. PHP не предоставляет способа определить, какой модуль остановил загрузку файла; в этом может помочь просмотр списка загруженных модулей с помощью phpinfo().
Опция MAX_FILE_SIZE не должна позволять передачу файлов,
размер которых превышает лимит, установленный конфигурационной директивой
upload_max_filesize в php.ini.
Ограничение по умолчанию составляет 2 мегабайта.
В случае, если установлены ограничения памяти, вам может понадобиться увеличить значение опции memory_limit. Убедитесь в том, что значение memory_limit достаточно велико.
В случае, если опция max_execution_time
установлена слишком маленьким значением, необходимое время работы скрипта
может превышать это значение. Убедитесь в том, что значение
max_execution_time достаточно велико.
Замечание: Директива max_execution_time касается исключительно времени, используемого непосредственно самим скриптом. Время, потраченное на внешние действия, такие как системные вызовы при помощи функции system() или sleep(), обращения к базе данных, а также время, потраченное на загрузку файла и другие действия, происходящие вне скрипта, не учитываются при определении максимально допустимого промежутка времени, отведённого для выполнения скрипта.
Директива max_input_time указывает
максимально допустимое время в секундах для получения входящих данных,
в том числе и загружаемых файлов. В случае, если вы имеете дело с несколькими
или большими файлами, либо удалённые пользователи используют медленный
канал, ограничение по умолчанию в 60 секунд может быть превышено.
Если директива post_max_size
слишком мала, большие файлы не смогут быть загружены на сервер.
Убедитесь, что значение директивы post_max_size достаточно велико.
Опция
max_file_uploads
контролирует максимальное количество загружаемых файлов в течение
одного запроса. Если загружается большее количество файлов,
чем указано в этом ограничении, то массив $_FILES
прекратит дальнейшую обработку файлов по достижении этого ограничения.
Например, если
max_file_uploads установлено
в 10, то $_FILES никогда не будет
содержать больше 10 элементов.
Если не проверять, с какими файлами вы работаете, пользователи могут получить доступ к конфиденциальной информации, расположенной в других директориях.
Поскольку разные системы по-разному работают с файловой структурой, нет никаких гарантий того, что файлы с экзотическими именами (например, которые содержат пробельные символы) будут обработаны корректно.
Разработчики не должны использовать одинаковые имена для
обычных полей ввода (тег input) и полей
выбора файла в пределах одной и той же формы (например, используя имя
для тега input наподобие foo[]).
Загрузку нескольких файлов можно реализовать используя, например,
различные значения name для тега input.
Также можно одновременно загружать несколько файлов и автоматически получить их в виде массива. Для реализации такой возможности используйте тот же синтаксис массива в HTML-форме, что и для множественных полей select и checkbox:
Пример #1 Загрузка нескольких файлов
<form action="file-upload.php" method="post" enctype="multipart/form-data"> Файлы:<br /> <input name="userfile[]" type="file" /><br /> <input name="userfile[]" type="file" /><br /> <input type="submit" value="Отправить" /> </form>
В случае, если такая форма была отправлена, массивы $_FILES['userfile'], $_FILES['userfile']['name'], и $_FILES['userfile']['size'] будут инициализированы.
Например, предположим, что были загружены файлы /home/test/review.html и /home/test/xwp.out. В таком случае переменная $_FILES['userfile']['name'][0] будет установлена значением review.html, а переменная $_FILES['userfile']['name'][1] - значением xwp.out. Аналогично, переменная $_FILES['userfile']['size'][0] будет содержать размер файла review.html и так далее.
Переменные $_FILES['userfile']['name'][0], $_FILES['userfile']['tmp_name'][0], $_FILES['userfile']['size'][0] и $_FILES['userfile']['type'][0] также будут инициализированы.
Конфигурационная директива max_file_uploads регулирует лимит одновременно загружаемых файлов в течение одного запроса. Вам необходимо будет убедиться, что ваша форма не пытается загрузить файлов больше этого лимита за один запрос.
Пример #2 Загрузка всего каталога
В полях загрузки HTML-файла можно загрузить весь каталог с помощью атрибута webkitdirectory.
Он поддерживается большинством современных браузеров.
С помощью информации full_path можно сохранить относительные пути
или восстановить тот же каталог на сервере.
<form action="file-upload.php" method="post" enctype="multipart/form-data"> Загрузка каталога:<br /> <input name="userfile[]" type="file" webkitdirectory multiple /> <input type="submit" value="Загрузить файлы" /> </form>
Атрибут webkitdirectory нестандартен и не входит в стандартную поставку.
Не используйте его на рабочих сайтах: он работает не у всех пользователей.
Между реализациями также может быть большая несовместимость, также поведение может измениться в будущем.
PHP анализирует только информацию об относительном пути, отправленную браузером/пользовательским агентом
и передаёт эту информацию в массив $_FILES.
Нет никакой гарантии, что значения в массиве full_path содержат реальную структуру каталогов
и приложение PHP не должно доверять этой информации.
PHP поддерживает загрузку файлов методом HTTP PUT, который используется в некоторых клиентах для загрузки файлов на сервер. Запросы PUT намного проще, чем загрузка файла с использованием POST-запросами и выглядят примерно так:
PUT /path/filename.html HTTP/1.1
Такой вызов означает, что удалённый клиент хотел бы сохранить
файл под именем /path/filename.html в
дереве каталогов вашего веб-сервера.
Очевидно, что возможность клиента автоматически перезаписывать
файлы веб-сервера при помощи Apache или PHP не является
хорошим решением. Поэтому для того, чтобы обрабатывать такие
запросы, вам необходимо указать веб-серверу PHP-скрипт,
которому вы доверяете их обработку. В веб-сервере Apache вы
можете сделать это, используя директиву Script.
Как правило, эта директива расположена внутри блока
<Directory> или же внутри блока
<VirtualHost>. Сама запись выглядит
следующим образом:
Script PUT /put.php
Это указывает веб-серверу Apache на необходимость перенаправлять все PUT-запросы, контекст которых совпадает с контекстом, в которым вы разместили эту строку, в файл put.php. Предполагается, что файлы с расширением .php обрабатываются, как PHP-скрипты, и что сам PHP установлен и работает. Ресурсом назначения для всех PUT-запросов на этот скрипт должен быть сам скрипт, а не имя файла, которое должен иметь загружаемый файл.
Внутри вашего файла put.php вы можете поместить что-нибудь похожее на следующий пример. Он скопирует содержимое загруженного файла в файл myputfile.ext на сервер. Возможно, вам понадобится осуществить несколько проверок и/или аутентифицировать пользователя перед выполнением копирования этого файла.
Пример #1 Сохранение файлов, отправленных через HTTP PUT
<?php
/* PUT данные приходят в потоке ввода stdin */
$putdata = fopen("php://input", "r");
/* Открываем файл на запись */
$fp = fopen("myputfile.ext", "w");
/* Читаем 1 KB данных за один раз
и пишем в файл */
while ($data = fread($putdata, 1024))
fwrite($fp, $data);
/* Закрываем потоки */
fclose($fp);
fclose($putdata);
?>В случае, если опция allow_url_fopen включена в конфигурационном файле php.ini, вы можете использовать URL-адреса HTTP и FTP в большинстве функций, принимающих в качестве параметра имя файла. Также вы можете использовать ссылки в операторах include, include_once, require и require_once (для корректной работы этих функций должна быть включена опция allow_url_include). Дополнительную информацию о поддерживаемых в PHP протоколах вы можете найти в Поддерживаемые протоколы и обёртки.
Например, вы можете использовать это для того, чтобы открыть файл на удалённом сервере, извлечь необходимые вам данные и использовать их в запросе к базе данных или же просто отобразить их в дизайне вашего сайта.
Пример #1 Получение заголовка удалённой страницы
<?php
$file = fopen ("http://www.example.com/", "r");
if (!$file) {
echo "<p>Невозможно открыть удалённый файл.\n";
exit;
}
while (!feof ($file)) {
$line = fgets ($file, 1024);
/* Сработает, только если заголовок и сопутствующие теги расположены в одной строке */
if (preg_match ("@\<title\>(.*)\</title\>@i", $line, $out)) {
$title = $out[1];
break;
}
}
fclose($file);
?>Вы также можете работать с удалёнными файлами, расположенными на FTP-сервере (подразумевается, что вы авторизовались с необходимыми для этого привилегиями). Таким образом вы можете только создавать новые файлы, но попытка перезаписать существующий файл при помощи функции fopen() приведёт к ошибке.
Для того, чтобы авторизоваться под пользователем, отличным от 'anonymous',
вам необходимо указать логин (и, возможно, пароль) в адресной строке, например
так: 'ftp://user:password@ftp.example.com/path/to/file'. (Вы можете
использовать этот же синтаксис для доступа к удалённым файлам по HTTP-протоколу,
если необходима Basic-аутентификация.)
Пример #2 Сохранение данных на удалённом сервере
<?php
$file = fopen ("ftp://ftp.example.com/incoming/outputfile", "w");
if (!$file) {
echo "<p>Невозможно перезаписать удалённый файл.\n";
exit;
}
/* Запись данных. */
fwrite ($file, $_SERVER['HTTP_USER_AGENT'] . "\n");
fclose ($file);
?>
Замечание:
Глядя на приведённый выше пример, у вас может возникнуть идея использовать эту технику для ведения удалённого лог-файла. К сожалению, это нереализуемо, поскольку попытка записи в уже существующий удалённый файл при помощи функции fopen() приведёт к ошибке. В реализации распределённого логирования, возможно, вам поможет функция syslog().
Статус соединения сохраняется внутренними механизмами PHP. Ниже перечислены четыре возможные состояния:
Во время штатного выполнения PHP-скрипта установлен статус NORMAL. В случае, если удалённый клиент разорвал соединение, статус изменяется на ABORTED. Чаще всего отсоединение удалённого клиента происходит при нажатии кнопки "Stop" в браузере. В случае, если достигается установленный временной лимит (ознакомьтесь с функцией set_time_limit()), будет установлен статус TIMEOUT.
Вы можете решать, приводит ли отключение клиента к завершению вашего
скрипта. Иногда бывает необходимо, чтобы скрипт выполнился до конца, даже
если отсутствует удалённый браузер, которому адресован весь вывод.
По умолчанию скрипт завершает свою работу при отключении клиента. Это
поведение может быть изменено при помощи опции ignore_user_abort
в конфигурационном файле php.ini. Такого же результата
можно добиться, указав php_value ignore_user_abort в конфигурационном
файле Apache httpd.conf или воспользовавшись функцией
ignore_user_abort().
Если вы явно не указали на необходимость игнорировать разрыв соединения
с клиентом, выполнение скрипта будет прервано. Исключением является
тот случай, если используя register_shutdown_function(),
вы указали специальную функцию, вызываемую при завершении скрипта.
В таком случае после того, как пользователь нажал кнопку "Stop" в своём
браузере, при первой же попытке что-либо вывести PHP обнаруживает, что
соединение с клиентом было утеряно, и вызывает завершающую функцию.
Эта функция также вызывается при нормальном завершении работы вашего
скрипта, поэтому для того, чтобы выполнить некоторые специфические
действия при отсоединении клиента, вам понадобится функция
connection_aborted(), которая возвращает
true, если соединение было разорвано.
Выполнение вашего скрипта также может быть прервано встроенным таймером.
Стандартное ограничение по времени составляет 30 секунд, изменить его
можно при помощи директивы max_execution_time в конфигурационном
файле php.ini. Такого же результата можно достичь,
добавив php_value max_execution_time в конфигурационный файл Apache
httpd.conf или воспользовавшись функцией set_time_limit().
При достижении скриптом временного лимита выполнение скрипта прерывается
и вызывается завершающая функция, если она была указана. Уточнить
причину завершения скрипта вы можете при помощи функции
connection_status(), которая возвращает
2, если скрипт был прерван по достижению временного ограничения.
Единственное, что следует заметить - что оба статуса: ABORTED и TIMEOUT, - могут быть установлены одновременно. Это может произойти в том случае, если вы явно указали необходимость игнорировать отсоединение удалённого клиента. В таком случае после разрыва соединения, отметив этот факт, PHP продолжит выполнение скрипта, и при достижении временного лимита будет вызвана завершающая функция, если таковая была указана. В этой точке вы можете обнаружить, что connection_status() вернёт значение 3.
Постоянные соединения представляют собой связи с базами данных, которые не закрываются при завершении скрипта. При получении запроса на постоянное соединение PHP вначале проверяет, имеется ли идентичное постоянное соединение (которое было открыто при предыдущих обращениях) и, если таковое было найдено, использует его. В случае, если идентичного соединения нет, PHP создаёт новое. Под "идентичным" подразумевается соединение, открытое на том же хосте с таким же именем пользователя и паролем (если они указаны).
Та часть разработчиков, которая не имеет чёткого представления о том, как работает веб-сервер и как распределяется нагрузка, могут получить ошибочное представление о том, чем на самом деле являются постоянные соединения. В частности, постоянные соединения не предоставляют возможность открывать 'пользовательские сессии' в том же самом соединении, они не предоставляют возможность организовывать более эффективные транзакции, также они не предоставляют множества других полезных возможностей. Фактически, постоянные соединения не предоставляют никакой функциональности, которая была бы невозможна в непостоянных аналогичных соединениях.
Почему?
Это зависит от того, как происходит взаимодействие с веб-сервером. Существует три основных способа использования PHP сервером для генерации веб-страниц.
Первый способ заключается в том, чтобы использовать PHP как CGI-обёртку. При этом PHP-интерпретатор создаётся и уничтожается при каждом обращении к странице (PHP-скрипту). Поскольку интерпретатор уничтожается после каждого запроса к серверу, все используемые им ресурсы (в том числе и соединение с базой данных) закрываются. Следовательно, в этом случае вы не получите ничего от использования постоянных соединений - их просто нет.
Второй, и наиболее популярный способ - использовать PHP как модуль в сервере, который использует несколько процессов. В число таких серверов сейчас входит только Apache. В таком случае, можно выделить один процесс (родительский), который координирует работу всех остальных процессов (дочерних), которые фактически и выполняют работу по обслуживанию веб-страниц. При каждом обращении клиента к серверу запрос перенаправляется одному из дочерних процессов, который в данный момент не занят обслуживанием другого клиента. Это означает, что когда тот же самый клиент выполняет повторный запрос к серверу, он может быть обработан другим дочерним процессом, отличным от того, который был при первом обращении. После открытия постоянного соединения каждая последующая страница, требующая соединения с базой данных, может использовать уже установленное ранее соединение с SQL-сервером.
Третий способ - использовать PHP в качестве плагина в многопоточном веб-сервере. В настоящее время в PHP реализована поддержка ISAPI, WSAPI, и NSAPI (для Windows-платформ), которые позволяют подключать PHP к таким многопоточным серверам, как Netscape FastTrack (iPlanet), Microsoft's Internet Information Server (IIS) и O'Reilly WebSite Pro. В этом случае поведение PHP полностью аналогично рассмотренной ранее модели с использованием нескольких процессов.
Если постоянные соединения не предоставляют никакой дополнительной функциональности, чем же они тогда так хороши?
Ответ содержится в повышении эффективности. Постоянные соединения полезны в том случае, если при открытии большого количества SQL-соединений возникает ощутимая нагрузка на сервер. То, насколько велика эта нагрузка, зависит от многих факторов. Например, от того, какая именно база данных используется, находится ли она на том же компьютере что и ваш веб-сервер, насколько загружена машина, на которой установлен SQL-сервер, и так далее. В случае, если затраты на установку соединения велики, постоянные соединения могут вам существенно помочь. Они позволяют дочернему процессу на протяжении всего жизненного цикла использовать одно и то же соединение вместо того, чтобы создавать его при обработке каждой страницы, которая взаимодействует с SQL-сервером. Это означает, что каждый дочерний процесс, открывший постоянное соединение, будет иметь своё собственное соединение с сервером. Например, если у вас запущено 20 дочерних процессов, которые выполнили скрипт, использовавший постоянное соединение с SQL-сервером, вы получите 20 различных соединений с SQL-сервером, по одному на каждый дочерний процесс.
Следует заметить, что этот подход имеет некоторые недостатки: если вы используете базу данных с ограниченным количеством возможных подключений, оно может быть превышено количеством запрашиваемых дочерними процессами постоянных соединений. Например, если ваша база данных позволяет 16 одновременных соединений, и во время нагрузки на сервер 17 дочерних процессов попробуют открыть соединение, одна из попыток потерпит неудачу. Если в вашем коде содержатся ошибки, не позволяющие закрывать соединение (например, бесконечные циклы), база данных с 32 одновременными подключениями вскоре может оказаться заблокированной. Информацию о том, как обрабатывать открытые и неиспользуемые соединения, вы можете найти в документации к вашей базе данных.
Есть ещё два дополнительных предостережения, которые следует помнить при работе с постоянными соединениями. В случае, если скрипт блокирует таблицу и по каким-либо причинам не может её освободить, при использовании постоянного соединения все последующие скрипты, которые используют это соединение будут блокированы бесконечно долго и могут потребовать рестарта веб-сервера или сервера баз данных. Второе предостережение заключается в том, что открытые транзакции, если они не были закрыты до завершения работы скрипта, будут продолжены в следующем скрипте, использующем это же постоянное соединение. Исходя из этого, вы можете использовать функцию register_shutdown_function() для указания простой функции, которая снимает блокировку таблиц или отката ваших транзакций. Ещё лучше избежать этих проблем полностью, не используя постоянные соединения в скриптах, которые используют блокировку таблиц или транзакции (при этом вы всё ещё можете использовать их где-то в другом месте).
Важное резюме. Постоянные соединения были созданы для точного отображения обыкновенных соединений. Это означает, что у вас всегда есть возможность заменить все постоянные соединения непостоянными, и это никак не отразится на поведении скрипта. Такая замена может повлиять (и, наверное, повлияет) на эффективность работы скрипта, но никак не на его поведение.
Смотрите также ibase_pconnect(), ociplogon(), odbc_pconnect(), oci_pconnect(), pfsockopen() и pg_pconnect().
Основная цель этого CLI SAPI - разработка консольных приложений на PHP. Имеется довольно много различий между CLI SAPI и другими видами SAPI, которые будут рассмотрены в этой главе. Стоит отметить, что CLI SAPI и CGI - различные SAPI-интерфейсы, хотя в их поведении много общего.
CLI SAPI включается по умолчанию с помощью опции --enable-cli, но может быть выключен опцией --disable-cli при запуске ./configure.
Имя, расположение и существование бинарных модулей CLI/CGI зависит от того, как именно установлен PHP в вашей системе. По умолчанию при выполнении make создаётся как CGI-, так и CLI-модуль, размещённые в директориях sapi/cgi/php-cgi и sapi/cli/php соответственно, внутри директории с исходниками PHP. Следует заметить, что оба файла имеют одинаковое название: php. Что произойдёт при выполнении make install, зависит от того, какие опции вы указали на стадии конфигурирования. Если выбран модуль SAPI во время выполнения, например, apxs, или используется опция опция --disable-cgi, модуль CLI будет скопирован в {PREFIX}/bin/php при выполнении make install, в противном случае будет скопирован CGI-модуль. Например, если задана опция --with-apxs, то при выполнении make install CLI-версия будет скопирована в {PREFIX}/bin/php. Если вы хотите переопределить установку CGI-модуль, используйте make install-cli после выполнения make install. В качестве альтернативы вы могли бы указать опцию --disable-cgi в строке конфигурации.
Замечание:
Поскольку обе опции, --enable-cli и --enable-cgi, включены по умолчанию, просто наличие --enable-cli в команде конфигурации необязательно означает, что CLI будет скопирован в {PREFIX}/bin/php при выполнении make install.
Бинарный файл CLI входит в дистрибутив для Windows в основной папке в качестве файлаphp.exe. CGI-версия находится в файле php-cgi.exe. Кроме того, в дистрибутив входит файл php-win.exe, если PHP был сконфигурирован с помощью --enable-cli-win32. Он полностью эквивалентен CLI-версии, за исключением того, что абсолютно ничего не выводит, и, таким образом, не предоставляет консоль (окно терминала не появляется на экране).
Замечание: Какой из вариантов SAPI установлен?
Выполните из командной строки php -v для получения информации о том, является ли php CGI или CLI. Также вы можете использовать функцию php_sapi_name() или константу
PHP_SAPI.
Замечание:
Соответствующую страницу руководства (
man) Unix можно просмотреть с помощью команды man php в консоли.
Основные отличия CLI SAPI от остальных реализаций SAPI:
В отличие от CGI SAPI, заголовки не пишутся в поток вывода.
Несмотря на то, что в CGI SAPI есть способ подавления HTTP-заголовков, в CLI SAPI нет возможности их включить.
CLI по умолчанию запускается в тихом режиме, тем не менее, ключи -q и --no-header сохранены для обратной совместимости, что позволяет использовать старые CGI-скрипты.
Текущая директория не изменяется на рабочую директорию скрипта. (Ключи -C и --no-chdir сохранены для обратной совместимости)
Сообщения об ошибках выдаются в текстовом режиме (без HTML-форматирования).
Некоторые настройки php.ini переопределяются CLI SAPI, поскольку они не имеют смысла при работе в командной строке:
| Директива | Значение по умолчанию в CLI SAPI | Комментарий |
|---|---|---|
| html_errors | false |
По умолчанию false, т.к. бывает достаточно сложно читать в консоли
сообщения об ошибке, когда они наполнены бессмысленными HTML-тегами.
|
| implicit_flush | true |
Обычно в консоли желательно отображать вывод, например, из print, echo и других, сразу же минуя буфер. Тем не менее, по-прежнему можно использовать буферизацию вывода для отложенного вывода или манипуляций с ним. |
| max_execution_time | 0 (без ограничений) | PHP, выполняемый в консоли, как правило, используется для более широкого диапазона задач, чем обычные веб-скрипты. И так как они могут выполняться очень долго, то максимальное время выполнения неограниченно. |
| register_argc_argv | true |
Установка этой опции в значение При использовании CLI SAPI переменные $argc и $argv автоматически заполняются соответствующими значениями. Эти значения можно также найти в массиве $_SERVER, например: $_SERVER['argv']. |
| output_buffering | false |
Несмотря на то, что эта опция php.ini жёстко установлена в |
| max_input_time | false |
PHP CLI не поддерживает GET, POST или загрузку файлов. |
Замечание:
Эти директивы не могут быть инициализированы другими значениями из конфигурационного файла php.ini или любого другого (в случае, если он указан). Это ограничение связано с тем, что значения применяются после обработки конфигурационных файлов. Тем не менее, эти значения могут быть изменены во время работы скрипта (хотя это не имеет особого смысла для всех них, например register_argc_argv).
Замечание:
Рекомендуется установить опцию ignore_user_abort для скриптов, используемых из командной строки. За подробностями обращайтесь к функции ignore_user_abort().
Для облегчения работы в окружении оболочки было определено некоторое количество констант для потоков ввода/вывода.
CLI SAPI не изменяет текущую директорию на директорию исполняемого скрипта.
Пример #1 Пример, демонстрирующий разницу с CGI SAPI:
<?php
// Простейший тестовый скрипт под названием test.php
echo getcwd(), "\n";
?>В случае, если используется CGI-версия, результат работы будет следующим:
$ pwd /tmp $ php -q another_directory/test.php /tmp/another_directory
Это наглядно демонстрирует, что PHP изменяет текущую директорию на директорию исполняемого скрипта.
Использование CLI SAPI даёт другой результат:
$ pwd /tmp $ php -f another_directory/test.php /tmp
Это обеспечивает большую гибкость при написании консольных скриптов на PHP.
Замечание:
CGI SAPI позволяет получить аналогичное CLI SAPI поведение в случае использования ключа -C при запуске из командной строки.
Список опций командной строки, предоставляемых PHP, могут быть получены в любой момент, запустив PHP с ключом -h:
Usage: php [options] [-f] <file> [--] [args...]
php [options] -r <code> [--] [args...]
php [options] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...]
php [options] [-B <begin_code>] -F <file> [-E <end_code>] [--] [args...]
php [options] -- [args...]
php [options] -a
-a Run interactively
-c <path>|<file> Look for php.ini file in this directory
-n No php.ini file will be used
-d foo[=bar] Define INI entry foo with value 'bar'
-e Generate extended information for debugger/profiler
-f <file> Parse and execute <file>.
-h This help
-i PHP information
-l Syntax check only (lint)
-m Show compiled in modules
-r <code> Run PHP <code> without using script tags <?..?>
-B <begin_code> Run PHP <begin_code> before processing input lines
-R <code> Run PHP <code> for every input line
-F <file> Parse and execute <file> for every input line
-E <end_code> Run PHP <end_code> after processing all input lines
-H Hide any passed arguments from external tools.
-S <addr>:<port> Run with built-in web server.
-t <docroot> Specify document root <docroot> for built-in web server.
-s Output HTML syntax highlighted source.
-v Version number
-w Output source with stripped comments and whitespace.
-z <file> Load Zend extension <file>.
args... Arguments passed to script. Use -- args when first argument
starts with - or script is read from stdin
--ini Show configuration file names
--rf <name> Show information about function <name>.
--rc <name> Show information about class <name>.
--re <name> Show information about extension <name>.
--rz <name> Show information about Zend extension <name>.
--ri <name> Show configuration for extension <name>.
| Опция | Полное название | Описание |
|---|---|---|
| -a | --interactive |
Запустить PHP в интерактивном режиме. Для получения дополнительной информации смотрите раздел Интерактивная консоль. |
| -b | --bindpath |
Путь связывания библиотек (Bind Path) для внешнего режима FASTCGI Server (только для CGI). |
| -C | --no-chdir |
Не менять текущую директорию на директорию скрипта (только для CGI). |
| -q | --no-header |
Тихий режим. Подавляет вывод заголовков HTTP (только для CGI). |
| -T | --timing |
Измерить время выполнения скрипта, повторенного count раз (только для CGI). |
| -c | --php-ini |
Указывает, либо директорию, в которой нужно искать
конфигурационный файл php.ini, либо пользовательский
$ php -c /custom/directory/ my_script.php $ php -c /custom/directory/custom-file.ini my_script.php Если эта опция не указана, поиск php.ini будет осуществлён в местах по умолчанию. |
| -n | --no-php-ini |
Полностью игнорировать php.ini. |
| -d | --define |
Устанавливает пользовательское значение для каждой из конфигурационных опций, доступных в php.ini. Синтаксис выглядит следующим образом: -d configuration_directive[=value]
# Если значение опущено, то соответствующей опции будет присвоено значение "1"
$ php -d max_execution_time
-r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(1) "1"
# Указание пустого значения установит соответствующую опцию значением ""
php -d max_execution_time=
-r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(0) ""
# Конфигурационная переменная будет установлена любым значением, указанным после символа '='
$ php -d max_execution_time=20
-r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(2) "20"
$ php
-d max_execution_time=doesntmakesense
-r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(15) "doesntmakesense"
|
| -e | --profile-info |
Включить режим расширенной информации, используемый отладчиком/профайлером. |
| -f | --file |
Парсит и исполняет файл, указанный в опции -f. Этот параметр необязателен и может быть опущен - достаточно просто указать имя запускаемого файла. |
| -h и -? | --help и --usage | Выводит список опций командной строки с однострочным описанием того, что они делают. |
| -i | --info | Вызывает phpinfo() и выводить её результат. В случае, если PHP работает некорректно, рекомендуется выполнить php -i и посмотреть, выводятся ли сообщения об ошибках до или вместо информационных таблиц. Учитывайте, что в случае использования CGI-модуля весь вывод будет в формате HTML и, как следствие, очень большим. |
| -l | --syntax-check |
Предоставляет удобный способ для проверки заданного
PHP-кода на наличие синтаксических ошибок.
В случае успешной проверки будет напечатана следующая фраза:
" Данная опция не будет обнаруживать фатальные ошибки (например, вызов неопределённых функций). Используйте опцию -f, если вы хотите проверить код на наличие фатальных ошибок.
|
| -m | --modules |
Пример #1 Вывод встроенных (и загруженных) модулей PHP и Zend $ php -m [PHP Modules] xml tokenizer standard session posix pcre overload mysql mbstring ctype [Zend Modules] |
| -r | --run |
Позволяет выполнять PHP-код, указанный
непосредственно в командной строке. Открывающие и закрывающие
PHP-теги (
|
| -B | --process-begin |
Выполняемый код PHP перед обработкой потока ввода (stdin). |
| -R | --process-code |
PHP-код, выполняемый для каждой строки ввода. В этом режиме есть две специальные переменные: $argn и $argi. $argn содержит строку, которую PHP обрабатывает в данный момент, а $argi содержит номер этой строки. |
| -F | --process-file |
PHP-файл, выполняемый для каждой строки ввода. |
| -E | --process-end |
PHP-код, выполняемый после обработки ввода. Пример #4 Использование опций -B, -R и -E для подсчёта количества строк в проекте. $ find my_proj | php -B '$l=0;' -R '$l += count(@file($argn));' -E 'echo "Всего строк: $l\n";' Всего строк: 37328 |
| -S | --server |
Запускает встроенный веб-сервер. |
| -t | --docroot | Указывает корень документа для встроенного веб-сервера. |
| -s | --syntax-highlight и --syntax-highlighting |
Показать исходный код с подсветкой синтаксиса.
Эта опция использует внутренний механизм для разбора файла
и записи в стандартный поток вывода подсвеченной версии
этого файла. Учтите, что все что она делает, это генерирует
блок
|
| -v | --version |
Пример #5 Использование -v для получения типа SAPI и версии PHP и Zend $ php -v PHP 5.3.1 (cli) (built: Dec 11 2009 19:55:07) Copyright (c) 1997-2009 The PHP Group Zend Engine v2.3.0, Copyright (c) 1998-2009 Zend Technologies |
| -w | --strip |
Показать исходный код без комментариев и пробелов.
|
| -z | --zend-extension |
Загружает модуль Zend. Если передано только имя файла, PHP попытается загрузить этот модуль из пути библиотек по умолчанию (обычно указывается в /etc/ld.so.conf в системах Linux). Передача файла с абсолютным путём не будет использовать системный путь поиска библиотеки. Относительное имя файла, содержащее директорию, укажет PHP подгрузить модуль относительно текущей директории. |
| --ini |
Показывает имена конфигурационных файлов и отсканированные директории. Пример #6 Пример $ php --ini Configuration File (php.ini) Path: /usr/dev/php/5.2/lib Loaded Configuration File: /usr/dev/php/5.2/lib/php.ini Scan for additional .ini files in: (none) Additional .ini files parsed: (none) |
|
| --rf | --rfunction |
Показывает информацию об указанной функции или методе класса (например, количество и названия параметров). Эта опция доступна только в том случае, если PHP был скомпилирован с поддержкой Reflection.
Пример #7 Базовое использование $ php --rf var_dump
Function [ <internal> public function var_dump ] {
- Parameters [2] {
Parameter #0 [ <required> $var ]
Parameter #1 [ <optional> $... ]
}
}
|
| --rc | --rclass |
Показывает информацию об указанном классе (список констант, свойств и методов). Эта опция доступна только в том случае, если PHP был скомпилирован с поддержкой Reflection.
Пример #8 Пример $ php --rc Directory
Class [ <internal:standard> class Directory ] {
- Constants [0] {
}
- Static properties [0] {
}
- Static methods [0] {
}
- Properties [0] {
}
- Methods [3] {
Method [ <internal> public method close ] {
}
Method [ <internal> public method rewind ] {
}
Method [ <internal> public method read ] {
}
}
}
|
| --re | --rextension |
Показывает информацию об указанном модуле (список опций php.ini, определённых функций, констант и классов). Эта опция доступна только в том случае, если PHP был скомпилирован с поддержкой Reflection.
Пример #9 Пример $ php --re json
Extension [ <persistent> extension #19 json version 1.2.1 ] {
- Functions {
Function [ <internal> function json_encode ] {
}
Function [ <internal> function json_decode ] {
}
}
}
|
| --rz | --rzendextension |
Показывает информацию о конфигурации указанного Zend-модуля (та же информация, которая возвращается phpinfo()). |
| --ri | --rextinfo |
Показывает информацию о конфигурации указанного модуля (та же информация, которая возвращается phpinfo()). Конфигурацию ядра можно узнать, указав в качестве имени модуля значение "main".
Пример #10 Пример $ php --ri date date date/time support => enabled "Olson" Timezone Database Version => 2009.20 Timezone Database => internal Default timezone => Europe/Oslo Directive => Local Value => Master Value date.timezone => Europe/Oslo => Europe/Oslo date.default_latitude => 59.930972 => 59.930972 date.default_longitude => 10.776699 => 10.776699 date.sunset_zenith => 90.583333 => 90.583333 date.sunrise_zenith => 90.583333 => 90.583333 |
Замечание:
Опции
-rBRFEH,--iniи--r[fcezi]доступны только в CLI.
В CLI SAPI есть три различных способа запуска PHP-кода:
Указание конкретного файла для запуска.
$ php my_script.php $ php -f my_script.php
Оба способа (с указанием опции -f или без) запустят
файл my_script.php. Нет ограничений, какой
файл запускать; в частности, файлы не обязаны иметь
расширение .php.
Передать PHP-код напрямую в командной строке.
$ php -r 'print_r(get_defined_constants());'
Необходимо быть особо осторожным при использовании этого способа, т.к. может произойти подстановка переменных оболочки при использовании двойных кавычек.
Замечание:
Внимательно прочтите пример: в нем нет открывающих и закрывающих тегов! Опция -r просто в них не нуждается, и их использование приведёт к ошибке разбора.
Передать запускаемый PHP-код через стандартный поток ввода
(stdin).
Это даёт мощную возможность создавать PHP-код и передавать его запускаемому файлу, как показано в этом (вымышленном) примере:
$ some_application | some_filter | php | sort -u > final_output.txt
Как и любое другое консольное приложение, бинарный файл PHP
принимает аргументы, но PHP-скрипт также может получать
аргументы. PHP не ограничивает количество аргументов,
передаваемых в скрипт (оболочка консоли устанавливает
некоторый порог количества символов, которые могут быть переданы;
обычно этого лимита хватает). Переданные аргументы доступны
в глобальном массиве $argv. Первый индекс
(ноль) всегда содержит имя вызываемого скрипта из командной
строки. Учтите, что если код вызывается на лету из командной
строки с помощью опции -r, значением
$argv[0] будет "Стандартный поток" ("Standard input code"); до PHP 7.2.0 это был дефис ("-"). То же самое верно и для кода,
переданного через конвейер из STDIN.
Вторая зарегистрированная глобальная переменная - это $argc, содержащая количество элементов в массиве $argv (а не количество аргументов, переданных скрипту).
Если передаваемые аргументы не начинаются с символа
-, то особых проблем быть не должно.
Передаваемый в скрипт аргумент, который начинается с -
создаст проблемы, т.к. PHP решит, что он сам должен его
обработать. Для предотвращения подобного поведения
используйте разделитель списка аргументов --.
После того, как этот разделитель будет проанализирован PHP, все последующие
аргументы будут переданы в скрипт нетронутыми.
# Эта команда не запустит данный код, но покажет информацию об использовании PHP
$ php -r 'var_dump($argv);' -h
Usage: php [options] [-f] <file> [args...]
[...]
# Эта команда передаст аргумент '-h' в скрипт, предотвратив показ справки PHP
$ php -r 'var_dump($argv);' -- -h
array(2) {
[0]=>
string(1) "-"
[1]=>
string(2) "-h"
}
Однако, в Unix-системах есть ещё один способ использования
PHP для консольных скриптов. Можно написать скрипт,
первая строка которого будет начинаться с
#!/usr/bin/php (или же другой
корректный путь к бинарному файлу PHP CLI).
После этой строки можно поместить обычный PHP-код, заключённый
в открывающие и закрывающие теги PHP. Как только будут установлены
корректные атрибуты запуска на файл (например,
chmod +x test), скрипт может быть
запущен как обычный консольный или perl-скрипт:
Пример #1 Запуск PHP-скрипта как консольного
#!/usr/bin/php
<?php
var_dump($argv);
?>Предполагая, что этот файл назван test и находится в текущей директории, можно сделать следующее:
$ chmod +x test
$ ./test -h -- foo
array(4) {
[0]=>
string(6) "./test"
[1]=>
string(2) "-h"
[2]=>
string(2) "--"
[3]=>
string(3) "foo"
}
Как можно увидеть, в этом случае не нужно заботиться о
передаче параметров, которые начинаются с -.
Исполняемый PHP-файл может использоваться для запуска PHP-скриптов
независимо от веб-сервера. В случае работы в Unix-подобной системе,
необходимо добавить в первую строку файла #! (называемый также "shebang")
чтобы указать, какая из программ должна запускать скрипт.
На Windows-платформах можно назначить обработчик php.exe для файлов
с расширениями .php или создать пакетный
(.bat) файл для запуска скриптов посредством PHP.
Строка, добавляемая в начале скрипта для Unix-систем,
не влияет на их работу в ОС Windows, таким образом можно
создавать кроссплатформенные скрипты. Ниже приведён простой
пример скрипта, выполняемого из командной строки:
Пример #2 Скрипт, предназначенный для запуска из командной строки (script.php)
#!/usr/bin/php
<?php
if ($argc != 2 || in_array($argv[1], array('--help', '-help', '-h', '-?'))) {
?>
Это консольный PHP-скрипт, принимающий один аргумент.
Использование:
<?php echo $argv[0]; ?> <option>
<option> Любое слово, которое вы хотели бы
напечатать. Опции --help, -help, -h,
или -? покажут текущую справочную информацию.
<?php
} else {
echo $argv[1];
}
?>В приведённом выше скрипте в первой строке содержится shebang, указывающий что этот файл должен запускаться PHP. Работа ведётся с CLI-версией, поэтому не будет выведено ни одного HTTP-заголовка.
Скрипт сначала проверяет наличие обязательного одного аргумента (в дополнение к имени скрипта, который также подсчитывается). Если их нет, или если переданный аргумент был --help, -help, -h или -?, выводится справочное сообщение с использованием $argv[0], которое содержит имя выполняемого скрипта. В противном случае просто выводится полученный аргумент.
Для запуска приведённого примера в Unix-системе, нужно сделать его исполняемым и просто выполнить в консоли script.php echothis или script.php -h. В Windows-системе можно создать пакетный файл:
Пример #3 Пакетный файл для запуска PHP-скрипта из командной строки (script.bat)
@echo OFF "C:\php\php.exe" script.php %*
Предполагая, что вышеприведённый скрипт называется script.php, а полный путь к CLI php.exe находится в C:\php\php.exe, этот пакетный файл запустит его с переданными параметрами: script.bat echothis или script.bat -h.
Также можно ознакомиться с модулем Readline для получения дополнительных функций, которые можно использовать для улучшения консольного PHP-скрипта.
В Windows запуск PHP можно настроить без
необходимости указывать C:\php\php.exe или
расширение .php.
Подробнее эта тема описана в разделе
Запуск PHP из
командной строки в Microsoft Windows.
Замечание:
В Windows рекомендуется запускать PHP под актуальной учётной записью пользователя. При работе в сетевой службе некоторые операции не будут выполнены, поскольку "сопоставление имён учётных записей и идентификаторов безопасности не выполнено".
Модуль CLI SAPI определяет несколько констант для потоков ввода/вывода, чтобы упростить работу с командной строкой.
| Константа | Описание |
|---|---|
STDIN |
Уже открытый поток ввода ( <?phpstdin,
можно использовать следующий код:
<?php |
STDOUT |
Уже открытый поток вывода ( <?php |
STDERR |
Уже открытый поток ошибок ( <?php |
Учитывая вышесказанное, нет необходимости самому открывать поток,
например, stderr, а можно просто
использовать уже определённую константу ресурса потока:
php -r 'fwrite(STDERR, "stderr\n");'
Замечание:
Эти константы недоступны, если считывается PHP-скрипт из
stdin.
Модуль CLI SAPI предоставляет интерактивную консоль, используя опцию -a, если PHP был скомпилирован с опцией --with-readline. Начиная с PHP PHP 7.1.0, интерактивная консоль также доступна на Windows, если модуль readline включён.
Используя интерактивную консоль, можно ввести и выполнить непосредственно PHP-код.
Пример #1 Запуск кода в интерактивной консоли
$ php -a
Interactive shell
php > echo 5+8;
13
php > function addTwo($n)
php > {
php { return $n + 2;
php { }
php > var_dump(addtwo(2));
int(4)
php >
Интерактивная консоль также автодополняет (с помощью клавиши Tab) имена функций, констант, классов, переменных, вызовы статических методов и константы классов.
Пример #2 Автодополнение по Tab
Двойное нажатие клавиши Tab при наличии нескольких вариантов дополнения покажет список этих вариантов:
php > strp[TAB][TAB] strpbrk strpos strptime php > strp
Когда есть только одно дополнение, одиночное нажатие Tab дополнит оставшийся текст на той же самой строке:
php > strpt[TAB]ime(
Дополнение также работает для имён, которые были объявлены в течение данной интерактивной сессии:
php > $fooThisIsAReallyLongVariableName = 42; php > $foo[TAB]ThisIsAReallyLongVariableName
Интерактивная консоль хранит историю команд, для доступа к которой можно использовать стрелки вверх и вниз. История хранится в файле ~/.php_history.
Модуль CLI SAPI предоставляет
две новые настройки в php.ini: cli.pager и
cli.prompt. Настройка cli.pager
позволяет использовать внешнюю программу (такую как less)
для постраничного просмотра данных вместо их прямого вывода на экран.
Настройка cli.prompt позволяет задавать
приглашение php > на ввод команды.
Также можно устанавливать настройки php.ini в интерактивной консоли, используя специальное сокращение.
Пример #3 Установка настройки php.ini в интерактивной консоли
Настройка cli.prompt:
php > #cli.prompt=hello world :> hello world :>
Используя обратные апострофы можно задать PHP-код, который выполнится в приглашении на ввод команды:
php > #cli.prompt=`echo date('H:i:s');` php >
15:49:35 php > echo 'hi';
hi
15:49:43 php > sleep(2);
15:49:45 php >
Установка less для постраничного вывода данных:
php > #cli.pager=less php > phpinfo(); (output displayed in less) php >
Настройка cli.prompt поддерживает
несколько управляющих последовательностей:
| Управляющая последовательность | Описание |
|---|---|
\e |
Используется для добавления цветов в приглашение на ввод команды.
Пример: \e[032m\v \e[031m\b \e[34m\> \e[0m
|
\v |
Версия PHP. |
\b |
Отображает в какой части PHP мы находимся. Для примера /*
показывает, что мы находимся в многострочном комментарии. Внешняя область
видимости обозначается как php.
|
\> |
Указывает символ приглашения. По умолчанию это символ >,
но можно изменить, когда оболочка находится внутри незакрытого блока или строки.
Возможные символы: ' " { ( >
|
Замечание:
Файлы, подключённые с помощью опций auto_prepend_file и auto_append_file обрабатываются в этом режиме с некоторыми ограничениями, например, функции должны быть объявлены до их использования.
Если модуль readline недоступен, то до PHP 8.1.0 вызов файла CLI SAPI с параметром -a обеспечивал интерактивный режим.
В этом режиме предполагается, что полный скрипт PHP передаётся через STDIN, а после завершения скрипт оценивается с помощью CRTL+d (POSIX) или CTRL+z с последующим ENTER (Windows).
По сути это то же самое, что и вызов CLI SAPI без параметра -a.
option.
Начиная с PHP 8.1.0, вызов CLI SAPI с параметром -a завершается ошибкой, если модуль readline недоступен.
Веб-сервер предназначен для помощи в разработке приложений. Он также может быть полезным в тестовых целях или для демонстрации приложения, запускаемого в полностью контролируемом окружении. Он не выполняет функции полноценного веб-сервера и не должен использоваться в общедоступных сетях.
Модуль CLI SAPI содержит встроенный веб-сервер.
Веб-сервер выполняет только один однопоточный процесс, поэтому приложения PHP будут останавливаться, если запрос заблокирован.
URI запросы обслуживаются из текущей директории, в которой был запущен PHP, если не используется опция -t для явного указания корневого документа. Если URI запроса не указывает на определённый файл, то будет возвращён index.php или index.html в указанной директории. Если ни один из файлов не существует, то поиск этих файлов будет продолжен в родительской директории и так далее до тех пор, пока они не будут найдены или был достигнут корень документа. Если найден index.php или index.html, он возвращается, а в $_SERVER['PATH_INFO'] будет находится последняя часть URL. В противном случае возвращается 404 код ответа.
Если PHP-файл указывается в командной строке, когда запускается веб-сервер,
то он рассматривается как скрипт "маршрутизации" (router). Скрипт выполняется
в самом начале каждого HTTP-запроса. Если этот скрипт возвращает
false, то запрашиваемый ресурс возвращается как есть.
В противном случае браузеру будет возвращён вывод этого скрипта.
Стандартные MIME-типы возвращаются для файлов со следующими расширениями: .3gp, .apk, .avi, .bmp, .css, .csv, .doc, .docx, .flac, .gif, .gz, .gzip, .htm, .html, .ics, .jpe, .jpeg, .jpg, .js, .kml, .kmz, .m4a, .mov, .mp3, .mp4, .mpeg, .mpg, .odp, .ods, .odt, .oga, .ogg, .ogv, .pdf, .pdf, .png, .pps, .pptx, .qt, .svg, .swf, .tar, .text, .tif, .txt, .wav, .webm, .wmv, .xls, .xlsx, .xml, .xsl, .xsd и .zip.
| Версия | Описание |
|---|---|
| 5.5.12 | .xml, .xsl, и .xsd |
| 5.5.7 | .3gp, .apk, .avi, .bmp, .csv, .doc, .docx, .flac, .gz, .gzip, .ics, .kml, .kmz, .m4a, .mp3, .mp4, .mpg, .mpeg, .mov, .odp, .ods, .odt, .oga, .pdf, .pptx, .pps, .qt, .swf, .tar, .text, .tif, .wav, .wmv, .xls, .xlsx и .zip |
| 5.5.5 | |
| 5.4.11 | .ogg, .ogv, и .webm |
| 5.4.4 | .htm и .svg |
| Версия | Описание |
|---|---|
| 7.4.0 |
Вы можете настроить встроенный веб-сервер так, чтобы он выполнял разветвление нескольких воркеров
для проверки кода, который требует нескольких одновременных запросов
к встроенному веб-серверу. Задайте в переменной окружения
PHP_CLI_SERVER_WORKERS
количество требуемых воркеров перед запуском
сервера.
Не поддерживается в Windows.
Внимание
Эта экспериментальная функция не предназначена для продакшен использования. Обычно встроенный веб-сервер не предназначен для продакшен использования. |
Пример #1 Запуск веб-сервера
$ cd ~/public_html $ php -S localhost:8000
В консоли выведется:
PHP 5.4.0 Development Server started at Thu Jul 21 10:43:28 2011 Listening on localhost:8000 Document root is /home/me/public_html Press Ctrl-C to quit
После URI-запросов http://localhost:8000/ и http://localhost:8000/myscript.html в консоли выведется примерно следующее:
PHP 5.4.0 Development Server started at Thu Jul 21 10:43:28 2011 Listening on localhost:8000 Document root is /home/me/public_html Press Ctrl-C to quit. [Thu Jul 21 10:48:48 2011] ::1:39144 GET /favicon.ico - Request read [Thu Jul 21 10:48:50 2011] ::1:39146 GET / - Request read [Thu Jul 21 10:48:50 2011] ::1:39147 GET /favicon.ico - Request read [Thu Jul 21 10:48:52 2011] ::1:39148 GET /myscript.html - Request read [Thu Jul 21 10:48:52 2011] ::1:39149 GET /favicon.ico - Request read
Обратите внимание, что до PHP 7.4.0 статические ресурсы с символическими ссылками не были доступны в Windows, если только скрипт маршрутизатора не обработал бы их.
Пример #2 Запуск с указанием корневой директории
$ cd ~/public_html $ php -S localhost:8000 -t foo/
В консоли выведется:
PHP 5.4.0 Development Server started at Thu Jul 21 10:50:26 2011 Listening on localhost:8000 Document root is /home/me/public_html/foo Press Ctrl-C to quit
Пример #3 Использование скрипта маршрутизации
В этом примере, запросы изображений будут отображать их, но запросы HTML-файлов будут возвращать "Добро пожаловать в PHP".
<?php
// router.php
if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"])) {
return false; // сервер возвращает файлы напрямую.
} else {
echo "<p>Добро пожаловать в PHP</p>";
}
?>$ php -S localhost:8000 router.php
Встроенный веб-сервер не должен использоваться в общедоступной сети.
Пример #4 Проверка использования веб-сервера CLI
Для совместного использования скрипта маршрутизации при разработке с веб-сервером CLI и в дальнейшем с рабочим (production) веб-сервером:
<?php
// router.php
if (php_sapi_name() == 'cli-server') {
/* Маршрутизация с заданными правилами и возврат false */
}
/* продолжение с обычными операциями index.php */
?>$ php -S localhost:8000 router.php
Пример #5 Поддержка неподдерживаемых типов файлов
Если вам нужно обслуживать статические ресурсы с MIME-типами, неподдерживаемыми веб-сервером CLI, используйте это:
<?php
// router.php
$path = pathinfo($_SERVER["SCRIPT_FILENAME"]);
if ($path["extension"] == "el") {
header("Content-Type: text/x-script.elisp");
readfile($_SERVER["SCRIPT_FILENAME"]);
}
else {
return FALSE;
}
?>$ php -S localhost:8000 router.php
Пример #6 Доступ к веб-серверу CLI с удалённых машин
Вы можете сделать веб-сервер доступным на 8000 порту для всех сетевых интерфейсов:
$ php -S 0.0.0.0:8000
| Имя | По умолчанию | Место изменения | Список изменений |
|---|---|---|---|
| cli_server.color | "0" | PHP_INI_ALL |
Краткое разъяснение конфигурационных директив.
cli_server.color
bool
Включает поддержку цветовых кодов ANSI в выводе терминала встроенного веб-сервера.
В этом разделе описываются достоинства нового механизма сборки мусора (также называемого Garbage Collection или GC), являющегося частью PHP 5.3.
Переменная PHP хранится в контейнере, называемом "zval". Контейнер zval, помимо типа и значения переменной, также содержит два дополнительных элемента. Первый называется "is_ref" и представляет булево значение, указывающее, является переменная частью "набора ссылок" или нет. Благодаря этому элементу PHP знает как отличать обычные переменные от ссылок. Так как PHP содержит пользовательские ссылки, которые можно создать оператором &, контейнер zval также содержит внутренний механизм подсчёта ссылок для оптимизации использования памяти. Эта вторая часть дополнительной информации, называемая "refcount" (счётчик ссылок), содержит количество имён переменных (также называемых символами), которые указывают на данный контейнер zval. Все имена переменных хранятся в таблице имён, отдельной для каждой области видимости переменных. Такая область видимости существует для главного скрипта, а также для каждой функции и метода.
Контейнер zval создаётся при создании новой переменной, которой присваивается константа, например:
Пример #1 Создание нового контейнера zval
<?php
$a = "new string";
?>
В данном примере создаётся новый символ a в текущей области видимости
и новый контейнер переменной с типом string и значением new string.
Бит "is_ref" по умолчанию задаётся равным false, т.к. не создано ни одной пользовательской
ссылки. Значение же "refcount" задаётся равным 1, т.к. только одно имя переменной
указывает на данный контейнер. Обратите внимание, что ссылки (т.е. "is_ref" равно true) с "refcount" равным 1
обрабатываются так, как если бы они не были ссылками (то есть как "is_ref" было бы false). Если у вас установлен » Xdebug, то
вы можете вывести эту информацию, вызвав функцию xdebug_debug_zval().
Пример #2 Вывод информации о zval
<?php
$a = "new string";
xdebug_debug_zval('a');
?>Результат выполнения данного примера:
a: (refcount=1, is_ref=0)='new string'
Присвоение этой переменной другой увеличивает счётчик ссылок.
Пример #3 Увеличение счётчика ссылок zval
<?php
$a = "new string";
$b = $a;
xdebug_debug_zval( 'a' );
?>Результат выполнения данного примера:
a: (refcount=2, is_ref=0)='new string'
Счётчик ссылок здесь равен 2, т.к.
a и b ссылаются на один
и тот же контейнер переменной. PHP достаточно умён, чтобы
не копировать контейнер, пока в этом нет необходимости. Как только
"refcount" станет равным нулю, контейнер уничтожается.
"refcount" уменьшается на единицу при уходе переменной
из области видимости (например, в конце функции) или при
удалении этой переменной (например при вызове unset()).
Пример #4 Уменьшение счётчика ссылок zval
<?php
$a = "new string";
$c = $b = $a;
xdebug_debug_zval( 'a' );
$b = 42;
xdebug_debug_zval( 'a' );
unset( $c );
xdebug_debug_zval( 'a' );
?>Результат выполнения данного примера:
a: (refcount=3, is_ref=0)='new string' a: (refcount=2, is_ref=0)='new string' a: (refcount=1, is_ref=0)='new string'
Если мы сейчас вызовем unset($a);,
то контейнер, включая тип и значение, будет удалён из памяти.
Все несколько усложняется с составными типами данных, такими как массивы (array) и объекты (object). В отличие от скалярных (scalar) значений, массивы и объекты хранят свои свойства в собственных таблицах имён. Это значит, что следующий пример создаст сразу три zval контейнера:
Пример #5 Создание array zval
<?php
$a = array( 'meaning' => 'life', 'number' => 42 );
xdebug_debug_zval( 'a' );
?>Результатом выполнения данного примера будет что-то подобное:
a: (refcount=1, is_ref=0)=array ( 'meaning' => (refcount=1, is_ref=0)='life', 'number' => (refcount=1, is_ref=0)=42 )
Графически:
Результат - три контейнера: a, meaning и number. Похожие правила применяются и для увеличения и уменьшения "refcounts". Ниже мы добавляем ещё один элемент массива и устанавливаем ему значение уже существующего элемента:
Пример #6 Добавление уже существующего элемента в массив
<?php
$a = array( 'meaning' => 'life', 'number' => 42 );
$a['life'] = $a['meaning'];
xdebug_debug_zval( 'a' );
?>Результатом выполнения данного примера будет что-то подобное:
a: (refcount=1, is_ref=0)=array ( 'meaning' => (refcount=2, is_ref=0)='life', 'number' => (refcount=1, is_ref=0)=42, 'life' => (refcount=2, is_ref=0)='life' )
Графически:
Вышеприведённый вывод Xdebug показывает, что и старый и новый элементы массива
сейчас указывают на контейнер, чей "refcount" равен 2.
Хотя показано два контейнера со значением 'life', на самом
деле это один контейнер. Функция xdebug_debug_zval() не выводит информации об этом,
но вы можете проверить это также отобразив указатели памяти.
Удаление элемента из массива происходит точно так же, как и удаление имени переменной из области видимости: уменьшается "refcount" контейнера, на который ссылается элемент массива. Опять же, при достижении "refcount" нуля, контейнер удаляется из памяти. Пример:
Пример #7 Удаление элемента из массива
<?php
$a = array( 'meaning' => 'life', 'number' => 42 );
$a['life'] = $a['meaning'];
unset( $a['meaning'], $a['number'] );
xdebug_debug_zval( 'a' );
?>Результатом выполнения данного примера будет что-то подобное:
a: (refcount=1, is_ref=0)=array ( 'life' => (refcount=1, is_ref=0)='life' )
Ситуация станет интереснее, если добавить массив новым элементом в самого себя. В следующем примере мы также используем оператор присваивания по ссылке, чтобы PHP не создал копию массива.
Пример #8 Добавление массива новым элементом в самого себя
<?php
$a = array( 'one' );
$a[] =& $a;
xdebug_debug_zval( 'a' );
?>Результатом выполнения данного примера будет что-то подобное:
a: (refcount=2, is_ref=1)=array ( 0 => (refcount=1, is_ref=0)='one', 1 => (refcount=2, is_ref=1)=... )
Графически:
Можно увидеть, что переменная с массивом (a), так же как и второй элемент
(1) сейчас указывают на контейнер с "refcount" равным 2.
Символы "..." в выводе означают рекурсию и, в нашем случае,
указывают на оригинальный массив.
Как и ранее, удаление переменной уменьшает счётчик ссылок контейнера на единицу. Если мы применим unset к переменной $a после вышеприведённого примера, то счётчик ссылок контейнера, на который указывают $a и элемент "1", изменится с "2" на "1":
Пример #9 Удаление $a
(refcount=1, is_ref=1)=array ( 0 => (refcount=1, is_ref=0)='one', 1 => (refcount=1, is_ref=1)=... )
Графически:
Хотя во всех областях видимости больше нет имени переменной, ссылающейся на данную структуру, она не может быть очищена, т.к. элемент массива "1" по-прежнему ссылается на этот массив. Т.к. теперь нет никакой возможности пользователю удалить эти данные, то мы получили утечку памяти. К счастью, PHP удалит эти данные при завершении запроса, но до этого момента данные будут занимать ценное место в памяти. Такая ситуация часто бывает, когда реализуются алгоритмы парсинга или другие, где есть дочерние элементы, ссылающиеся на родительские. Ещё чаще такая ситуация случается с объектами, потому что они всегда неявно используются по ссылке.
Эта не проблема, если такое случается раз или два, но если существуют тысячи или даже миллионы таких утечек памяти, то они уже становятся проблемой. Особенно в долгоработающих скриптах, таких как демоны, где запрос не заканчивается никогда, или в больших наборах модульных тестов. Последний случай вызвал проблемы при запуске модульных тестов для компонента Template из библиотеки ez Components. В некоторых случаях может потребоваться свыше 2 Гб памяти, которая не всегда есть на тестовом сервере.
Обычно механизмы подсчёта ссылок в памяти, например, используемый в PHP ранее, не решают проблему утечки памяти из-за циклических ссылок. Начиная с версии 5.3.0, в PHP реализован синхронный механизм из исследования "» Concurrent Cycle Collection in Reference Counted Systems", в котором рассматривается этот вопрос.
Полное описание работы алгоритма выходит за рамки данного раздела, поэтому приведены только основы. Прежде всего мы должны задать несколько основных правил. Если счётчик ссылок увеличивается, то контейнер всё ещё используется и не является мусором. Если счётчик уменьшается до нуля, то zval может быть удалён. Исходя из этих правил утечки памяти с циклическими ссылками могут получиться только при уменьшении счётчика ссылок до ненулевого значения. Затем, в выделенных контейнерах можно найти мусор проверив возможность уменьшения всех счётчиков ссылок на единицу и определив те контейнеры, у которых счётчик станет равным нулю.
Для избежания постоянной проверки на мусор с циклическими ссылками при каждом уменьшении счётчика ссылок, алгоритм добавляет все возможные корни (zval контейнеры) в "корневой буфер" (помечая их как "фиолетовые"). Это также гарантирует попадание любого корня в буфер только один раз. Механизм сборки мусора стартует только тогда, когда наполняется буфер (смотрите шаг A на рисунке выше).
На шаге B алгоритм производит поиск в глубину по всем возможным корням для однократного уменьшения счётчика ссылок на единицу у всех контейнеров (помечая их как "серые"). На шаге C алгоритм снова производит поиск в глубину для проверки счётчиков ссылок. Если он находит счётчик с нулевым значением, то контейнер помечается как "белый" (на рисунке отображено синим). Если же счётчик больше нуля, то происходит поиск в глубину от этого контейнера с обратным увеличением счётчиков на единицу и повторной пометкой как "чёрный" на их контейнерах. На последнем шаге D алгоритм проходит по корневому буферу и удаляет из него корни контейнеров, заодно проверяя какие контейнеры помечены как "белые". Эти контейнеры будут освобождены из памяти.
Теперь, когда вы имеете представление о работе алгоритма, рассмотрим его интеграцию в PHP. По умолчанию сборщик мусора всегда включён. Для изменения этой опции используется параметр zend.enable_gc в php.ini.
Если сборщик мусора включён, алгоритм поиска циклических ссылок выполняется каждый раз,
когда корневой буфер наполняется 10,000 корнями (вы можете поменять это значение,
изменив константу GC_THRESHOLD_DEFAULT в файле
Zend/zend_gc.c в исходном коде PHP и пересобрав PHP).
Если сборщик мусора выключен, алгоритм никогда не будет запущен. Тем не менее,
буфер всегда заполняется корнями.
Если буфер заполнился при выключенном механизме сборки мусора, то другие корни не будут в него записаны. Таким образом, если они окажутся мусором с циклическими ссылками, то никогда не будут очищены и создадут утечку памяти.
Причиной постоянной записи корней в буфер даже при выключенном механизме сборки мусора является то, что это намного быстрее, чем постоянно проверять включён ли механизм сборки мусора или нет. Однако, сама сборка мусора и алгоритм её анализа могут занимать значительное время.
Помимо изменения параметра zend.enable_gc, механизм сборки мусора также можно запустить и остановить вызвав функции gc_enable() и gc_disable() соответственно. Вызов этих функций имеет тот же эффект, что и включение/выключение механизма с помощью настроек конфигурации. Кроме того, можно запустить сборку мусора, даже если корневой буфер ещё не заполнен. Для этого вы можете вызвать функцию gc_collect_cycles(), которая также возвращает количество циклических ссылок собранных алгоритмом.
Причиной включения и выключения механизма сборки, а также его ручного запуска, может стать то, что некоторые части вашего приложения могут быть требовательными ко времени. В этих случаях вы, возможно, не захотите постороннего вмешательства сборщика мусора. Разумеется, выключая сборщик мусора в определённых местах вашего приложения вы рискуете получить утечку памяти, т.к. потенциально некоторые корни могут не поместиться в ограниченный корневой буфер. Более целесообразно будет вызвать gc_collect_cycles() непосредственно перед вызовом gc_disable() для освобождения памяти и уже записанных корней в буфере. Это очистит буфер и позволит использовать больше места для хранения корней, пока механизм будет выключен.
В предыдущем разделе нами уже говорилось, что простой сбор корней меньше влияет на производительность. Хотя запись корней в буфер по сравнению с полным отсутствием таковой в PHP 5.2 работает медленней, другие изменения в работе PHP 5.3 сделали эту потерю производительности незаметной.
Есть две основные области влияющие на производительность: уменьшение размера используемой памяти и замедление работы при сборке мусора. Рассмотрим их.
Прежде всего, основной причиной реализации механизма сборки мусора является уменьшение размера используемой памяти с помощью чистки циклических ссылок, которая происходит при достижении соответствующих условий. В реализации PHP это происходит как только заполнится корневой буфер или при вызове функции gc_collect_cycles(). На графике ниже приведено использование памяти скрипта, запущенного в PHP 5.2 и PHP 5.3, без учёта памяти, используемой самим PHP при запуске.
Пример #1 Пример использования памяти
<?php
class Foo
{
public $var = '3.14159265359';
}
$baseMemory = memory_get_usage();
for ( $i = 0; $i <= 100000; $i++ )
{
$a = new Foo;
$a->self = $a;
if ( $i % 500 === 0 )
{
echo sprintf( '%8d: ', $i ), memory_get_usage() - $baseMemory, "\n";
}
}
?>
В этом очень академическом примере мы создаём объект, свойство a которого задаётся ссылкой на сам объект. Когда в скрипте в следующей итерации цикла переопределяется переменная $a, то происходит типичная утечка памяти. В данном случае пропадают два контейнера zval (контейнер объекта и контейнер свойства объекта), но определяется только один корень - удалённая переменная. Как только пройдут 10 000 итераций (максимально в корневом буфере будет 10 000 корней), то запустится механизм сборки мусора и память, занимаемая этими корнями, будет освобождена. Этот процесс хорошо виден на графике использования памяти для PHP 5.3: после каждых 10 000 итераций график проседает. Сам по себе механизм в данном примере совершает не так много работы, потому что структура утечек слишком проста. Из графика видно, что максимальное использование памяти в PHP 5.3 составило около 9 Мб, тогда как в PHP 5.2 оно продолжает возрастать.
Второй областью, где сборка мусора влияет на производительность, является потеря времени, когда сборщик мусора освобождает память. Чтобы понять степень этого влияния, мы немного изменим предыдущий скрипт, добавив большее число итераций и промежуточных переменных. Изменённый скрипт:
Пример #2 Влияние на производительность
<?php
class Foo
{
public $var = '3.1415962654';
}
for ( $i = 0; $i <= 1000000; $i++ )
{
$a = new Foo;
$a->self = $a;
}
echo memory_get_peak_usage(), "\n";
?>Мы запустим скрипт два раза: с включённой опцией zend.enable_gc и без неё.
Пример #3 Запуск скрипта
time php -dzend.enable_gc=0 -dmemory_limit=-1 -n example2.php # и time php -dzend.enable_gc=1 -dmemory_limit=-1 -n example2.php
На тестовой машине первая команда примерно выполняется 10.7 секунд, а вторая примерно 11.4 секунды. Это примерно на 7% медленнее. Однако, максимальное использование памяти скриптом уменьшилось на 98% с 931 Мб до 10 Мб. Этот тест не очень научный, но он действительно демонстрирует преимущество по использованию памяти, обеспечиваемое сборщиком мусора. Также хорошо то, что замедление для этого скрипта всегда примерно 7%, тогда как экономия памяти увеличивается все больше и больше при нахождении нового мусора.
Можно получить немного больше информации о том, как механизм сборки
мусора выполняется в PHP. Но для этого вам необходимо пересобрать PHP
для включения теста производительности и кода для дополнительного сбора данных. Необходимо
установить переменную окружения CFLAGS в значение
-DGC_BENCH=1 до выполнения команды ./configure
с вашими параметрами. Следующие команды должны сработать:
Пример #4 Сборка PHP для включения теста производительности GC
export CFLAGS=-DGC_BENCH=1 ./config.nice make clean make
При запуске вышеприведённого примера с обновлённым PHP, можно увидеть следующую информацию по завершении работы скрипта:
Пример #5 Статистика GC
GC Statistics
-------------
Runs: 110
Collected: 2072204
Root buffer length: 0
Root buffer peak: 10000
Possible Remove from Marked
Root Buffered buffer grey
-------- -------- ----------- ------
ZVAL 7175487 1491291 1241690 3611871
ZOBJ 28506264 1527980 677581 1025731
Наиболее полезная статистика отображена в первом блоке. Можно увидеть, что механизм сборки мусора был запущен 110 раз, и суммарно было освобождено свыше 2 миллионов записей в памяти. Если сборка мусора была запущена хотя бы раз, то максимальное число корней в буфере всегда будет равно 10 000.
В целом, сборщик мусора в PHP вызовет ощутимые замедления только во время непосредственной работы механизма сборки циклических ссылок, тогда как в обычных (небольших) скриптах не должно быть никакого падения производительности.
Однако в тех случаях, когда механизм сборки должен срабатывать и в обычных скриптах, снижение используемой памяти позволяет одновременно работать на сервере большему их количеству.
Преимущества наиболее очевидны для долгоработающих скриптов, таких как большие наборы тестов или демоны. Новый механизм также должен снизить утечки памяти для приложений » PHP-GTK, которые выполняются обычно дольше, чем веб-скрипты.
DTrace - это всегда доступный, практически не потребляющий ресурсов фреймворк трассировки. Он доступен на множестве платформ, включая Solaris, macOS, Oracle Linux и BSD. DTrace может отслеживать поведение операционной системы и запущенных пользовательских приложений. Он может показывать значения параметров и используется для вывода статистики производительности. Зонды отслеживаются пользовательскими скриптами, написанными на скриптовом языке DTrace D. Это позволяет эффективно анализировать срезы данных.
Зонды PHP, которые не отслеживаются пользовательскими DTrace D скриптами, не содержат никакого дополнительного кода и, следовательно, во время нормальной работы приложения, никакой деградации производительности не происходит. Отслеживаемые зонды, в свою очередь, дают очень низкую просадку производительности, что позволяет использовать их в промышленных средах.
PHP включает в себя зонды "Статически определённой
трассировки уровня пользователя" (User-level Statically
Defined Tracing, или USDT), которые работают во время
исполнения. К примеру, когда D-скрипт отслеживает зонд
function-entry, то каждый раз при вызове
функции, этот зонд запускает соответствующее действие
D-скрипта. Это действие, например, печатает аргументы
зонда, такие как расположение этой функции в PHP-скрипте.
Или же это может быть агрегация данных, таких как
количество запусков каждой из функции.
Здесь описываются только зонды PHP USDT. Для получения информации о том, как следить за произвольными функциями и отслеживать поведение операционной системы, читайте соответствующую литературу, специфичную для каждой операционной системы и внешнюю полноценную документацию DTrace. Обратите внимание, что различные реализации DTrace могут отличаться набором доступного функционала.
Статические зонды DTrace в PHP, также могут быть использованы с SystemTap в некоторых дистрибутивах Linux.
PHP может быть сконфигурирован со статическими зондами DTrace на платформах поддерживающих динамическую трассировку DTrace.
Обратитесь к документации вашей платформы, чтобы включить поддержку DTrace в вашей операционной системе. К примеру, в Oracle Linux необходимо загрузить ядро UEK3 и сделать следующее:
# modprobe fasttrap
# chmod 666 /dev/dtrace/helper
Вместо chmod, вы можете использовать
пакет правил ACL для ограничения доступа для конкретного
пользователя.
Сборка PHP с ключом --enable-dtrace:
# ./configure --enable-dtrace ...
# make
# make installЭто включит статические зонды в ядре PHP. Любой модуль PHP, предоставляющий собственные зонды, должен быть собран отдельно как разделяемый модуль.
| Имя зонда | Описание зонда | Аргументы зонда |
|---|---|---|
request-startup |
Срабатывает при начале запроса. | char *file, char *request_uri, char *request_method |
request-shutdown |
Срабатывает при окончании запроса. | char *file, char *request_uri, char *request_method |
compile-file-entry |
Срабатывает, когда начинается компиляция скрипта. | char *compile_file, char *compile_file_translated |
compile-file-return |
Срабатывает, когда заканчивается компиляция скрипта. | char *compile_file, char *compile_file_translated |
execute-entry |
Срабатывает, когда запускается массив байт-кода. К примеру, когда вызываются функции, возобновляется работа генератора или происходит include. | char *request_file, int lineno |
execute-return |
Срабатывает, после отработки массива байт-кода. | char *request_file, int lineno |
function-entry |
Срабатывает, когда движок PHP начинает запуск функции или метода. | char *function_name, char *request_file, int lineno, char *classname, char *scope |
function-return |
Срабатывает, когда движок PHP возвращается из функции или метода. | char *function_name, char *request_file, int lineno, char *classname, char *scope |
exception-thrown |
Срабатывает, когда выброшено исключение. | char *classname |
exception-caught |
Срабатывает, когда исключение поймано. | char *classname |
error |
Срабатывает если произошла ошибка, вне зависимости от уровня error_reporting. | char *errormsg, char *request_file, int lineno |
Модули PHP могут содержать дополнительные зонды.
Для получения списка зондов, запустите процесс PHP и выполните:
# dtrace -l
Вывод будет примерно такой:
ID PROVIDER MODULE FUNCTION NAME
[ . . . ]
4 php15271 php dtrace_compile_file compile-file-entry
5 php15271 php dtrace_compile_file compile-file-return
6 php15271 php zend_error error
7 php15271 php ZEND_CATCH_SPEC_CONST_CV_HANDLER exception-caught
8 php15271 php zend_throw_exception_internal exception-thrown
9 php15271 php dtrace_execute_ex execute-entry
10 php15271 php dtrace_execute_internal execute-entry
11 php15271 php dtrace_execute_ex execute-return
12 php15271 php dtrace_execute_internal execute-return
13 php15271 php dtrace_execute_ex function-entry
14 php15271 php dtrace_execute_ex function-return
15 php15271 php php_request_shutdown request-shutdown
16 php15271 php php_request_startup request-startup
Колонка Provider содержит надпись php и
pid текущего запущенного процесса PHP.
Если запущен веб-сервер Apache, имя модуля может быть, например, libphp5.so, и может быть множество блоков списка, по одному на каждый процесс Apache.
Колонка Function ссылается на имя внутренней С-функции PHP, реализующей соответствующий зонд.
Если PHP не запущен, то связанных с ним зондов в списке не будет.
Этот пример показывает базовые возможности скриптового языка DTrace D.
Пример #1 all_probes.d - трассировка всех статических зондов PHP с помощью DTrace
#!/usr/sbin/dtrace -Zs
#pragma D option quiet
php*:::compile-file-entry
{
printf("PHP compile-file-entry\n");
printf(" compile_file %s\n", copyinstr(arg0));
printf(" compile_file_translated %s\n", copyinstr(arg1));
}
php*:::compile-file-return
{
printf("PHP compile-file-return\n");
printf(" compile_file %s\n", copyinstr(arg0));
printf(" compile_file_translated %s\n", copyinstr(arg1));
}
php*:::error
{
printf("PHP error\n");
printf(" errormsg %s\n", copyinstr(arg0));
printf(" request_file %s\n", copyinstr(arg1));
printf(" lineno %d\n", (int)arg2);
}
php*:::exception-caught
{
printf("PHP exception-caught\n");
printf(" classname %s\n", copyinstr(arg0));
}
php*:::exception-thrown
{
printf("PHP exception-thrown\n");
printf(" classname %s\n", copyinstr(arg0));
}
php*:::execute-entry
{
printf("PHP execute-entry\n");
printf(" request_file %s\n", copyinstr(arg0));
printf(" lineno %d\n", (int)arg1);
}
php*:::execute-return
{
printf("PHP execute-return\n");
printf(" request_file %s\n", copyinstr(arg0));
printf(" lineno %d\n", (int)arg1);
}
php*:::function-entry
{
printf("PHP function-entry\n");
printf(" function_name %s\n", copyinstr(arg0));
printf(" request_file %s\n", copyinstr(arg1));
printf(" lineno %d\n", (int)arg2);
printf(" classname %s\n", copyinstr(arg3));
printf(" scope %s\n", copyinstr(arg4));
}
php*:::function-return
{
printf("PHP function-return\n");
printf(" function_name %s\n", copyinstr(arg0));
printf(" request_file %s\n", copyinstr(arg1));
printf(" lineno %d\n", (int)arg2);
printf(" classname %s\n", copyinstr(arg3));
printf(" scope %s\n", copyinstr(arg4));
}
php*:::request-shutdown
{
printf("PHP request-shutdown\n");
printf(" file %s\n", copyinstr(arg0));
printf(" request_uri %s\n", copyinstr(arg1));
printf(" request_method %s\n", copyinstr(arg2));
}
php*:::request-startup
{
printf("PHP request-startup\n");
printf(" file %s\n", copyinstr(arg0));
printf(" request_uri %s\n", copyinstr(arg1));
printf(" request_method %s\n", copyinstr(arg2));
}
Этот скрипт использует опцию -Z для
dtrace, позволяя ему работать даже
если ни одного процесса PHP не запущено. Если не использовать
эту опцию, то скрипт сразу же завершит выполнения, поскольку
не увидит ни одного зонда, который ему надо отслеживать.
Скрипт отслеживает все статические зонды PHP на всем протяжении работы PHP-скрипта. Запускаем D-скрипт:
# ./all_probes.d
Запустите скрипт или приложение PHP. Отслеживающий D-скрипт будет выводить аргументы всех сработавших зондов.
Когда вы увидели все, что хотели, прервать работу скрипта можно комбинацией CTRL+C.
На многопроцессорных машинах, порядок зондов может быть не последовательным, в зависимости от того, на каких процессорах работают зонды и как мигрируют потоки между процессорами. Отображение временных меток позволит избежать конфузов. К примеру:
php*:::function-entry
{
printf("%lld: PHP function-entry ", walltimestamp);
[ . . .]
}
В некоторых дистрибутивах Linux, можно использовать утилиту трассировки SystemTap для отслеживания статических зондов DTrace. Данный вариант доступен в PHP 5.4.20 и PHP 5.5.
Установите разработческий пакет SystemTap SDT:
# yum install systemtap-sdt-devel
Установите PHP с DTrace:
# ./configure --enable-dtrace ... # make
Статические зонды PHP можно посмотреть используя stap:
# stap -l 'process.provider("php").mark("*")' -c 'sapi/cli/php -i'
Примерный вывод:
process("sapi/cli/php").provider("php").mark("compile__file__entry")
process("sapi/cli/php").provider("php").mark("compile__file__return")
process("sapi/cli/php").provider("php").mark("error")
process("sapi/cli/php").provider("php").mark("exception__caught")
process("sapi/cli/php").provider("php").mark("exception__thrown")
process("sapi/cli/php").provider("php").mark("execute__entry")
process("sapi/cli/php").provider("php").mark("execute__return")
process("sapi/cli/php").provider("php").mark("function__entry")
process("sapi/cli/php").provider("php").mark("function__return")
process("sapi/cli/php").provider("php").mark("request__shutdown")
process("sapi/cli/php").provider("php").mark("request__startup")
Пример #1 all_probes.stp - трассировка всех статических зондов PHP
probe process("sapi/cli/php").provider("php").mark("compile__file__entry") {
printf("Probe compile__file__entry\n");
printf(" compile_file %s\n", user_string($arg1));
printf(" compile_file_translated %s\n", user_string($arg2));
}
probe process("sapi/cli/php").provider("php").mark("compile__file__return") {
printf("Probe compile__file__return\n");
printf(" compile_file %s\n", user_string($arg1));
printf(" compile_file_translated %s\n", user_string($arg2));
}
probe process("sapi/cli/php").provider("php").mark("error") {
printf("Probe error\n");
printf(" errormsg %s\n", user_string($arg1));
printf(" request_file %s\n", user_string($arg2));
printf(" lineno %d\n", $arg3);
}
probe process("sapi/cli/php").provider("php").mark("exception__caught") {
printf("Probe exception__caught\n");
printf(" classname %s\n", user_string($arg1));
}
probe process("sapi/cli/php").provider("php").mark("exception__thrown") {
printf("Probe exception__thrown\n");
printf(" classname %s\n", user_string($arg1));
}
probe process("sapi/cli/php").provider("php").mark("execute__entry") {
printf("Probe execute__entry\n");
printf(" request_file %s\n", user_string($arg1));
printf(" lineno %d\n", $arg2);
}
probe process("sapi/cli/php").provider("php").mark("execute__return") {
printf("Probe execute__return\n");
printf(" request_file %s\n", user_string($arg1));
printf(" lineno %d\n", $arg2);
}
probe process("sapi/cli/php").provider("php").mark("function__entry") {
printf("Probe function__entry\n");
printf(" function_name %s\n", user_string($arg1));
printf(" request_file %s\n", user_string($arg2));
printf(" lineno %d\n", $arg3);
printf(" classname %s\n", user_string($arg4));
printf(" scope %s\n", user_string($arg5));
}
probe process("sapi/cli/php").provider("php").mark("function__return") {
printf("Probe function__return: %s\n", user_string($arg1));
printf(" function_name %s\n", user_string($arg1));
printf(" request_file %s\n", user_string($arg2));
printf(" lineno %d\n", $arg3);
printf(" classname %s\n", user_string($arg4));
printf(" scope %s\n", user_string($arg5));
}
probe process("sapi/cli/php").provider("php").mark("request__shutdown") {
printf("Probe request__shutdown\n");
printf(" file %s\n", user_string($arg1));
printf(" request_uri %s\n", user_string($arg2));
printf(" request_method %s\n", user_string($arg3));
}
probe process("sapi/cli/php").provider("php").mark("request__startup") {
printf("Probe request__startup\n");
printf(" file %s\n", user_string($arg1));
printf(" request_uri %s\n", user_string($arg2));
printf(" request_method %s\n", user_string($arg3));
}
Приведённый выше скрипт будет выводить данные статических зондов PHP на всем протяжении работы PHP-скрипта:
# stap -c 'sapi/cli/php test.php' all_probes.stp
Смотрите также Список/классификация модулей.
APCu - это хранилище "ключ-значение" в памяти для PHP. Ключи являются строками (string), а значения могут быть любыми переменными PHP. APCu поддерживает только кеширование переменных в пользовательском пространстве.
В Windows кеш APCu относится к каждому процессу, поэтому при использовании SAPI, основанного на процессах (а не на потоках), он не будет разделяться между различными процессами.
APCu - это APC без кеширования опкода.
Первая версия APCu имеет номер 4.0.0, так как она была клонирована из основной кодовой ветви APC. Поддержка PHP 7 доступна, начиная с APCu 5.0.0. Поддержка PHP 8 доступна, начиная с APCu 5.1.19.
Для сборки этого модуля не требуются внешние библиотеки.
Информация по установке этого модуля PECL может быть найдена в главе руководства Установка PECL модулей. Дополнительная информация, такая как новые версии, скачивание, исходные файлы, информация о разработчике и CHANGELOG, может быть найдена здесь: » https://pecl.php.net/package/apcu.
В PHP 7 есть отдельный модуль (» apcu-bc) для обратной совместимости с APC.
В режиме обратной совместимости, APCu регистрирует применимые функции APC с помощью специальных, обратно совместимых, прототипов.
Если функция APC принимает параметр cache_type, он просто
игнорируется и опускается в прототипе функции APCu.
Начиная с PHP 8.0.0, apcu-bc больше не поддерживается.
Замечание: В Windows, APCu необходимо, чтобы был задана временная директория и веб-сервер имел право туда писать. Модуль проверяет переменные окружающей среды в таком порядке: TMP, TEMP, USERPROFILE. Если ни одна из них не задана, то модуль пытается работать с каталогом WINDOWS.
Замечание: Крайне подробная, в техническом плане, документация о реализации этого модуля доступна в » предоставленном разработчиком файле TECHNOTES.
Исходные коды APCu можно найти » тут.
Поведение этих функций зависит от установок в php.ini.
Хотя настроек APCu по умолчанию вполне достаточно для большинства задач, но для серьёзных проектов необходимо внимательно изучить следующие настройки.
При настройке APCu необходимо определиться, сколько памяти
предоставить в распоряжение APCu.
Директива ini-файла, ответственная за эту настройку - apc.shm_size.
Внимательно прочитайте нижеследующий раздел.
После запуска сервера скрипт apc.php, который поставляется вместе с модулем,
следует скопировать в docroot и просмотреть в браузере, поскольку он предоставляет
подробный анализ внутренней работы APCu.
Если в PHP включён модуль GD, он даже отобразит некоторые интересные графики.
Если APCu работает, число Cache full count (слева) покажет,
сколько раз кеш достигал максимальной ёмкости и был вынужден вытеснять записи,
чтобы освободить память.
Во время вытеснения, если было указано значение apc.ttl,
APCu сначала попытается удалить записи с истёкшим сроком действия, т.е. записи,
TTL которых либо истёк, либо записи, у которых TTL не установлен
и к которым не было доступа в течение последних apc.ttl секунд.
Если значение apc.ttl не было установлена или удаление истёкших записей
не освободило достаточно места, APCu очистит весь кеш.
В хорошо настроенном кеше количество вытеснений должно быть минимальным. Если кеш постоянно заполняется и, следовательно, принудительно освобождается, то возникающая в результате этого возня негативно скажется на производительности скрипта. Самый простой способ минимизировать это число - выделить больше памяти для APCu.
Если APCu собран с поддержкой mmap (Memory Mapping), он будет использовать
всего один сегмент памяти, если же наоборот, APC собран с поддержкой SHM (SysV Shared
Memory), он будет использовать несколько сегментов. MMAP не имеет максимального
ограничения, в отличие от SHM, который ограничивается
/proc/sys/kernel/shmmax. Обычно рекомендуется использовать MMAP,
потому что он гораздо быстрее выделяет память при перезагрузке веб-сервера, что
сказывается на скорости запуска сервера.
| Имя | По умолчанию | Место изменения | Список изменений |
|---|---|---|---|
| apc.enabled | "1" | PHP_INI_SYSTEM | |
| apc.shm_segments | "1" | PHP_INI_SYSTEM | |
| apc.shm_size | "32M" | PHP_INI_SYSTEM | |
| apc.entries_hint | "4096" | PHP_INI_SYSTEM | |
| apc.ttl | "0" | PHP_INI_SYSTEM | |
| apc.gc_ttl | "3600" | PHP_INI_SYSTEM | |
| apc.mmap_file_mask | NULL | PHP_INI_SYSTEM | |
| apc.slam_defense | "1" | PHP_INI_SYSTEM | |
| apc.enable_cli | "0" | PHP_INI_SYSTEM | |
| apc.use_request_time | "0" | PHP_INI_ALL | До APCu 5.1.19 значение по умолчанию было "1". |
| apc.serializer | "php" | PHP_INI_SYSTEM | До APCu 5.1.19 значение по умолчанию было "default". |
| apc.coredump_unmap | "0" | PHP_INI_SYSTEM | |
| apc.preload_path | NULL | PHP_INI_SYSTEM |
Краткое разъяснение конфигурационных директив.
apc.enabled
bool
Если установить apc.enabled равным 0, то APCu не будет запущен.
Это полезно, когда APCu статически включён в PHP и нет других вариантов, для запрещения
его использования. Если APC собран как DSO, можно просто закомментировать строку
extension в php.ini.
apc.shm_segments
int
Количество сегментов разделяемой памяти выделенной под кеш.
Если APC использовал всю доступную разделяемую память, а
apc.shm_size таким большим, как позволяет система, увеличение
этого параметра может помочь.
apc.shm_size
string
Размер сегмента разделяемой памяти, заданный в короткой нотации (смотрите этот FAQ). По умолчанию, некоторые системы (включая большинство вариантов BSD) ограничивают это значение крайне малым значением.
apc.entries_hint
int
Это подсказка о количестве уникальных пользовательских переменных, которые надо кешировать. Установите равным нулю или вообще не указывайте, если не уверены.
apc.ttl
int
Записи кеша без явного указания TTL считаются истёкшими,
если к ним не обращались в течение этого количества секунд.
По сути, это позволяет удалять такие записи оппортунистически
во время добавления кеша или перед полным удалением.
Обратите внимание, что поскольку удаление происходит по обстоятельствам,
записи могут быть доступны для чтения, даже если их срок жизни
превышает apc.ttl секунд.
Параметр не влияет на записи кеша, для которых явно задан TTL.
apc.gc_ttl
int
Количество секунд, которые запись может находиться в списке сборщика мусора. Это значение обеспечивает безотказность в случае падения сервера в момент исполнения закешированного файла. Если исполняемый файл был изменён, память, выделенная под кеширование его старой версии, не будет возвращена до истечения этого времени. Установка в ноль отключает этот функционал.
apc.mmap_file_mask
string
Если собран с поддержкой MMAP, с помощью опции --enable-mmap,
этот параметр должен содержать файловую маску типа mktemp-style для
передачи в модуль MMAP, чтобы определить, будет ли MMAP использовать
файловую систему или разделяемую память.
Для файловой системы задайте опцию как /tmp/apc.XXXXXX
(ровно 6 X).
Для использования shm_open/mmap в стиле POSIX, добавьте .shm
в любом месте маски, например /apc.shm.XXXXXX
Вы также можете установить его как /dev/zero для использования
интерфейса ядра /dev/zero для анонимной памяти mmap.
Если не задано, то будет принудительно использоваться анонимный mmap.
apc.slam_defense
int
На очень загруженных серверах, когда вы запускаете веб-сервер,
сразу множество процессов будут пытаться закешировать один и тот же
файл одновременно. Этой опцией задаётся вероятность, в процентах,
того, что попытка одного конкретного процесса закешировать данные
будет отклонена. Например, если apc.slam_defense
установить равной 75, то это означает, что
вероятность закешировать файл, которого в кеше нет,
будет равна 25% и вероятность того, что в кешировании будет
отказано равна 75%. Для запрета данного функционала установите
этот параметр равным 0.
apc.enable_cli
int
Больше для тестирования и отладки. Эта настройка включает APCu для CLI версии PHP. При обычной работе, запускать APCu, который будет создавать, наполнять и уничтожать кеш при каждом запуске сценария в консоли, будет далеко не лучшей идеей. Но в целях тестирования и отладки, можно легко включить APCu для CLI.
apc.serializer
string
Указывает APC использовать сторонний сериализатор.
apc.coredump_unmap
bool
Разрешает APC перехватывать сигналы, такие как SIGSEGV, который записывает coredump, когда подан. Когда эти сигналы будут получены, APC попытается освободить всю разделяемую память, чтобы не включать её в coredump. Эта настройка может увеличить стабильность системы, когда критический сигнал был получен, а APC сконфигурирован на использование большого объёма памяти.
Эта возможность потенциально опасна. Освобождение сегментов разделяемой памяти при получении критического сигнала может привести к непредсказуемому поведению.
Замечание:
Хотя некоторые ядра предоставляют возможность игнорировать некоторые сегменты разделяемой памяти при записи core-файла, эти реализации могут также игнорировать важные сегменты памяти, такие как Apache scoreboard.
apc.preload_path
string
Опционально. Задаёт путь, который используется APC для загрузки кешированных данных во время запуска.
apc.use_request_time
bool
Использовать время старта запроса SAPI для TTL.
Данный модуль не определяет каких-либо типов ресурсов.
Перечисленные ниже константы определены данным модулем и могут быть доступны только в том случае, если PHP был собран с поддержкой этого модуля или же в том случае, если данный модуль был динамически загружен во время выполнения.
APC_ITER_ALL
(int)
APC_ITER_ATIME
(int)
APC_ITER_CTIME
(int)
APC_ITER_DEVICE
(int)
APC_ITER_DTIME
(int)
APC_ITER_FILENAME
(int)
APC_ITER_INODE
(int)
APC_ITER_KEY
(int)
APC_ITER_MD5
(int)
APC_ITER_MEM_SIZE
(int)
APC_ITER_MTIME
(int)
APC_ITER_NONE
(int)
APC_ITER_NUM_HITS
(int)
APC_ITER_REFCOUNT
(int)
APC_ITER_TTL
(int)
APC_ITER_TYPE
(int)
APC_ITER_VALUE
(int)
APC_LIST_ACTIVE
(int)
APC_LIST_DELETED
(int)
(PECL apcu >= 4.0.0)
apcu_add — Добавить переменную в кеш
Добавляет переменную в кеш, если её там ещё нет.
Замечание: В отличие от многих других механизмов PHP, переменные, сохранённые apcu_add(), сохраняются между запросами, пока их не удалят из кеша.
key
Имя, под которым будет сохранена переменная. Значение key
является уникальным для кеша, так что попытка использовать
apcu_add() для сохранения переменной с ключом, который уже
существует, не перезапишет запись, а вернёт false. (Это единственное различие между
apcu_add() и apcu_store().)
varПеременная для сохранения
ttl
Время жизни; переменная var будет храниться в течение
ttl секунд. Как только ttl секунд
пройдут, переменная будет удалена из кеша (при следующем запросе). Если параметр
ttl не задан (или ttl задан как
0), значение будет храниться пока не будет удалено явно, либо
по технической причине (очистка кеша, перезапуск и т.д.)
valuesИмена в ключах, переменные в значениях.
Возвращает true, если удалось занести значение в кеш, в противном случае возвращает false.
Второй тип синтаксиса возвращает массив с ключами, по которым произошла ошибка.
Пример #1 Пример использования apcu_add()
<?php
$bar = 'BAR';
apcu_add('foo', $bar);
var_dump(apcu_fetch('foo'));
echo "\n";
$bar = 'NEVER GETS SET';
apcu_add('foo', $bar);
var_dump(apcu_fetch('foo'));
echo "\n";
?>Результат выполнения данного примера:
string(3) "BAR" string(3) "BAR"
(PECL apcu >= 4.0.0)
apcu_cache_info — Извлекает закешированную информацию из хранилища APCu
$limited = false): array|falseИзвлекает закешированную информацию из хранилища APCu.
limited
Если limited задан как true, возвращаемое
значение не будет содержать индивидуальный список записей кеша.
Это полезно при попытках оптимизировать вызовы для получения статистики.
Массив кешированных данных (и метаданные) или false в случае возникновения ошибки
Замечание: apcu_cache_info() вызывает предупреждение, если невозможно получить данные кеша APC. Обычно это происходит, если APC не разрешён.
| Версия | Описание |
|---|---|
| PECL apcu 3.0.11 |
Добавлен параметр limited.
|
| PECL apcu 3.0.16 |
Добавлена опция "filehits" для параметра
cache_type.
|
Пример #1 Пример использования apcu_cache_info()
<?php
print_r(apcu_cache_info());
?>Результатом выполнения данного примера будет что-то подобное:
Array
(
[num_slots] => 2000
[ttl] => 0
[num_hits] => 9
[num_misses] => 3
[start_time] => 1123958803
[cache_list] => Array
(
[0] => Array
(
[filename] => /path/to/apcu_test.php
[device] => 29954
[inode] => 1130511
[type] => file
[num_hits] => 1
[mtime] => 1123960686
[creation_time] => 1123960696
[deletion_time] => 0
[access_time] => 1123962864
[ref_count] => 1
[mem_size] => 677
)
[1] => Array (...итерирует для каждого закешированного файла)
)
(PECL apcu >= 4.0.0)
apcu_cas — Заменяет старое значение на новое
$key, int $old, int $new): bool
apcu_cas() заменяет значение уже существующего целочисленного
значения, если оно равно old на
new.
keyКлюч изменяемого значения.
oldСтарое значение (которое в данный момент хранится в кеше).
newНовое значение.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Пример использования apcu_cas()
<?php
apcu_store('foobar', 2);
echo '$foobar = 2', PHP_EOL;
echo '$foobar == 1 ? 2 : 1 = ', (apcu_cas('foobar', 1, 2) ? 'ok' : 'fail'), PHP_EOL;
echo '$foobar == 2 ? 1 : 2 = ', (apcu_cas('foobar', 2, 1) ? 'ok' : 'fail'), PHP_EOL;
echo '$foobar = ', apcu_fetch('foobar'), PHP_EOL;
echo '$f__bar == 1 ? 2 : 1 = ', (apcu_cas('f__bar', 1, 2) ? 'ok' : 'fail'), PHP_EOL;
apcu_store('perfection', 'xyz');
echo '$perfection == 2 ? 1 : 2 = ', (apcu_cas('perfection', 2, 1) ? 'ok' : 'epic fail'), PHP_EOL;
echo '$foobar = ', apcu_fetch('foobar'), PHP_EOL;
?>Результатом выполнения данного примера будет что-то подобное:
$foobar = 2 $foobar == 1 ? 2 : 1 = fail $foobar == 2 ? 1 : 2 = ok $foobar = 1 $f__bar == 1 ? 2 : 1 = fail $perfection == 2 ? 1 : 2 = epic fail $foobar = 1
(PECL apcu >= 4.0.0)
apcu_clear_cache — Очистить кеш APCu
Очищает кеш APCu.
У этой функции нет параметров.
Всегда возвращает true
(PECL apcu >= 4.0.0)
apcu_dec — Уменьшить сохранённое число
$key,$step = 1,&$success = ?,$ttl = 0Уменьшает сохранённое число.
keyКлюч значения, которое надо уменьшить.
stepВеличина, на которую необходимо уменьшить.
success
Необязательный параметр. Если задан, то в него будет
записано логическое значение true или false в зависимости от успешности
операции уменьшения.
ttlTTL(время жизни), используемое если операция вставляет новое значение (а не уменьшает существующее).
Возвращает текущее значение key в случае успешного выполнения или false в случае возникновения ошибки
Пример #1 Пример использования apcu_dec()
<?php
echo "Сделаем что-то без ошибки", PHP_EOL;
apcu_store('anumber', 42);
echo apcu_fetch('anumber'), PHP_EOL;
echo apcu_dec('anumber'), PHP_EOL;
echo apcu_dec('anumber', 10), PHP_EOL;
echo apcu_dec('anumber', 10, $success), PHP_EOL;
var_dump($success);
echo "А теперь с ошибкой", PHP_EOL, PHP_EOL;
apcu_store('astring', 'foo');
$ret = apcu_dec('astring', 1, $fail);
var_dump($ret);
var_dump($fail);
?>Результатом выполнения данного примера будет что-то подобное:
Сделаем что-то без ошибки 42 41 31 21 bool(true) А теперь с ошибкой bool(false) bool(false)
(PECL apcu >= 4.0.0)
apcu_delete — Удаляет сохранённое значение из кеша
key
key можно задать как строку, для удаления одного
значения, либо как массив строк, для удаления нескольких значений, либо
как объект APCUIterator.
Если key является массивом (array), возвращается индексированный массив (array) ключей.
В противном случае возвращается true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Пример использования apcu_delete()
<?php
$bar = 'BAR';
apcu_store('foo', $bar);
//Удаляем одну запись.
apcu_delete('foo');
// Удаляем несколько записей.
apcu_delete(['foo', 'bar', 'baz']);
// Используем итератор с регулярным выражением.
apcu_delete(new APCUIterator('#^myprefix_#'));
?>
(PECL apcu >= 4.0.3)
apcu_enabled — Возможно ли использовать APCu в текущем окружении
Определяет, возможно ли использовать APCu в текущем окружении.
У этой функции нет параметров.
Возвращает true или false в зависимости от возможности использовать APCu.
(PECL apcu >= 5.1.0)
apcu_entry — Автоматическое извлечение или создание записи в кеше
Автоматически пытается найти запись с заданным ключом key.
Если не может, то вызывается генератор generator и ему
передаётся ключ key как единственный аргумент.
Сгенерированное значение заносится в кеш с указанным ttl и
возвращается.
Замечание: Когда контроль передаётся apcu_entry(), производится эксклюзивная блокировка кеша, которая снимается после завершения работы apcu_entry(): это приводит к тому, что тело генератора
generatorпомещается в критическую секцию, запрещая двум процессам запустить выполнение одинакового кода конкурентно. К тому же, это приводит к запрету конкурентного запуска любых других функций APCu, так как они будут выставлять ту же блокировку.
Единственная функция APCu, которую можно безопасно вызывать в генераторе
generator - это apcu_entry().
keyИдентификатор записи
generator
Callback-функция, принимающая один параметр key
и возвращающая значение для кеширования.
ttl
Время жизни; переменная var будет храниться в течение
ttl секунд. Как только ttl секунд
пройдут, переменная будет удалена из кеша (при следующем запросе). Если параметр
ttl не задан (или ttl задан как
0), значение будет храниться пока не будет удалено явно, либо
по технической причине (очистка кеша, перезапуск и т.д.)
Возвращает закешированное значение
Пример #1 Пример использования apcu_entry()
<?php
$config = apcu_entry("config", function($key) {
return [
"fruit" => apcu_entry("config.fruit", function($key){
return [
"apples",
"pears"
];
}),
"people" => apcu_entry("config.people", function($key){
return [
"bob",
"joe",
"niki"
];
})
];
});
var_dump($config);
?>Результат выполнения данного примера:
array(2) {
["fruit"]=>
array(2) {
[0]=>
string(6) "apples"
[1]=>
string(5) "pears"
}
["people"]=>
array(3) {
[0]=>
string(3) "bob"
[1]=>
string(3) "joe"
[2]=>
string(4) "niki"
}
}
(PECL apcu >= 4.0.0)
apcu_exists — Проверяет, существуют ли записи
keysСтрока или массив строк, содержащие ключи для проверки.
Возвращает true, если ключ существует или false, если нет. Если же
был передан массив ключей, то вернётся массив с существующими ключами, либо
пустой массив, если ни одного ключа не существует.
Пример #1 Пример использования apcu_exists()
<?php
$fruit = 'apple';
$veggie = 'carrot';
apcu_store('foo', $fruit);
apcu_store('bar', $veggie);
if (apcu_exists('foo')) {
echo "Foo с: ";
echo apcu_fetch('foo');
} else {
echo "Foo не существует";
}
echo PHP_EOL;
if (apcu_exists('baz')) {
echo "Baz не существует.";
} else {
echo "Baz не существует";
}
echo PHP_EOL;
$ret = apcu_exists(array('foo', 'donotexist', 'bar'));
var_dump($ret);
?>Результатом выполнения данного примера будет что-то подобное:
Foo существует: apple
Baz не существует
array(2) {
["foo"]=>
bool(true)
["bar"]=>
bool(true)
}
(PECL apcu >= 4.0.0)
apcu_fetch — Извлекает из кеша сохранённую переменную
Извлекает из кеша сохранённую переменную.
key
Ключ key, под которым запись была сохранена в кеш
(с помощью apcu_store()). Если задан массив, то будет извлечён
и возвращён каждый элемент.
success
Устанавливается в true в случае успешного выполнения и false в случае возникновения ошибки.
Сохранённая переменная либо массив; false в случае возникновения ошибки
| Версия | Описание |
|---|---|
| PECL apcu 3.0.17 |
Добавлен параметр success.
|
Пример #1 Пример использования apcu_fetch()
<?php
$bar = 'BAR';
apcu_store('foo', $bar);
var_dump(apcu_fetch('foo'));
?>Результат выполнения данного примера:
string(3) "BAR"
(PECL apcu >= 4.0.0)
apcu_inc — Увеличить сохранённое число
$key,$step = 1,&$success = ?,$ttl = 0Увеличивает сохранённое число.
keyКлюч значения, которое надо увеличить.
stepВеличина, на которую необходимо увеличить.
success
Необязательный параметр. Если задан, то в него будет
записано логическое значение true или false в зависимости от успешности
операции увеличения.
ttlTTL(время жизни), используемое если операция вставляет новое значение (а не увеличивает существующее).
Возвращает текущее значение key в случае успешного выполнения или false в случае возникновения ошибки
Пример #1 Пример использования apcu_inc()
<?php
echo "Сделаем что-то без ошибки", PHP_EOL;
apcu_store('anumber', 42);
echo apcu_fetch('anumber'), PHP_EOL;
echo apcu_inc('anumber'), PHP_EOL;
echo apcu_inc('anumber', 10), PHP_EOL;
echo apcu_inc('anumber', 10, $success), PHP_EOL;
var_dump($success);
echo "А теперь с ошибкой", PHP_EOL, PHP_EOL;
apcu_store('astring', 'foo');
$ret = apcu_inc('astring', 1, $fail);
var_dump($ret);
var_dump($fail);
?>Результатом выполнения данного примера будет что-то подобное:
Сделаем что-то без ошибки 42 43 53 63 bool(true) А теперь с ошибкой bool(false) bool(false)
(No version information available, might only be in Git)
apcu_key_info — Получить детальную информацию о ключе в кеше
$key): ?arrayПолучить детальную информацию о ключе в кеше
keyПолучить детальную информацию о ключе в кеше
Массив, содержащий подробную информацию о ключе кеша
или null, если ключ не существует.
Пример #1 Пример использования apcu_key_info()
<?php
apcu_add('a','b');
var_dump(apcu_key_info('a'));
?>Результат выполнения данного примера:
array(7) {
["hits"]=>
int(0)
["access_time"]=>
int(1606701783)
["mtime"]=>
int(1606701783)
["creation_time"]=>
int(1606701783)
["deletion_time"]=>
int(0)
["ttl"]=>
int(0)
["refs"]=>
int(0)
}
(PECL apcu >= 4.0.0)
apcu_sma_info — Извлекает информацию о выделении разделяемой памяти APCu
$limited = false): array|falseИзвлекает информацию о выделении разделяемой памяти APCu.
limited
Если установлен в false (по умолчанию), apcu_sma_info()
вернёт детальную информацию о каждом сегменте.
Массив данных о выделенной разделяемой памяти; false в случае возникновения ошибки.
Пример #1 Пример использования apcu_sma_info()
<?php
print_r(apcu_sma_info());
?>Результатом выполнения данного примера будет что-то подобное:
Array
(
[num_seg] => 1
[seg_size] => 31457280
[avail_mem] => 31448408
[block_lists] => Array
(
[0] => Array
(
[0] => Array
(
[size] => 31448408
[offset] => 8864
)
)
)
)
(PECL apcu >= 4.0.0)
apcu_store — Кеширует переменную
Кеширует переменную.
Замечание: В отличие от многих других механизмов PHP, переменные, сохранённые apcu_store(), сохраняются между запросами, пока их не удалят из кеша.
key
Имя, под которым будет сохранена переменная. Значение key
является уникальным для кеша, так что попытка сохранить запись с ключом
key, который уже существует, приведёт к её перезаписи.
varПеременная для сохранения
ttl
Время жизни; переменная var будет храниться в течение
ttl секунд. Как только ttl секунд
пройдут, переменная будет удалена из кеша (при следующем запросе). Если параметр
ttl не задан (или ttl задан как
0), значение будет храниться пока не будет удалено явно, либо
по технической причине (очистка кеша, перезапуск и т.д.)
valuesИмена в ключах, переменные в значениях.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Второй тип синтаксиса возвращает массив с ключами, по которым произошла ошибка.
Пример #1 Пример использования apcu_store()
<?php
$bar = 'BAR';
apcu_store('foo', $bar);
var_dump(apcu_fetch('foo'));
?>Результат выполнения данного примера:
string(3) "BAR"
(PECL apcu >= 5.0.0)
Класс APCUIterator позволяет с лёгкостью итерировать большой APCu кеш. Это полезно, так как позволяет перебирать большой кеш по шагам, забирая заданное количество записей используя одну блокировку, позволяя другим активностям использовать блокировку, а не задерживать весь кеш для чтения ста (по умолчанию) записей. Также, использование регулярных выражений более эффективно, так как выполняется на уровне скомпилированного кода C.
$search = null,$format = APC_ITER_ALL,$chunk_size = 100,$list = APC_LIST_ACTIVE(PECL apcu >= 5.0.0)
APCUIterator::__construct — Создаёт объект итератор класса APCUIterator
$search = null,$format = APC_ITER_ALL,$chunk_size = 100,$list = APC_LIST_ACTIVEСоздаёт объект APCUIterator.
search
Либо регулярное выражение PCRE, которое соответствует именам ключей APCu, заданным как строки (string).
Или массив (array) строк (string) с именами ключей APCu.
Или, необязательно, null чтобы пропустить поиск.
formatФормат, заданный одной из констант APC_ITER_*.
chunk_sizeРазмер блока данных. Должно быть больше 0. По умолчанию 100.
list
Тип списка. Задаётся константами APC_LIST_ACTIVE
или APC_LIST_DELETED.
Пример #1 Пример использования APCUIterator::__construct()
<?php
foreach (new APCUIterator('/^counter\./') as $counter) {
echo "$counter[key]: $counter[value]\n";
apc_dec($counter['key'], $counter['value']);
}
?>(PECL apcu >= 5.0.0)
APCUIterator::current — Получить текущий элемент
У этой функции нет параметров.
В случае успешного выполнения возвращает текущий элемент либо false, если элементов больше нет
или произошла ошибка.
(PECL apcu >= 5.0.0)
APCUIterator::getTotalCount — Получить общее количество записей
Получить общее количество записей.
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
Общее количество записей.
(PECL apcu >= 5.0.0)
APCUIterator::getTotalHits — Получить общее количество попаданий в кеш
Получить общее количество попаданий в кеш.
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
Количество попаданий в случае успешного выполнения или false в случае возникновения ошибки.
(PECL apcu >= 5.0.0)
APCUIterator::getTotalSize — Общий размер кеша
Возвращает общий размер кеша.
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
Общий размер кеша.
(PECL apcu >= 5.0.0)
APCUIterator::key — Получить ключ итератора
Возвращает текущий ключ итератора.
У этой функции нет параметров.
В случае успешного выполнения возвращает ключ или false в случае возникновения ошибки.
(PECL apcu >= 5.0.0)
APCUIterator::next — Перемещает указатель на следующий элемент
Перемещает указатель на следующий элемент.
У этой функции нет параметров.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PECL apcu >= 5.0.0)
APCUIterator::rewind — Перемотка итератора
Устанавливает указатель итератора на первый элемент.
У этой функции нет параметров.
Функция не возвращает значения после выполнения.
(PECL apcu >= 5.0.0)
APCUIterator::valid — Проверяет, корректна ли текущая позиция итератора
Проверяет, корректна ли текущая позиция итератора.
У этой функции нет параметров.
Возвращает true или false, в зависимости от того, корректна ли позиция.
Componere (латинский, английский: compose) предназначен для производственных окружений и предоставляет API для составления классов, обезьяньих патчей и приведения.
Componere\Definition используется для определения (или переопределения) класса во время выполнения; Затем класс может быть зарегистрирован и в случае переопределения он заменяет исходный класс до тех пор, пока существует Componere\Definition.
Componere\Patch используется для изменения класса конкретного экземпляра объекта во время выполнения; После применения исправление будет применяться до тех пор, пока существует Componere\Patch и его можно явно отменить.
Componere\ функции приведения могут приводить среди определённых пользователем совместимых типов;
В случае совместимости означает, что Type является подчинённым или супер типом object.
Для работы модуля требуется Reflection
(Componere 2 >= 2.1.0)
Окончательный абстрактный класс представляет собой структуру класса и не должен использоваться программистом.
(Componere 2 >= 2.1.0)
Componere\Abstract\Definition::addInterface — Добавляет интерфейс
$interface): DefinitionРеализует данный интерфейс по текущему определению
interfaceИмя интерфейса без учёта регистра
The current Definition
Выбрасывает исключение RuntimeException, если Definition был зарегистрирован
(Componere 2 >= 2.1.0)
Componere\Abstract\Definition::addMethod — Добавляет метод
Должен создать или переопределить метод в текущем определении.
nameНечувствительное к регистру имя метода
methodComponere\Method ранее не добавленный к другому Definition
The current Definition
Выбрасывает исключение RuntimeException, если Definition был зарегистрирован
Выбрасывает исключение RuntimeException, если метод был добавлен к другому определению
(Componere 2 >= 2.1.0)
Componere\Abstract\Definition::addTrait — Добавляет трейт
$trait): DefinitionИспользовать данный трейт для текущего определения
traitНечувствительное к регистру имя трейта
The current Definition
Выбрасывает исключение RuntimeException, если Definition был зарегистрирован
(Componere 2 >= 2.1.0)
Componere\Abstract\Definition::getReflector — Reflection
Должен создать или вернуть ReflectionClass
ReflectionClass для текущего определения (кешируется)
(Componere 2 >= 2.1.0)
Класс Definition позволяет программисту создавать и регистрировать тип во время выполнения.
Если Definition заменит существующий класс, существующий класс будет восстановлен после уничтожения Definition.
(Componere 2 >= 2.1.0)
Componere\Definition::__construct — Определение конструктора
$name)$name, string $parent)$name, array $interfaces)$name, string $parent, array $interfaces)nameРегистронезависимое имя класса
parentРегистронезависимое имя класса
interfacesМассив регистронезависимых имён классов
Выбрасывает исключение InvalidArgumentException, если сделана попытка заменить внутренний класс
Выбрасывает исключение InvalidArgumentException, если сделана попытка заменить интерфейс
Выбрасывает исключение InvalidArgumentException, если сделана попытка заменить трейт
Выбрасывает исключение RuntimeException, если класс, указанный в interfaces не найден
Выбрасывает исключение RuntimeException, если класс, указанный в interfaces не является интерфейсом
(Componere 2 >= 2.1.0)
Componere\Definition::addConstant — Добавляет константу
Должен объявить константу класса в текущем определении
nameРегистронезависимое имя константы
valueЗначение для константы не должно быть неопределённым (undefined) или статичным
Текущее определение
Выбрасывает исключение RuntimeException, если Definition уже было зарегистрировано
Выбрасывает исключение RuntimeException, если name уже объявлено как константа
Выбрасывает исключение RuntimeException, если value является статичным
Выбрасывает исключение RuntimeException, если value является неопределённым
(Componere 2 >= 2.1.0)
Componere\Definition::addProperty — Добавляет свойство
Должен объявить свойство класса в текущем определении
nameРегистронезависимое имя свойства
valueЗначение свойства по умолчанию
Текущее определение
Выбрасывает исключение RuntimeException, если Definition уже было зарегистрировано
Выбрасывает исключение RuntimeException, если name уже объявлен как свойство
(Componere 2 >= 2.1.0)
Componere\Definition::register — Регистрация
Регистрирует текущее определение
Выбрасывает исключение RuntimeException, если Definition уже был зарегистрирован
(Componere 2 >= 2.1.0)
Componere\Definition::isRegistered — Определение состояния
Определяет состояние регистрации этого определения
Возвращает true, если определение зарегистрировано
(Componere 2 >= 2.1.0)
Componere\Definition::getClosure — Получает замыкание
Должен вернуть замыкание для указанного метода
nameРегистронезависимое имя метода
Замыкание, привязанное к корректной области
Выбрасывает исключение RuntimeException, если Definition уже было зарегистрировано
Выбрасывает исключение RuntimeException, если name не найдено
(Componere 2 >= 2.1.0)
Componere\Definition::getClosures — Получает замыкание
Возвращает массив замыканий
Возвращает все методы в виде массива объектов Closure, привязанных к корректной области
Выбрасывает исключение RuntimeException, если Definition уже было зарегистрировано
(Componere 2 >= 2.1.0)
Класс Patch позволяет программисту изменять тип экземпляра во время выполнения без регистрации нового Definition.
Когда Patch уничтожается, он возвращается, поэтому экземпляры, которые были исправлены в течение срока действия Patch, возвращаются к их формальному типу.
(Componere 2 >= 2.1.0)
Componere\Patch::__construct — Конструктор класса Patch
$instance)$instance, array $interfaces)instanceНазначение для этого патча
interfacesРегистронезависимый массив имён классов
Выбрасывает исключение RuntimeException, если класс не может быть найден interfaces
Выбрасывает исключение RuntimeException, если класс в interfaces не является интерфейсом
(Componere 2 >= 2.1.0)
Componere\Patch::apply — Приложение
Применяет текущий патч
(Componere 2 >= 2.1.0)
Componere\Patch::revert — Отмена
Отменяет текущий патч
(Componere 2 >= 2.1.0)
Componere\Patch::isApplied — Определение состояния
(Componere 2 >= 2.1.1)
Componere\Patch::derive — Получение патча
$instance): Patch
Должен получить Patch для заданного экземпляра instance
instanceНазначение для полученного патча
Patch для instance получается из текущего Patch
Выбрасывает исключение InvalidArgumentException если instance не совместим
(Componere 2 >= 2.1.0)
Componere\Patch::getClosure — Получает замыкание
Должен вернуть замыкание для указанного метода
nameРегистронезависимое имя метода
Замыкание, привязанное к правильной области и объекту
Выбрасывает исключение RuntimeException если name не найден
(Componere 2 >= 2.1.0)
Componere\Patch::getClosures — Получает замыкания
Должен вернуть массив замыканий
Должен вернуть все методы в виде массива объектов Closure, привязанных к правильной области и объекту
(Componere 2 >= 2.1.0)
Method представляет функцию с изменяемыми флагами доступности
(Componere 2 >= 2.1.0)
Componere\Method::__construct — Конструктор класса Method
closure
(Componere 2 >= 2.1.0)
Componere\Method::setPrivate — Изменение доступности
Текущий метод
Выбрасывает исключение RuntimeException, если уровень доступа был ранее установлен
(Componere 2 >= 2.1.0)
Componere\Method::setProtected — Изменение доступности
Текущий метод
Выбрасывает исключение RuntimeException, если уровень доступа был ранее установлен
(Componere 2 >= 2.1.0)
Componere\Method::setStatic — Изменение доступности
Текущий метод
(Componere 2 >= 2.1.0)
Componere\Method::getReflector — Reflection
Должен создать и вернуть ReflectionMethod
ReflectionMethod для текущего метода (кешируется)
(Componere 2 >= 2.1.0)
Value представляет переменную PHP всех типов, включая неопределённую (undefined)
(Componere 2 >= 2.1.0)
Componere\Value::__construct — Конструктор класса Value
$default = ?)
default
Выбрасывает исключение InvalidArgumentException, если default не имеет подходящего значения
(Componere 2 >= 2.1.0)
Componere\Value::setPrivate — Изменение доступности
Текущее значение
Выбрасывает исключение RuntimeException, если уровень доступа был ранее установлен
(Componere 2 >= 2.1.0)
Componere\Value::setProtected — Изменение доступности
Текущее значение
Выбрасывает исключение RuntimeException, если уровень доступа был ранее установлен
(Componere 2 >= 2.1.0)
Componere\Value::setStatic — Изменение доступности
Текущее значение
(Componere 2 >= 2.1.0)
Componere\Value::isPrivate — Определение доступности
(Componere 2 >= 2.1.0)
Componere\Value::isProtected — Определение доступности
(Componere 2 >= 2.1.0)
Componere\Value::isStatic — Определение доступности
(Componere 2 >= 2.1.0)
Componere\Value::hasDefault — Взаимодействие с классом Value
(Componere 2 >= 2.1.2)
Componere\cast — Приведение к типу
$type, $object): TypetypeПользовательский тип
objectОбъект с пользовательским типом, совместимый с Type
object типа Type, приведённый из object
Выбрасывает исключение InvalidArgumentException, если тип object является производным от внутреннего класса
Выбрасывает исключение InvalidArgumentException, если Type является интерфейсом
Выбрасывает исключение InvalidArgumentException, если Type является трейтом
Выбрасывает исключение InvalidArgumentException, если Type является абстрактным классом
Выбрасывает исключение InvalidArgumentException, если Type не совместим с типом object
(Componere 2 >= 2.1.2)
Componere\cast_by_ref — Приведение к типу
$type, $object): TypeПользовательский тип
objectОбъект с пользовательским типом, совместимым с Type
object типа Type, приведённый из object,
где элементы являются ссылками на элементы object
Выбрасывает исключение InvalidArgumentException, если тип object является производным от внутреннего класса
Выбрасывает исключение InvalidArgumentException, если Type является интерфейсом
Выбрасывает исключение InvalidArgumentException, если Type является трейтом
Выбрасывает исключение InvalidArgumentException, если Type является абстрактным классом
Выбрасывает исключение InvalidArgumentException, если Type не совместим с типом object
В данном разделе представлены функции, связанные с обработкой и логированием ошибок. Они дают возможность определять собственные правила обработки ошибок, а также изменять способы их логирования. Это позволяет пользователю настраивать обработку ошибок под собственные нужды.
С помощью функций логирования возможно напрямую отправлять сообщения об ошибках на другие машины, по электронной почте (или на смс-шлюзы), записывать в системные журналы и т.д. Это позволяет выборочно следить за наиболее важными частями приложений и сайтов.
Функции логирования позволяют настраивать тип и детализацию информации об ошибках того или иного типа от простых уведомлений до трассировки функций, вызвавших ошибку.
Для сборки этого модуля не требуются внешние библиотеки.
Для использования этих функций не требуется проведение установки, поскольку они являются частью ядра PHP.
Поведение этих функций зависит от установок в php.ini.
| Имя | По умолчанию | Место изменения | Список изменений |
|---|---|---|---|
| error_reporting | NULL | PHP_INI_ALL | |
| display_errors | "1" | PHP_INI_ALL | |
| display_startup_errors | "1" | PHP_INI_ALL |
До PHP 8.0.0 значение по умолчанию было "0".
|
| log_errors | "0" | PHP_INI_ALL | |
| log_errors_max_len | "1024" | PHP_INI_ALL | Не имеет смысла в версии PHP 8.0.0, удалено в версии PHP 8.1.0. |
| ignore_repeated_errors | "0" | PHP_INI_ALL | |
| ignore_repeated_source | "0" | PHP_INI_ALL | |
| report_memleaks | "1" | PHP_INI_ALL | |
| track_errors | "0" | PHP_INI_ALL | Объявлено устаревшим в PHP 7.2.0, удалено в PHP 8.0.0. |
| html_errors | "1" | PHP_INI_ALL | |
| xmlrpc_errors | "0" | PHP_INI_SYSTEM | |
| xmlrpc_error_number | "0" | PHP_INI_ALL | |
| docref_root | "" | PHP_INI_ALL | |
| docref_ext | "" | PHP_INI_ALL | |
| error_prepend_string | NULL | PHP_INI_ALL | |
| error_append_string | NULL | PHP_INI_ALL | |
| error_log | NULL | PHP_INI_ALL | |
| error_log_mode | 0o644 | PHP_INI_ALL | Доступно, начиная с PHP 8.2.0 |
| syslog.facility | "LOG_USER" | PHP_INI_SYSTEM | Доступно, начиная с PHP 7.3.0. |
| syslog.filter | "no-ctrl" | PHP_INI_ALL | Доступно, начиная с PHP 7.3.0. |
| syslog.ident | "php" | PHP_INI_SYSTEM | Доступно, начиная с PHP 7.3.0. |
Краткое разъяснение конфигурационных директив.
error_reporting
int
Задаёт уровень протоколирования ошибки. Параметр может быть либо числом, представляющим битовое поле, либо именованной константой. Соответствующие уровни и константы приведены в разделе Предопределённые константы, а также в php.ini. Для установки настройки во время выполнения используйте функцию error_reporting(). Смотрите также описание директивы display_errors.
Значение по умолчанию равно E_ALL.
До PHP 8.0.0 значение по умолчанию было:
.
При этой настройке не отображаются уровни ошибок E_ALL &
~E_NOTICE &
~E_STRICT &
~E_DEPRECATEDE_NOTICE,
E_STRICT и E_DEPRECATED.
Замечание: PHP-константы за пределами PHP
Использование PHP-констант за пределами PHP, например в файле httpd.conf, не имеет смысла, так как в таких случаях требуются целочисленные значения (int). Более того, с течением времени будут добавляться новые уровни ошибок, а максимальное значение константы
E_ALLсоответственно будет расти. Поэтому в месте, где предполагается указатьE_ALL, лучше задать большое целое число, чтобы перекрыть все возможные битовые поля. Таким числом может быть, например,2147483647(оно включит все возможные ошибки, не толькоE_ALL).
display_errors
string
Эта настройка определяет, требуется ли выводить ошибки на экран вместе с остальным выводом, либо ошибки должны быть скрыты от пользователя.
Значение "stderr" посылает ошибки в поток stderr
вместо stdout.
Замечание:
Эта функциональность предназначена только для разработки и не должен использоваться в готовых производственных системах (например, системах, имеющих доступ в интернет).
Замечание:
Несмотря на то, что display_errors может быть установлена во время выполнения (функцией ini_set()), это ни на что не повлияет, если в скрипте есть фатальные ошибки. Это обусловлено тем, что ожидаемые действия программы во время выполнения не получат управления (не будут выполняться).
display_startup_errors
bool
Даже если display_errors включена, ошибки, возникающие во время запуска PHP, не будут отображаться. Настойчиво рекомендуем включать директиву display_startup_errors только для отладки.
log_errors
bool
Отвечает за выбор журнала, в котором будут сохраняться сообщения об ошибках. Это может быть журнал сервера или error_log. Применимость этой настройки зависит от конкретного сервера.
Замечание:
Настоятельно рекомендуем при работе на готовых работающих web сайтах протоколировать ошибки там, где они отображаются.
log_errors_max_len
int
Задание максимальной длины log_errors в байтах. В error_log добавляется информация об источнике. Значение по умолчанию 1024. Установка значения в 0 позволяет снять ограничение на длину log_errors. Это ограничение распространяется на записываемые в журнал ошибки, на отображаемые ошибки, а также на $php_errormsg, но не на явно вызываемые функции, такие как error_log().
Если используется int, значение измеряется байтами. Вы также можете использовать сокращённую запись, которая описана в этом разделе FAQ.ignore_repeated_errors
bool
Не заносить в журнал повторяющиеся ошибки. Ошибка считается повторяющейся, если происходит в том же файле и в той же строке, и если настройка ignore_repeated_source выключена.
ignore_repeated_source
bool
Игнорировать источник ошибок при пропуске повторяющихся сообщений. Когда эта настройка включена, повторяющиеся сообщения об ошибках не будут заноситься в журнал вне зависимости от того, в каких файлах и строках они происходят.
report_memleaks
bool
Если настройка включена (по умолчанию), будет формироваться отчёт об утечках памяти,
зафиксированных менеджером памяти Zend. На POSIX платформах этот отчёт будет
направляться в поток stderr. На Windows платформах он будет посылаться в отладчик
функцией OutputDebugString(), просмотреть отчёт в этом случае можно с помощью утилит,
вроде » DbgView. Эта настройка имеет
смысл в сборках, предназначенных для отладки. При этом
E_WARNING должна быть включена в список error_reporting.
track_errors
bool
Если включена, последняя произошедшая ошибка будет первой в переменной $php_errormsg.
html_errors
bool
Если разрешена, сообщения об ошибках будут включать теги HTML. Формат для HTML-ошибок производит нажимаемые ссылки, ведущие на описание ошибки, либо функии, в которой она произошла. За такие ссылки ответственны docref_root и docref_ext.
Если запрещена, то ошибки будут выдаваться простым текстом, без форматирования.
xmlrpc_errors
bool
Если включена, то нормальное оповещение об ошибках отключается и, вместо него, ошибки выводятся в формате XML-RPC.
xmlrpc_error_number
int
Используется в качестве значения XML-RPC элемента faultCode.
docref_root
string
Новый формат ошибок содержит ссылку на страницу с описанием ошибки или
функции, вызвавшей эту ошибку. Можно разместить копию
описаний ошибок и функций локально и задать ini директиве значение
URL этой копии. Если, например, локальная копия описаний доступна по
адресу "/manual/", достаточно прописать
docref_root=/manual/. Дополнительно, необходимо
задать значение директиве docref_ext, отвечающей за соответствие
расширений файлов файлам описаний вашей локальной копии,
docref_ext=.html. Также возможно использование
внешних ссылок. Например,
docref_root=http://manual/en/ или
docref_root="http://landonize.it/?how=url&theme=classic&filter=Landon
&url=http%3A%2F%2Fwww.php.net%2F"
В большинстве случаев вам потребуется, чтобы значение docref_root оканчивалось
слешем "/". Тем не менее, бывают случаи, когда
это не требуется (смотрите выше, второй пример).
Замечание:
Эта функциональность предназначена только для разработки, так как он облегчает поиск описаний функций и ошибок. Не используйте его в готовых производственных системах (например, имеющих доступ в интернет).
docref_ext
string
Смотрите docref_root.
Замечание:
Значение docref_ext должно начинаться с точки
".".
error_prepend_string
string
Строка, которая будет выводиться непосредственно перед сообщением об ошибке. Используется только тогда, когда на экране отображается сообщение об ошибке. Основная цель - добавить дополнительную HTML-разметку к сообщению об ошибке.
error_append_string
string
Строка, которая будет выводиться после сообщения об ошибке. Используется только тогда, когда на экране отображается сообщение об ошибке. Основная цель - добавить дополнительную HTML-разметку к сообщению об ошибке.
error_log
string
Имя файла, в который будут добавляться сообщения об ошибках. Файл
должен быть открыт для записи пользователем веб-сервера. Если
используется специальное значение syslog, то
сообщения будут посылаться в системный журнал. На Unix-системах это
syslog(3), на Windows NT - журнал событий. Смотрите также: syslog().
Если директива не задана, ошибки будут направляться в SAPI журналы.
Например, это могут быть журналы ошибок Apache или поток
stderr командной строки CLI.
Смотрите также функцию error_log().
error_log_mode
int
Режим файла, описанного в error_log.
syslog.facility
string
Указывает, какой тип программы регистрирует сообщение. Действует только в том случае, если опция error_log установлена в "syslog".
syslog.filter
string
Указывает тип фильтра для фильтрации регистрируемых сообщений.
Разрешённые символы передаются без изменений; все остальные записываются в шестнадцатеричном представлении с префиксом \x.
all – строка будет разделена
на символы новой строки и все символы будут переданы без изменений
ascii – строка будет разделена
на символы новой строки, а любые непечатаемые 7-битные символы ASCII будут экранированы
no-ctrl – строка будет разделена
на символы новой строки, а любые непечатаемые символы будут экранированы
raw – все символы передаются в системный
журнал без изменений, без разделения на новые строки (идентично PHP до 7.3)
Директива не поддерживается в Windows.Замечание:
Тип фильтра
rawдоступен начиная с PHP 7.3.8 и PHP 7.4.0.
syslog.ident
string
Определяет строку идентификатора, которая добавляется к каждому сообщению. Действует только в том случае, если опция error_log установлена в "syslog".
Данный модуль не определяет каких-либо типов ресурсов.
Перечисленные ниже константы всегда доступны как часть ядра PHP.
Замечание: Данные имена констант можно использовать в файле php.ini но не вне PHP, как например в файле httpd.conf, где вместо них необходимо использовать значения их битовых масок.
| Значение | Константа | Описание | Примечание |
|---|---|---|---|
| 1 |
E_ERROR
(int)
|
Фатальные ошибки времени выполнения. Это неустранимые средствами самого скрипта ошибки, такие как ошибка распределения памяти и т.п. Выполнение скрипта в таком случае прекращается. | |
| 2 |
E_WARNING
(int)
|
Предупреждения времени выполнения (не фатальные ошибки). Выполнение скрипта в таком случае не прекращается. | |
| 4 |
E_PARSE
(int)
|
Ошибки на этапе компиляции. Должны генерироваться только парсером. | |
| 8 |
E_NOTICE
(int)
|
Уведомления времени выполнения. Указывают на то, что во время выполнения скрипта произошло что-то, что может указывать на ошибку, хотя это может происходить и при обычном выполнении программы. | |
| 16 |
E_CORE_ERROR
(int)
|
Фатальные ошибки, которые происходят во время запуска РНР. Такие ошибки схожи с
E_ERROR, за исключением того, что они генерируются ядром PHP.
|
|
| 32 |
E_CORE_WARNING
(int)
|
Предупреждения (не фатальные ошибки), которые происходят во время начального запуска РНР.
Такие предупреждения схожи с E_WARNING, за исключением того,
что они генерируются ядром PHP.
|
|
| 64 |
E_COMPILE_ERROR
(int)
|
Фатальные ошибки на этапе компиляции. Такие ошибки
схожи с E_ERROR, за исключением того,
что они генерируются скриптовым движком Zend.
|
|
| 128 |
E_COMPILE_WARNING
(int)
|
Предупреждения на этапе компиляции (не фатальные ошибки). Такие
предупреждения схожи с E_WARNING, за
исключением того, что они генерируются скриптовым движком Zend.
|
|
| 256 |
E_USER_ERROR
(int)
|
Сообщения об ошибках, сгенерированные пользователем. Такие
ошибки схожи с E_ERROR, за исключением
того, что они генерируются в коде скрипта средствами функции
PHP trigger_error().
|
|
| 512 |
E_USER_WARNING
(int)
|
Предупреждения, сгенерированные пользователем. Такие
предупреждения схожи с E_WARNING,
за исключением того, что они генерируются в коде скрипта
средствами функции PHP trigger_error().
|
|
| 1024 |
E_USER_NOTICE
(int)
|
Уведомления, сгенерированные пользователем. Такие уведомления
схожи с E_NOTICE, за исключением того,
что они генерируются в коде скрипта, средствами
функции PHP trigger_error().
|
|
| 2048 |
E_STRICT
(int)
|
Включаются для того, чтобы PHP предлагал изменения в коде, которые обеспечат лучшее взаимодействие и совместимость кода. | |
| 4096 |
E_RECOVERABLE_ERROR
(int)
|
Фатальные ошибки с возможностью обработки. Такие ошибки указывают, что,
вероятно, возникла опасная ситуация, но при этом, скриптовый движок остаётся в стабильном состоянии.
Если такая ошибка не обрабатывается функцией, определённой пользователем для обработки ошибок
(смотрите set_error_handler()), выполнение приложения прерывается, как происходит
при ошибках E_ERROR.
|
|
| 8192 |
E_DEPRECATED
(int)
|
Уведомления времени выполнения об использовании устаревших конструкций. Включаются для того, чтобы получать предупреждения о коде, который не будет работать в следующих версиях PHP. | |
| 16384 |
E_USER_DEPRECATED
(int)
|
Уведомления времени выполнения об использовании устаревших
конструкций, сгенерированные пользователем. Такие уведомления
схожи с E_DEPRECATED за исключением того,
что они генерируются в коде скрипта, с помощью функции PHP
trigger_error().
|
|
| 32767 |
E_ALL
(int)
|
Все поддерживаемые ошибки, предупреждения и замечания. |
Представленные выше значения (как числовые, так и символьные) используются для задания битовой маски, определяющей об ошибках какого типа будет даваться отчёт. Вы можете использовать побитовые операторы, чтобы совмещать эти значения для указания определённых типов ошибок. Стоит отметить, что в php.ini допустимы только следующие операторы: '|', '~', '!', '^' и '&'.
Ниже представлен пример использования возможностей обработки ошибок в PHP. Мы определим функцию для обработки ошибок, которая будет записывать информацию об ошибках в файл (используя формат XML), а в случае возникновения критических ошибок, будем дополнительно отправлять разработчикам письмо с уведомлением.
Пример #1 Обработка ошибок в скрипте
<?php
// мы будем делать нашу собственную обработку ошибок
error_reporting(0);
// пользовательская функция для обработки ошибок
function userErrorHandler($errno, $errmsg, $filename, $linenum, $vars)
{
// временная метка возникновения ошибки
$dt = date("Y-m-d H:i:s (T)");
// определим ассоциативный массив соответствия всех
// констант уровней ошибок с их названиями, хотя
// в действительности мы будем рассматривать только
// следующие типы: E_WARNING, E_NOTICE, E_USER_ERROR,
// E_USER_WARNING и E_USER_NOTICE
$errortype = array (
E_ERROR => 'Ошибка',
E_WARNING => 'Предупреждение',
E_PARSE => 'Ошибка разбора исходного кода',
E_NOTICE => 'Уведомление',
E_CORE_ERROR => 'Ошибка ядра',
E_CORE_WARNING => 'Предупреждение ядра',
E_COMPILE_ERROR => 'Ошибка на этапе компиляции',
E_COMPILE_WARNING => 'Предупреждение на этапе компиляции',
E_USER_ERROR => 'Пользовательская ошибка',
E_USER_WARNING => 'Пользовательское предупреждение',
E_USER_NOTICE => 'Пользовательское уведомление',
E_STRICT => 'Уведомление времени выполнения',
E_RECOVERABLE_ERROR => 'Отлавливаемая фатальная ошибка'
);
// определим набор типов ошибок, для которых будет сохранён стек переменных
$user_errors = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE);
$err = "<errorentry>\n";
$err .= "\t<datetime>" . $dt . "</datetime>\n";
$err .= "\t<errornum>" . $errno . "</errornum>\n";
$err .= "\t<errortype>" . $errortype[$errno] . "</errortype>\n";
$err .= "\t<errormsg>" . $errmsg . "</errormsg>\n";
$err .= "\t<scriptname>" . $filename . "</scriptname>\n";
$err .= "\t<scriptlinenum>" . $linenum . "</scriptlinenum>\n";
if (in_array($errno, $user_errors)) {
$err .= "\t<vartrace>" . wddx_serialize_value($vars, "Переменные") . "</vartrace>\n";
}
$err .= "</errorentry>\n\n";
// для тестирования
// echo $err;
// сохраняем в журнал ошибок, а если произошла пользовательская критическая ошибка, то отправляем письмо
error_log($err, 3, "/usr/local/php4/error.log");
if ($errno == E_USER_ERROR) {
mail("phpdev@example.com", "Пользовательская критическая ошибка", $err);
}
}
function distance($vect1, $vect2)
{
if (!is_array($vect1) || !is_array($vect2)) {
trigger_error("Некорректные параметры функции, ожидаются массивы в качестве параметров", E_USER_ERROR);
return NULL;
}
if (count($vect1) != count($vect2)) {
trigger_error("Векторы должны быть одинаковой размерности", E_USER_ERROR);
return NULL;
}
for ($i=0; $i<count($vect1); $i++) {
$c1 = $vect1[$i]; $c2 = $vect2[$i];
$d = 0.0;
if (!is_numeric($c1)) {
trigger_error("Координата $i в векторе 1 не является числом, будет использовать ноль",
E_USER_WARNING);
$c1 = 0.0;
}
if (!is_numeric($c2)) {
trigger_error("Координата $i в векторе 2 не является числом, будет использовать ноль",
E_USER_WARNING);
$c2 = 0.0;
}
$d += $c2*$c2 - $c1*$c1;
}
return sqrt($d);
}
$old_error_handler = set_error_handler("userErrorHandler");
// использование неопределённой константы, будет генерироваться предупреждение
$t = I_AM_NOT_DEFINED;
// определим несколько "векторов"
$a = array(2, 3, "foo");
$b = array(5.5, 4.3, -1.6);
$c = array(1, -3);
// генерируем пользовательскую ошибку
$t1 = distance($c, $b) . "\n";
// генерируем ещё одну пользовательскую ошибку
$t2 = distance($b, "я не массив") . "\n";
// генерируем пользовательское предупреждение
$t3 = distance($a, $b) . "\n";
?>Смотрите также функцию syslog().
(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)
debug_backtrace — Выводит стек вызовов функций в массив
$options = DEBUG_BACKTRACE_PROVIDE_OBJECT, int $limit = 0): arraydebug_backtrace() выводит стек вызовов функций PHP в массив.
optionsАргумент является битовой маской для следующих настроек:
| DEBUG_BACKTRACE_PROVIDE_OBJECT | Нужно ли заполнять данные для ключа object. |
| DEBUG_BACKTRACE_IGNORE_ARGS | Нужно ли исключить аргументы всех функций/методов в ключе "args" для уменьшения расхода памяти. |
Замечание:
Возможны четыре комбинации:
Опции debug_backtrace() debug_backtrace()Заполняются оба индекса. debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT)debug_backtrace(1)debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS & DEBUG_BACKTRACE_PROVIDE_OBJECT)Опускается индекс "object".debug_backtrace(0)debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)Опускается индекс "object"и индекс"args".debug_backtrace(2)
limit
Аргумент используется для ограничения количества
вызовов функций, которые будут выведены. По умолчанию
(limit=0) будет выведен весь
стек вызовов.
Возвращает массив вложенных ассоциативных массивов (array). Описание элементов массива приведено ниже:
| Имя | Тип | Описание |
|---|---|---|
| function | string | Имя текущей функции. Смотрите также __FUNCTION__. |
| line | int | Текущий номер строки. Смотрите также __LINE__. |
| file | string | Имя текущего файла. Смотрите также __FILE__. |
| class | string | Имя текущего класса. Смотрите также __CLASS__ |
| object | object | Текущий объект. |
| type | string | Текущий тип вызова функции. Если это вызов метода объекта, будет выведено "->". Если это вызов статического метода класса, то "::". Если это простой вызов функции, не выводится ничего. |
| args | array | При нахождении внутри функции, будет выведен список аргументов этой функции. Если внутри включаемого файла, будет выведен список включаемых файлов. |
Пример #1 Пример использования debug_backtrace()
<?php
// файл /tmp/a.php
function a_test($str)
{
echo "\nПривет, $str";
var_dump(debug_backtrace());
}
a_test('друг');
?>
<?php
// файл /tmp/b.php
include_once '/tmp/a.php';
?>Результат аналогичен приведённому ниже, если запустить /tmp/b.php:
Привет, друг
array(2) {
[0]=>
array(4) {
["file"] => string(10) "/tmp/a.php"
["line"] => int(10)
["function"] => string(6) "a_test"
["args"]=>
array(1) {
[0] => &string(8) "друг"
}
}
[1]=>
array(4) {
["file"] => string(10) "/tmp/b.php"
["line"] => int(2)
["args"] =>
array(1) {
[0] => string(10) "/tmp/a.php"
}
["function"] => string(12) "include_once"
}
}
(PHP 5, PHP 7, PHP 8)
debug_print_backtrace — Выводит стек вызовов функций
$options = 0, int $limit = 0): voiddebug_print_backtrace() выводит стек вызовов функций. Выводит вызовы функций, имена включённых/требуемых файлов и другую информацию из функций (eval()).
optionsАргумент является битовой маской для следующих настроек:
| DEBUG_BACKTRACE_IGNORE_ARGS | Нужно ли исключить ключ "args", то есть списки аргументов всех функций/методов, чтобы уменьшить расход памяти. |
limit
Аргумент используется для ограничения количества
вызовов функций, которые будут выведены. По умолчанию
(limit=0) будет выведен весь
стек вызовов.
Функция не возвращает значения после выполнения.
Пример #1 Пример использования debug_print_backtrace()
<?php
// файл include.php
function a() {
b();
}
function b() {
c();
}
function c(){
debug_print_backtrace();
}
a();
?><?php
// файл test.php
// этот файл нужно запустить
include 'include.php';
?>Результатом выполнения данного примера будет что-то подобное:
#0 c() called at [/tmp/include.php:10] #1 b() called at [/tmp/include.php:6] #2 a() called at [/tmp/include.php:17] #3 include(/tmp/include.php) called at [/tmp/test.php:3]
(PHP 7, PHP 8)
error_clear_last — Очистить самую последнюю ошибку
У этой функции нет параметров.
Очищает самую последнюю ошибку, делая невозможным получение её с помощью error_get_last().
Пример #1 Пример error_clear_last()
<?php
var_dump(error_get_last());
error_clear_last();
var_dump(error_get_last());
@$a = $b;
var_dump(error_get_last());
error_clear_last();
var_dump(error_get_last());
?>Результатом выполнения данного примера будет что-то подобное:
NULL
NULL
array(4) {
["type"]=>
int(8)
["message"]=>
string(21) "Undefined variable: b"
["file"]=>
string(9) "%s"
["line"]=>
int(6)
}
NULL
(PHP 5 >= 5.2.0, PHP 7, PHP 8)
error_get_last — Получение информации о последней произошедшей ошибке
Получает информацию о последней произошедшей ошибке.
У этой функции нет параметров.
Возвращает ассоциативный массив с описанием последней произошедшей ошибки.
Ключи массива: "type", "message", "file" и "line". Если ошибка произошла
во внутренней функции PHP, элемент с ключом "message" будет начинаться с
имени этой функции. Возвращает null, если ошибок ещё не произошло.
Пример #1 Пример использования error_get_last()
<?php
echo $a;
print_r(error_get_last());
?>Результатом выполнения данного примера будет что-то подобное:
Array
(
[type] => 8
[message] => Undefined variable: a
[file] => C:\WWW\index.php
[line] => 2
)
display_errorshtml_errorsxmlrpc_errors(PHP 4, PHP 5, PHP 7, PHP 8)
error_log — Отправляет сообщение об ошибке заданному обработчику ошибок
$message,$message_type = 0,$destination = null,$additional_headers = nullОтправляет сообщение об ошибке в лог веб-сервера или в пользовательский файл.
messageСообщение об ошибке, которое должно быть логировано.
message_typeОпределяет куда отправлять ошибку. Возможны следующие значения:
| 0 |
Сообщение message отправляется в системный регистратор PHP, используя
механизм логирования операционной системы, или файл, в зависимости от значения директивы
error_log
в конфигурационном файле. Это значение по умолчанию.
|
| 1 |
Сообщение message отправляется электронной почтой на адрес, установленный в параметре
destination. Это единственный тип сообщения, где используется четвёртый параметр
additional_headers.
|
| 2 | Больше не используется. |
| 3 |
message применяется к указанному в
destination файлу. Перенос строки автоматически не добавляется в конец
message.
|
| 4 |
Сообщение message отправляется напрямую в обработчик
логера SAPI.
|
destination
Назначение. Устанавливается в зависимости от параметра
message_type.
additional_headers
Дополнительные заголовки. Используется, когда значение параметра message_type
- 1.
Данный тип сообщения использует ту же внутреннюю функцию, что и
mail().
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Если message_type равен нулю, функция всегда возвращает true,
независимо от того, может ли ошибка логироваться или нет.
| Версия | Описание |
|---|---|
| 8.0.0 |
Параметр destination и
additional_headers теперь допускают значение null.
|
Пример #1 Примеры использования error_log()
<?php
// Отправляет уведомление посредством серверного лога, если мы не можем
// подключиться к базе данных.
if (!Ora_Logon($username, $password)) {
error_log("База данных Oracle недоступна!", 0);
}
// Уведомить администратора по электронной почте, если невозможно выделить ресурсы для FOO
if (!($foo = allocate_new_foo())) {
error_log("Большая проблема, мы выпали из FOO!", 1,
"operator@example.com");
}
// другой способ вызвать error_log():
error_log("Вы ошиблись!", 3, "/var/tmp/my-errors.log");
?>
error_log() не является бинарно-безопасной функцией. message обрезается по null-символу.
message не должен содержать null-символ. Учтите, что message может передаваться в файл, по почте, в syslog и т.д. Используйте подходящую преобразующую или экранирующую функцию, base64_encode(), rawurlencode() или addslashes() перед вызовом error_log().
(PHP 4, PHP 5, PHP 7, PHP 8)
error_reporting — Задаёт, какие ошибки PHP попадут в отчёт
$error_level = null): int
Функция error_reporting() задаёт значение директивы
error_reporting во время
выполнения. В PHP есть много уровней ошибок. Используя эту функцию, можно
задать уровень ошибок времени выполнения скрипта, которые попадут в отчёт.
Если необязательный аргумент error_level не задан,
error_reporting() вернёт текущее значение уровня
протоколирования ошибок.
error_levelНовое значение уровня error_reporting. Это может быть битовая маска или именованные константы. При использовании именованных констант нужно будет следить за совместимостью с новыми версиями PHP. В новых версиях могут добавиться новые уровни ошибок, увеличиться диапазон целочисленных типов. Все это может привести к нестабильной работе при использовании старых целочисленных обозначений уровней ошибок.
Доступные константы уровней ошибок и их описания приведены в разделе Предопределённые константы.
Возвращает старое значение уровня
error_reporting либо текущее
значение, если аргумент error_level не задан.
| Версия | Описание |
|---|---|
| 8.0.0 |
error_level теперь допускает значение null.
|
Пример #1 Примеры использования error_reporting()
<?php
// Выключение протоколирования ошибок
error_reporting(0);
// Включать в отчёт простые описания ошибок
error_reporting(E_ERROR | E_WARNING | E_PARSE);
// Включать в отчёт E_NOTICE сообщения (добавятся сообщения о
// непроинициализированных переменных или ошибках в именах переменных)
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
// Добавлять сообщения обо всех ошибках, кроме E_NOTICE
error_reporting(E_ALL & ~E_NOTICE);
// Добавлять в отчёт все ошибки PHP
error_reporting(E_ALL);
// Добавлять в отчёт все ошибки PHP
error_reporting(-1);
// То же, что и error_reporting(E_ALL);
ini_set('error_reporting', E_ALL);
?>
Если передать -1, будут отображаться все возможные
ошибки, даже если в новых версиях PHP добавятся уровни или константы.
Поведение эквивалентно передаче константы E_ALL.
(PHP 4 >= 4.0.1, PHP 5, PHP 7, PHP 8)
restore_error_handler — Восстанавливает предыдущий обработчик ошибок
Используется после смены обработчика ошибок функцией set_error_handler(), чтобы вернуть предыдущий обработчик (который может быть как встроенной функцией, так и определённой пользователем).
У этой функции нет параметров.
Функция всегда возвращает true.
Пример #1 Пример использования restore_error_handler()
Определение, произошла ли ошибка в функции unserialize(), а затем восстановление исходного обработчика ошибок.
<?php
function unserialize_handler($errno, $errstr)
{
echo "Сериализуемое значение недопустимо.\n";
}
$serialized = 'foo';
set_error_handler('unserialize_handler');
$original = unserialize($serialized);
restore_error_handler();
?>Результат выполнения данного примера:
Сериализуемое значение недопустимо.
(PHP 5, PHP 7, PHP 8)
restore_exception_handler — Восстанавливает предыдущий обработчик исключений
Используется после смены обработчика исключений функцией set_exception_handler(), чтобы вернуть предыдущий обработчик (который может быть как встроенной функцией, так и определённой пользователем).
У этой функции нет параметров.
Функция всегда возвращает true.
Пример #1 Пример использования restore_exception_handler()
<?php
function exception_handler_1(Exception $e)
{
echo '[' . __FUNCTION__ . '] ' . $e->getMessage();
}
function exception_handler_2(Exception $e)
{
echo '[' . __FUNCTION__ . '] ' . $e->getMessage();
}
set_exception_handler('exception_handler_1');
set_exception_handler('exception_handler_2');
restore_exception_handler();
throw new Exception('Вызван первый обработчик исключений...');
?>Результат выполнения данного примера:
[exception_handler_1] Вызван первый обработчик исключений...
(PHP 4 >= 4.0.1, PHP 5, PHP 7, PHP 8)
set_error_handler — Задаёт пользовательский обработчик ошибок
Задаёт пользовательскую функцию (callback),
как обработчик ошибок в скрипте.
Функция может быть использована для определения пользовательских обработчиков ошибок во время выполнения, например, в приложениях, которые должны выполнять очистку файлов/данных в случае возникновения критической ошибки или при инициировании ошибки в ответ на определённые условия (используя функцию trigger_error()).
Важно помнить, что стандартный обработчик ошибок PHP не будет обрабатывать
никакие типы ошибок, определённые в error_levels,
пока callback-функция не вернёт false. Пользовательский обработчик будет
вызываться в случае возникновения любой ошибки, независимо от настроек, заданных функцией
error_reporting.
Также обратите внимание, что обработчик обязан при необходимости остановить выполнение скрипта, вызвав функцию exit(). Если происходит возврат из обработчика ошибок, управление передаётся следующему выражению, стоящему за тем, что вызвало ошибку.
Ошибки следующих типов не могут быть обработаны пользователем:
E_ERROR, E_PARSE,
E_CORE_ERROR, E_CORE_WARNING,
E_COMPILE_ERROR,
E_COMPILE_WARNING независимо от того, где они были сгенерированы и большинство
ошибок E_STRICT, произошедших в файле, где вызвана
функция set_error_handler().
Если ошибки возникают до запуска скрипта (например, пока файл загружается), пользовательский обработчик не будет вызываться, если на этот момент он ещё не зарегистрирован.
callback
Если передано значение null, обработчик сбрасывается в состояние по умолчанию.
В противном случае обработчик представляет собой callback-функцию со следующей сигнатурой:
$errno,$errstr,$errfile = ?,$errline = ?,$errcontext = ?errnoerrno будет передан уровень
ошибки в виде целого числа.
errstrerrstr будет передано сообщение
об ошибке в виде строки.
errfileerrfile, то в него будет передано
имя файла, в котором произошла ошибка, в виде строки.
errlineerrline, то в него будет передан
номер строки, в которой произошла ошибка, в виде целого
числа.
errcontexterrcontext, то в него будет передан
массив указателей на активную таблицу символов в точке, где
произошла ошибка. Другими словами, errcontext
будет содержать массив всех переменных, существующих в области
видимости, где произошла ошибка. Пользовательские обработчики ошибок не
должны изменять этот контекст.
Этот параметр объявлен УСТАРЕВШИМ начиная с PHP 7.2.0 и был УДАЛЁН в PHP 8.0.0. Если в вашей функции этот параметр используется и для него не задано значение по умолчанию, то при вызове функции обработчика будет выдана ошибка "too few arguments".
Если функция возвращает false, управление передаётся встроенному
обработчику ошибок.
error_levels
Может использоваться для задания маски, в соответствии с которой будет
вызываться callback, по аналогии с
ini-настройкой error_reporting,
которая отвечает за то, какие ошибки будут показаны в отчёте. Без этой
маски callback будет вызываться для
обработки всех происходящих ошибок, вне зависимости от настроек в
error_reporting.
Возвращает ранее определённый обработчик ошибок (если есть) Если на данный момент используется встроенный обработчик, функция
вернёт null. Если предыдущий определённый обработчик является методом класса, функция вернёт массив,
содержащий имя класса и имя метода.
| Версия | Описание |
|---|---|
| 8.0.0 |
Параметр errcontext был удалён и больше не передаётся в
пользовательскую функцию обработки ошибок.
|
| 7.2.0 |
Параметр errcontext объявлен устаревшим. Теперь при его
использовании будет вызываться ошибка уровня E_DEPRECATED.
|
Пример #1 Обработка ошибок с помощью функций set_error_handler() и trigger_error()
Пример ниже демонстрирует обработку внутренних исключений путём вызова ошибок разных типов и их обработки пользовательской функцией:
<?php
// функция обработки ошибок
function myErrorHandler($errno, $errstr, $errfile, $errline)
{
if (!(error_reporting() & $errno)) {
// Этот код ошибки не включён в error_reporting,
// так что пусть обрабатываются стандартным обработчиком ошибок PHP
return false;
}
// может потребоваться экранирование $errstr:
$errstr = htmlspecialchars($errstr);
switch ($errno) {
case E_USER_ERROR:
echo "<b>Пользовательская ОШИБКА</b> [$errno] $errstr<br />\n";
echo " Фатальная ошибка в строке $errline файла $errfile";
echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />\n";
echo "Завершение работы...<br />\n";
exit(1);
case E_USER_WARNING:
echo "<b>Пользовательское ПРЕДУПРЕЖДЕНИЕ</b> [$errno] $errstr<br />\n";
break;
case E_USER_NOTICE:
echo "<b>Пользовательское УВЕДОМЛЕНИЕ</b> [$errno] $errstr<br />\n";
break;
default:
echo "Неизвестная ошибка: [$errno] $errstr<br />\n";
break;
}
/* Не запускаем внутренний обработчик ошибок PHP */
return true;
}
// функция для тестирования обработчика ошибок
function scale_by_log($vect, $scale)
{
if (!is_numeric($scale) || $scale <= 0) {
trigger_error("log(x) для x <= 0 не определён, вы используете: scale = $scale", E_USER_ERROR);
}
if (!is_array($vect)) {
trigger_error("Некорректный входной вектор, пропущен массив значений", E_USER_WARNING);
return null;
}
$temp = array();
foreach($vect as $pos => $value) {
if (!is_numeric($value)) {
trigger_error("Значение на позиции $pos не является числом, будет использован 0 (ноль)", E_USER_NOTICE);
$value = 0;
}
$temp[$pos] = log($scale) * $value;
}
return $temp;
}
// переключаемся на пользовательский обработчик
$old_error_handler = set_error_handler("myErrorHandler");
// вызовем несколько ошибок, во-первых, определим массив с нечисловым элементом
echo "vector a\n";
$a = array(2, 3, "foo", 5.5, 43.3, 21.11);
print_r($a);
// теперь создадим ещё один массив
echo "----\nvector b - a notice (b = log(PI) * a)\n";
/* Значение на позиции $pos не является числом, будет использован 0 (ноль)*/
$b = scale_by_log($a, M_PI);
print_r($b);
// проблема, мы передаём строку вместо массива
echo "----\nvector c - a warning\n";
/* Некорректный входной вектор, пропущен массив значений */
$c = scale_by_log("not array", 2.3);
var_dump($c); // NULL
// критическая ошибка, логарифм от неположительного числа не определён
echo "----\nvector d - fatal error\n";
/* log(x) для x <= 0 не определён, вы используете: scale = $scale */
$d = scale_by_log($a, -2.5);
var_dump($d); // До сюда не дойдём никогда
?>Результатом выполнения данного примера будет что-то подобное:
vector a
Array
(
[0] => 2
[1] => 3
[2] => foo
[3] => 5.5
[4] => 43.3
[5] => 21.11
)
----
vector b - a notice (b = log(PI) * a)
<b>Пользовательское УВЕДОМЛЕНИЕ</b> [1024] Значение на позиции 2 не является числом, будет использован 0 (ноль)<br />
Array
(
[0] => 2.2894597716988
[1] => 3.4341896575482
[2] => 0
[3] => 6.2960143721717
[4] => 49.566804057279
[5] => 24.165247890281
)
----
vector c - a warning
<b>Пользовательское ПРЕДУПРЕЖДЕНИЕ</b> [512] Некорректный входной вектор, пропущен массив значений<br />
NULL
----
vector d - fatal error
<b>Пользовательская ОШИБКА</b> [256] log(x) for x <= 0 is undefined, you used: scale = -2.5<br />
Фатальная ошибка в строке 35 файла trigger_error.php, PHP 5.2.1 (FreeBSD)<br />
Завершение работы...<br />
(PHP 5, PHP 7, PHP 8)
set_exception_handler — Задаёт пользовательский обработчик исключений
Задаёт обработчик по умолчанию для случаев, когда исключение выброшено
вне блока try/catch. После вызова callback
выполнение будет остановлено.
callbackФункция, вызываемая при возникновении неперехваченного исключения. Эта функция-обработчик должна принимать один параметр, которым будет объект выброшенного исключения Throwable. И Error и Exception реализуют интерфейс Throwable. Сигнатура обработчика:
В качестве этого аргумента можно передать null. В этом случае
обработчик вернётся к своему изначальному состоянию.
Возвращает ранее определённый обработчик исключений или null в случае
ошибки. Если предыдущих обработчиков определено не было, то также
возвращается null.
Пример #1 Пример использования set_exception_handler()
<?php
function exception_handler(Throwable $exception) {
echo "Неперехваченное исключение: " , $exception->getMessage(), "\n";
}
set_exception_handler('exception_handler');
throw new Exception('Неперехваченное исключение');
echo "Не выполнено\n";
?>
(PHP 4 >= 4.0.1, PHP 5, PHP 7, PHP 8)
trigger_error — Вызывает пользовательскую ошибку/предупреждение/уведомление
$message, int $error_level = E_USER_NOTICE): boolИспользуется для вызова пользовательских ошибок. Можно использовать в связке со встроенным обработчиком ошибок, а также с пользовательским обработчиком, заданным функцией set_error_handler().
Эта функция может быть полезной, если требуется сгенерировать определённую реакцию на исключение во время выполнения.
messageСообщение, соответствующее этой ошибке. Ограничено 1024 байтами в длину. Символы дальше 1024-го будут обрезаны.
error_level
Назначенный тип ошибки. Работает только с семейством констант E_USER.
По умолчанию E_USER_NOTICE.
Функция возвращает false, если задан неправильный
error_level, и true в остальных случаях.
Пример #1 Пример использования trigger_error()
Более подробный пример приведён в описании функции set_error_handler().
<?php
if ($divisor == 0) {
trigger_error("Не могу поделить на ноль", E_USER_ERROR);
}
?>
HTML-сущности в message не экранированы.
Чтобы сообщение можно было отобразить в браузере, преобразуйте его
функцией htmlentities().
Функция является псевдонимом: trigger_error().
Модуль позволяет загружать общие(shared) библиотеки (.DLL или .so), вызывать C-функции и получать доступ с структурам языка C из PHP без необходимости глубоко изучать API модулей Zend и стороннего, "промежуточного" языка. Публичный API реализован как один единственный класс FFI с некоторым набором статических методов (некоторые из них могут вызываться динамически) и переопределёнными методами объекта, что позволяет взаимодействовать с данными С.
Модуль FFI довольно опасен, поскольку позволяет взаимодействовать с системой на очень низком уровне. Модуль FFI должен использоваться только разработчиками, знакомыми с языком С и умеющими использовать его API. Для минимизации риска, модуль может быть запрещён директивой ffi.enable в php.ini.
Замечание:
Модуль FFI не делает классический API модулей PHP устаревшим; он предназначен для взаимодействия с функциями и структурами данных C.
Сейчас доступ к структурам данных FFI примерно в 2 раза медленнее чем доступ к объектам и массивам PHP. Таким образом, нет повода использовать FFI для ускорения; однако его можно использовать для сокращения потребляемой памяти.
Для включения модуля FFI, PHP надо сконфигурировать с ключом --with-ffi.
Пользователям Windows будет необходимо добавить php_ffi.dll в php.ini.
Поведение этих функций зависит от установок в php.ini.
| Имя | По умолчанию | Место изменения | Список изменений |
|---|---|---|---|
| ffi.enable | "preload" | PHP_INI_SYSTEM | |
| ffi.preload | "" | PHP_INI_SYSTEM |
Краткое разъяснение конфигурационных директив.
ffi.enable
string
Позволяет разрешить ("true") или запретить
("false") использование FFI API, либо
ограничить использование только для CLI SAPI и
предзагруженных файлов ("preload").
Ограничения FFI API влияют только на класс FFI, но не на перезагруженные функции объекта FFI\CData. Это значит, что можно создать объекты FFI\CData в предзагружаемых файлах и использовать потом напрямую из скриптов PHP.
ffi.preload
string
Позволяет предзагружать привязки FFI во время
старта, что невозможно с
FFI::load(),
если включено opcache.preload_user.
Эта директива принимает список разделителей имён файлов
DIRECTORY_SEPARATOR.
Предзагруженные привязки доступны с помощью
вызова FFI::scope().
Данный модуль не определяет каких-либо типов ресурсов.
Данный модуль не определяет никакие константы.
Перед погружением в детали FFI API, давайте рассмотрим несколько примеров упрощённого использования FFI API в стандартных задачах.
Замечание:
Для некоторых из этих примеров понадобится библиотека libc.so.6. Они не будут работать в системах, где её нет.
Пример #1 Вызов функции из общей библиотеки
<?php
// создаём объект FFI, загружаем libc и экспортируем функцию printf()
$ffi = FFI::cdef(
"int printf(const char *format, ...);", // это стандартная декларация C
"libc.so.6");
// вызываем printf()
$ffi->printf("Привет, %s!\n", "мир");
?>Результат выполнения данного примера:
Привет, мир!
Замечание:
Обратите внимание, что для некоторых функций C требуются определённые соглашения о вызовах, например:
__fastcall,__stdcallили,__vectorcall.
Пример #2 Вызов функции и возврат структуры через аргумент
<?php
// создаём привязку gettimeofday()
$ffi = FFI::cdef("
typedef unsigned int time_t;
typedef unsigned int suseconds_t;
struct timeval {
time_t tv_sec;
suseconds_t tv_usec;
};
struct timezone {
int tz_minuteswest;
int tz_dsttime;
};
int gettimeofday(struct timeval *tv, struct timezone *tz);
", "libc.so.6");
// создаём структуры данных C
$tv = $ffi->new("struct timeval");
$tz = $ffi->new("struct timezone");
// вызываем gettimeofday()
var_dump($ffi->gettimeofday(FFI::addr($tv), FFI::addr($tz)));
// получаем доступ к полю структуры данных C
var_dump($tv->tv_sec);
// печатаем всю структуру данных
var_dump($tz);
?>Результатом выполнения данного примера будет что-то подобное:
int(0)
int(1555946835)
object(FFI\CData:struct timezone)#3 (2) {
["tz_minuteswest"]=>
int(0)
["tz_dsttime"]=>
int(0)
}
Пример #3 Доступ к существующим переменным C
<?php
// создаём объект FFI, загружаем libc и экспортируем переменную errno
$ffi = FFI::cdef(
"int errno;", // это стандартная декларация C
"libc.so.6");
// печатаем errno
var_dump($ffi->errno);
?>Результат выполнения данного примера:
int(0)
Пример #4 Создание и модификация переменной C
<?php
// создаём переменную C типа int
$x = FFI::new("int");
var_dump($x->cdata);
// простое присваивание
$x->cdata = 5;
var_dump($x->cdata);
// не простое присвоение
$x->cdata += 2;
var_dump($x->cdata);
?>Результат выполнения данного примера:
int(0) int(5) int(7)
Пример #5 Работа с массивами C
<?php
// создаём структуру данных
$a = FFI::new("long[1024]");
// работаем с ней как с обычным массивом PHP
for ($i = 0; $i < count($a); $i++) {
$a[$i] = $i;
}
var_dump($a[25]);
$sum = 0;
foreach ($a as $n) {
$sum += $n;
}
var_dump($sum);
var_dump(count($a));
var_dump(FFI::sizeof($a));
?>Результат выполнения данного примера:
int(25) int(523776) int(1024) int(8192)
Пример #6 Работа с перечислениями C
<?php
$a = FFI::cdef('typedef enum _zend_ffi_symbol_kind {
ZEND_FFI_SYM_TYPE,
ZEND_FFI_SYM_CONST = 2,
ZEND_FFI_SYM_VAR,
ZEND_FFI_SYM_FUNC
} zend_ffi_symbol_kind;
');
var_dump($a->ZEND_FFI_SYM_TYPE);
var_dump($a->ZEND_FFI_SYM_CONST);
var_dump($a->ZEND_FFI_SYM_VAR);
?>Результат выполнения данного примера:
int(0) int(2) int(3)
Можно присвоить замыкание PHP переменной типа "указатель" (pointer) либо передать его как аргумент функции:
<?php
$zend = FFI::cdef("
typedef int (*zend_write_func_t)(const char *str, size_t str_length);
extern zend_write_func_t zend_write;
");
echo "Привет, мир 1!\n";
$orig_zend_write = clone $zend->zend_write;
$zend->zend_write = function($str, $len) {
global $orig_zend_write;
$orig_zend_write("{\n\t", 3);
$ret = $orig_zend_write($str, $len);
$orig_zend_write("}\n", 2);
return $ret;
};
echo "Привет, мир 2!\n";
$zend->zend_write = $orig_zend_write;
echo "Привет, мир 3!\n";
?>Результат выполнения данного примера:
Привет, мир 1!
{
Привет, мир 2!
}
Привет, мир 3!
Поэтому рекомендуется минимизировать использование callback-функций PHP.
php.ini
ffi.enable=preload opcache.preload=preload.php
preload.php
<?php
FFI::load(__DIR__ . "/dummy.h");
opcache_compile_file(__DIR__ . "/dummy.php");
?>dummy.h
#define FFI_SCOPE "DUMMY" #define FFI_LIB "libc.so.6" int printf(const char *format, ...);
dummy.php
<?php
final class Dummy {
private static $ffi = null;
function __construct() {
if (is_null(self::$ffi)) {
self::$ffi = FFI::scope("DUMMY");
}
}
function printf($format, ...$args) {
return (int)self::$ffi->printf($format, ...$args);
}
}
?>test.php
<?php
$d = new Dummy();
$d->printf("Привет, %s!\n", "мир");
?>(PHP 7 >= 7.4.0, PHP 8)
Объекты этого класса создаются фабричными методами FFI::cdef(), FFI::load() и FFI::scope(). Объявленные переменные C доступны как свойства экземпляра FFI, а функции как его методы. Объявленные типы C можно использовать для создания структур данных с помощью FFI::new() и FFI::type().
Разбор объявлений FFI и загрузка разделяемой библиотеки
может занять значительное время. Не имеет смысла делать
это для каждого HTTP-запроса в окружении Web. Тем не
менее можно перезагрузить объявления FFI и библиотеки
при старте PHP и инстанциировать объекты FFI по
необходимости. Заголовочные файлы могут быть расширены
специальными объявлениями FFI_SCOPE
(например, #define FFI_SCOPE "foo";
скоуп по умолчанию "C") и загружены с помощью
FFI::load() во время предзагрузки.
Это приведёт к созданию постоянных привязок, которые
будут доступны для всех запросов через
FFI::scope().
Более подробно читайте на странице
Простые примеры использования FFI.
В один и тот же скоуп можно загрузить несколько заголовочных файлов.
FFI::__BIGGEST_ALIGNMENT__(PHP 7 >= 7.4.0, PHP 8)
FFI::addr — Создаёт неуправляемый указатель на данные C
Создаёт неуправляемый указатель на данные C, представленные
заданным FFI\CData. Исходный
ptr должен пережить результирующий
указатель. Эта функция используется главным образом для
передачи аргументов в функцию C по указателю.
ptrДескриптор неуправляемого указателя на структуру данных.
Возвращает новый объект FFI\CData.
(PHP 7 >= 7.4.0, PHP 8)
FFI::alignof — Возвращает величину выравнивания
ptrДескриптор указателя на данные или тип C.
(PHP 7 >= 7.4.0, PHP 8)
FFI::arrayType — Динамически конструирует новый тип С массива
Динамически конструирует новый тип С массива с элементами типа
type и размерностями, заданными в
dimensions. В следующем примере
$t1 и $t2 определяют массивы
одинакового типа:
<?php
$t1 = FFI::type("int[2][3]");
$t2 = FFI::arrayType(FFI::type("int"), [2, 3]);
?>typeКорректная декларация типа С, например string, или заранее созданный объект класса FFI\CType.
dimensionsМассив, определяющий размерность типа.
Возвращает новый объект FFI\CType.
(PHP 7 >= 7.4.0, PHP 8)
FFI::cast — Производит преобразование типа C
FFI::cast() создаёт новый объект
класса FFI\CData, который указывает на
ту же структуру C, но ассоциирован с другим типом.
Полученный объект не становится владельцем данных, так что
исходный указатель ptr должен
оставаться живым дольше полученного объекта. Тип C должен
быть задан как строка, содержащая имя любого корректного
типа С, либо как объект FFI\CType.
Если метод вызывается статически, то можно использовать только
предопределённые имена типов С (например,
int, char, etc.); если метод
вызывается как метод объекта, то допустимы любые определённые
для него типы.
typeСтрока с именем типа С или объект класса FFI\CType.
ptrДескриптор указателя на структуру данных С.
Возвращает новый объект FFI\CData.
(PHP 7 >= 7.4.0, PHP 8)
FFI::cdef — Создаёт новый объект FFI
Создаёт новый объект FFI.
codeСтрока, содержащая последовательность деклараций на языке С (типы, структуры, функции, переменные и т.д.). Фактически можно скопировать кусок заголовочного файла С.
Замечание:
Директивы сопроцессора С не поддерживаются. Т.е.
#include,#defineи макросы CPP работать не будут.
libИмя файла библиотеки, который будет загружен и связан с заданными декларациями.
Замечание:
Если параметр
libне задан илиnull, то для платформ, поддерживающихRTLD_DEFAULT, будет произведён поиск задекларированных вcodeсущностей в глобальной области видимости. Для прочих платформ произвести привязку не получится.
Возвращает новый объект FFI.
| Версия | Описание |
|---|---|
| 8.0.0 |
lib теперь допускает значение null.
|
(PHP 7 >= 7.4.0, PHP 8)
FFI::free — Высвобождает неуправляемую структуру данных
Высвобождает созданную ранее неуправляемую структуру данных.
ptrДескриптор неуправляемого указателя на структуру данных.
Функция не возвращает значения после выполнения.
(PHP 7 >= 7.4.0, PHP 8)
FFI::isNull — Проверяет, является ли FFI\CData нулевым указателем
Проверяет, является ли FFI\CData нулевым указателем.
ptrУказатель на структуру данных C.
Возвращает true или false в зависимости от того,
является ли FFI\CData нулевым указателем.
(PHP 7 >= 7.4.0, PHP 8)
FFI::load — Загрузить декларации C из заголовочного файла
Загружает декларации C из заголовочного файла. Можно указать
общие библиотеки для загрузки с помощью специальной
#define директивы FFI_LIB в
заголовочном файле.
filenameИмя заголовочного файла C.
Директивы сопроцессора С не поддерживаются. Т.е.
#include, #define и макросы CPP
работать не будут, за исключением особых случаев,
перечисленных ниже.
Заголовочный файл должен содержать оператор #define
для переменной FFI_SCOPE, например, #define FFI_SCOPE "MYLIB".
За подробностями обратитесь к Введению в FFI.
Заголовочный файл может содержать оператор #define для переменной
FFI_LIB, чтобы указать библиотеку, которую он раскрывает. Если это
системная библиотека, требуется только имя файла, например:
#define FFI_LIB
"libc.so.6". Если это пользовательская библиотека, требуется относительный путь,
например: #define FFI_LIB "./mylib.so".
Возвращает новый объект FFI или null в случае возникновения ошибки.
(PHP 7 >= 7.4.0, PHP 8)
FFI::memcmp — Сравнивает две области памяти
Сравнивает size байт памяти по указателям
ptr1 и ptr2.
И ptr1 и ptr2
могут быть любыми нативными структурами данных
(FFI\CData), либо строками PHP.
ptr1Указатель на первую область памяти.
ptr2Указатель на вторую область памяти.
sizeКоличество байт для сравнения.
Возвращает < 0, если содержимое памяти для
ptr1 меньше, чем для
ptr2, > 0, если первое
больше второго и 0, если равны.
(PHP 7 >= 7.4.0, PHP 8)
FFI::memcpy — Копирует содержимое одной области памяти в другую
Копирует size байт из области памяти
from в область памяти
to.
toЦелевая область памяти.
fromОбласть памяти, откуда будет происходить копирование.
sizeКоличество байт для копирования.
Функция не возвращает значения после выполнения.
(PHP 7 >= 7.4.0, PHP 8)
FFI::memset — Заполнить область памяти
Заполняет size байт памяти по указателю
ptr значением value.
ptrУказатель на начало участка памяти.
valueЗначение для заполнения.
sizeКоличество байт, которые будут заполнены.
Функция не возвращает значения после выполнения.
(PHP 7 >= 7.4.0, PHP 8)
FFI::new — Создаёт структуру данных C
$type, bool $owned = true, bool $persistent = false): ?FFI\CData
Создаёт нативную структуру данных заданного типа.
При статическом вызове данного метода необходимо использовать
только предопределённые имена типов С (такие как
int, char, и т.д.); при вызове как
метод объекта, допустим любой тип объявленный для него.
type
type - корректная декларация типа С,
например, string или заранее созданный объект класса
FFI\CType.
ownedСоздавать ли управляемые или неуправляемые данные. Управляемые данные живут в связке с возвращённым объектом FFI\CData и высвобождается когда стандартный подсчёт ссылок PHP или GC (сборщик мусора) освободят последнюю ссылку на этот объект. Неуправляемые данные необходимо высвобождать вручную с помощью FFI::free().
persistentРасполагать ли данные на постоянной основе к системной куче(heap) (используя malloc()), или в куче запроса PHP (используя emalloc()).
Возвращает новый объект FFI\CData
или null в случае возникновения ошибки.
(PHP 7 >= 7.4.0, PHP 8)
FFI::scope — Инстанциирует объект FFI в соответствии с декларацией С, разобранной на этапе предзагрузки
Инстанциирует объект FFI в соответствии с декларацией С, разобранной на этапе предзагрузки.
Метод FFI::scope() можно многократно вызывать для одного и того же контекста. Множество ссылок на один и тот же контекст могут быть загружены одновременно.
name
Имя скоупа, заданного с помощью специальной
#define директивы FFI_SCOPE.
Возвращает новый объект FFI.
(PHP 7 >= 7.4.0, PHP 8)
FFI::sizeof — Возвращает размер данных или типа C
ptrДескриптор указателя на тип или данные C.
Размер области памяти, на который указывает
ptr.
(PHP 7 >= 7.4.0, PHP 8)
FFI::string — Создаёт строку PHP из области памяти
Создаёт переменную PHP типа string из
size байт памяти, начиная с
адреса по указателю ptr.
ptrНачало участка памяти, из которой будет создаваться строка.
size
Количество байт для копирования в строку.
Если параметр size не задан или null, то
ptr должен указывать на массив
C типа char, завершающийся
нулевым байтом.
Строка PHP.
| Версия | Описание |
|---|---|
| 8.0.0 |
size теперь допускает значение null; ранее значением по умолчанию был
0.
|
(PHP 7 >= 7.4.0, PHP 8)
FFI::type — Создаёт объект FFI\CType из декларации С
Функция создаёт и возвращает объект
FFI\CType для заданной строки, содержащей
декларацию типа С.
Если метод вызывается статически, то можно использовать только
предопределённые имена типов С (например,
int, char, и т.д.); если метод
вызывается как метод объекта, то допустимы любые определённые
для него типы.
typeКорректная декларация типа C в качестве строки (string).
Возвращает новый объект FFI\CType
или null в случае возникновения ошибки.
(PHP 7 >= 7.4.0, PHP 8)
FFI::typeof — Получает FFI\CType для FFI\CData
ptrУказатель на структуру данных C.
(PHP 7 >= 7.4.0, PHP 8)
Объекты FFI\CData могут использоваться множеством разных способов как обычные данные PHP:
$x = FFI::new('int'); $x->cdata = 42;
$cdata->field
$cdata[$offset]
$cdata[0]
<,
<=, ==, !=, >=, >).
+/-/
++/–-: $cdata += 5
-.
$cdata()
$cdata2 = clone $cdata;
Замечание: Обратите внимание, что для экземпляров FFI\CData не поддерживаются функции isset(), empty() и unset(). А для тех, что оборачивают структуры и объединения не реализован интерфейс Traversable.
(PHP 7 >= 7.4.0, PHP 8)
FFI\CType::TYPE_VOIDFFI\CType::TYPE_FLOATFFI\CType::TYPE_DOUBLEFFI\CType::TYPE_LONGDOUBLEFFI\CType::TYPE_UINT8FFI\CType::TYPE_SINT8FFI\CType::TYPE_UINT16FFI\CType::TYPE_SINT16FFI\CType::TYPE_UINT32FFI\CType::TYPE_SINT32FFI\CType::TYPE_UINT64FFI\CType::TYPE_SINT64FFI\CType::TYPE_ENUMFFI\CType::TYPE_BOOLFFI\CType::TYPE_CHARFFI\CType::TYPE_POINTERFFI\CType::TYPE_FUNCFFI\CType::TYPE_ARRAYFFI\CType::TYPE_STRUCTFFI\CType::ATTR_CONSTFFI\CType::ATTR_INCOMPLETE_TAGFFI\CType::ATTR_VARIADICFFI\CType::ATTR_INCOMPLETE_ARRAYFFI\CType::ATTR_VLAFFI\CType::ATTR_UNIONFFI\CType::ATTR_PACKEDFFI\CType::ATTR_MS_STRUCTFFI\CType::ATTR_GCC_STRUCTFFI\CType::ABI_DEFAULTFFI\CType::ABI_CDECLFFI\CType::ABI_FASTCALLFFI\CType::ABI_THISCALLFFI\CType::ABI_STDCALLFFI\CType::ABI_PASCALFFI\CType::ABI_REGISTERFFI\CType::ABI_MSFFI\CType::ABI_SYSVFFI\CType::ABI_VECTORCALL(PHP 8 >= 8.1.0)
FFI\CType::getAlignment — Описание
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
(PHP 8 >= 8.1.0)
FFI\CType::getArrayElementType — Описание
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
(PHP 8 >= 8.1.0)
FFI\CType::getArrayLength — Описание
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
(PHP 8 >= 8.1.0)
FFI\CType::getAttributes — Описание
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
(PHP 8 >= 8.1.0)
FFI\CType::getEnumKind — Описание
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
(PHP 8 >= 8.1.0)
FFI\CType::getFuncABI — Описание
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
(PHP 8 >= 8.1.0)
FFI\CType::getFuncParameterCount — Описание
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
(PHP 8 >= 8.1.0)
FFI\CType::getFuncParameterType — Описание
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
index
(PHP 8 >= 8.1.0)
FFI\CType::getFuncReturnType — Описание
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
(PHP 8 >= 8.1.0)
FFI\CType::getKind — Описание
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
(PHP 7 >= 7.4.0, PHP 8)
FFI\CType::getName — Описание
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
(PHP 8 >= 8.1.0)
FFI\CType::getPointerType — Описание
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
(PHP 8 >= 8.1.0)
FFI\CType::getSize — Описание
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
(PHP 8 >= 8.1.0)
FFI\CType::getStructFieldNames — Описание
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
(PHP 8 >= 8.1.0)
FFI\CType::getStructFieldOffset — Описание
$name): int
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
name
(PHP 8 >= 8.1.0)
FFI\CType::getStructFieldType — Описание
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
name
(PHP 7 >= 7.4.0, PHP 8)
(PHP 7 >= 7.4.0, PHP 8)
OPcache улучшает производительность PHP путём сохранения скомпилированного байт-кода скриптов в разделяемой памяти, тем самым избавляя PHP от необходимости загружать и анализировать скрипты при каждом запросе.
Этот модуль доступен по умолчанию с PHP 5.5.0 и » доступен в PECL для версий 5.2, 5.3 и 5.4.
Для сборки этого модуля не требуются внешние библиотеки.
OPcache можно собирать только как разделяемый модуль. Если вы запретили сборку модулей по умолчанию с помощью --disable-all, то вам будет необходимо компилировать PHP с ключом --enable-opcache для включения OPcache.
Единожды скомпилировав, вы можете использовать директиву конфигурации
zend_extension для загрузки
OPcache в PHP. Это можно сделать с помощью
zend_extension=/full/path/to/opcache.so для платформ, отличных от Windows,
и zend_extension=C:\path\to\php_opcache.dll в Windows.
Замечание:
Если вы хотите использовать OPcache с » Xdebug, то сперва нужно загружать OPcache, а потом Xdebug.
Данные опции рекомендованы для обеспечения хорошей производительности:
opcache.memory_consumption=128 opcache.interned_strings_buffer=8 opcache.max_accelerated_files=4000 opcache.revalidate_freq=60 opcache.fast_shutdown=1 ; до PHP 7.2.0 opcache.enable_cli=1
Вы также можете рассмотреть возможность отключения opcache.save_comments и включения opcache.enable_file_override. Однако обратите внимание, что вам придётся протестировать свой код, прежде чем использовать его в промышленной эксплуатации так как известны случаи, когда некоторые фреймворки и приложения переставали работать, особенно в случае использования аннотаций в комментариях.
В Windows должен быть включён параметр opcache.file_cache_fallback и opcache.file_cache должна быть установлена на уже существующий и доступный для записи каталог.
Полный список опций настройки OPcache смотрите тут.
Поведение этих функций зависит от установок в php.ini.
| Имя | По умолчанию | Место изменения | Список изменений |
|---|---|---|---|
| opcache.enable | "1" | PHP_INI_ALL | |
| opcache.enable_cli | "0" | PHP_INI_SYSTEM | В версиях с PHP 7.1.2 по 7.1.6 включительно, значение по умолчанию "1" (включено) |
| opcache.memory_consumption | "128" | PHP_INI_SYSTEM | |
| opcache.interned_strings_buffer | "8" | PHP_INI_SYSTEM | |
| opcache.max_accelerated_files | "10000" | PHP_INI_SYSTEM | |
| opcache.max_wasted_percentage | "5" | PHP_INI_SYSTEM | |
| opcache.use_cwd | "1" | PHP_INI_SYSTEM | |
| opcache.validate_timestamps | "1" | PHP_INI_ALL | |
| opcache.revalidate_freq | "2" | PHP_INI_ALL | |
| opcache.revalidate_path | "0" | PHP_INI_ALL | |
| opcache.save_comments | "1" | PHP_INI_SYSTEM | |
| opcache.fast_shutdown | "0" | PHP_INI_SYSTEM | |
| opcache.enable_file_override | "0" | PHP_INI_SYSTEM | |
| opcache.optimization_level | "0x7FFEBFFF" | PHP_INI_SYSTEM | До PHP 7.3.0 было 0x7FFFBFFF |
| opcache.inherited_hack | "1" | PHP_INI_SYSTEM | Удалено в PHP 7.3.0 |
| opcache.dups_fix | "0" | PHP_INI_ALL | |
| opcache.blacklist_filename | "" | PHP_INI_SYSTEM | |
| opcache.max_file_size | "0" | PHP_INI_SYSTEM | |
| opcache.consistency_checks | "0" | PHP_INI_ALL | |
| opcache.force_restart_timeout | "180" | PHP_INI_SYSTEM | |
| opcache.error_log | "" | PHP_INI_SYSTEM | |
| opcache.log_verbosity_level | "1" | PHP_INI_SYSTEM | |
| opcache.record_warnings | "0" | PHP_INI_SYSTEM | Доступно, начиная с PHP 8.0.0. |
| opcache.preferred_memory_model | "" | PHP_INI_SYSTEM | |
| opcache.protect_memory | "0" | PHP_INI_SYSTEM | |
| opcache.mmap_base | null |
PHP_INI_SYSTEM | |
| opcache.restrict_api | "" | PHP_INI_SYSTEM | |
| opcache.file_update_protection | "2" | PHP_INI_ALL | |
| opcache.huge_code_pages | "0" | PHP_INI_SYSTEM | |
| opcache.lockfile_path | "/tmp" | PHP_INI_SYSTEM | |
| opcache.opt_debug_level | "0" | PHP_INI_SYSTEM | Доступно с PHP 7.1.0 |
| opcache.file_cache | NULL | PHP_INI_SYSTEM | |
| opcache.file_cache_only | "0" | PHP_INI_SYSTEM | |
| opcache.file_cache_consistency_checks | "1" | PHP_INI_SYSTEM | |
| opcache.file_cache_fallback | "1" | PHP_INI_SYSTEM | |
| opcache.validate_permission | "0" | PHP_INI_SYSTEM | Доступно с PHP 7.0.14 |
| opcache.validate_root | "0" | PHP_INI_SYSTEM | Доступно с PHP 7.0.14 |
| opcache.preload | "" | PHP_INI_SYSTEM | Доступно с PHP 7.4.0 |
| opcache.preload_user | "" | PHP_INI_SYSTEM | Доступно с PHP 7.4.0 |
| opcache.cache_id | "" | PHP_INI_SYSTEM | Только в Windows. Доступно с PHP 7.4.0 |
| opcache.jit | "tracing" | PHP_INI_ALL | Доступно с PHP 8.0.0 |
| opcache.jit_buffer_size | "0" | PHP_INI_SYSTEM | Доступно с PHP 8.0.0 |
| opcache.jit_debug | "0" | PHP_INI_ALL | Доступно с PHP 8.0.0 |
| opcache.jit_bisect_limit | "0" | PHP_INI_ALL | Доступно с PHP 8.0.0 |
| opcache.jit_prof_threshold | "0.005" | PHP_INI_ALL | Доступно с PHP 8.0.0 |
| opcache.jit_max_root_traces | "1024" | PHP_INI_SYSTEM | Доступно с PHP 8.0.0 |
| opcache.jit_max_side_traces | "128" | PHP_INI_SYSTEM | Доступно с PHP 8.0.0 |
| opcache.jit_max_exit_counters | "8192" | PHP_INI_SYSTEM | Доступно с PHP 8.0.0 |
| opcache.jit_hot_loop | "64" | PHP_INI_SYSTEM | Доступно с PHP 8.0.0 |
| opcache.jit_hot_func | "127" | PHP_INI_SYSTEM | Доступно с PHP 8.0.0 |
| opcache.jit_hot_return | "8" | PHP_INI_SYSTEM | Доступно с PHP 8.0.0 |
| opcache.jit_hot_side_exit | "8" | PHP_INI_SYSTEM | Доступно с PHP 8.0.0 |
| opcache.jit_blacklist_root_trace | "16" | PHP_INI_ALL | Доступно с PHP 8.0.0 |
| opcache.jit_blacklist_side_trace | "8" | PHP_INI_ALL | Доступно с PHP 8.0.0 |
| opcache.jit_max_loop_unrolls | "8" | PHP_INI_ALL | Доступно с PHP 8.0.0 |
| opcache.jit_max_recursive_calls | "2" | PHP_INI_ALL | Доступно с PHP 8.0.0 |
| opcache.jit_max_recursive_returns | "2" | PHP_INI_ALL | Доступно с PHP 8.0.0 |
| opcache.jit_max_polymorphic_calls | "2" | PHP_INI_ALL | Доступно с PHP 8.0.0 |
Краткое разъяснение конфигурационных директив.
opcache.enable
bool
Разрешает кеширование опкодов. Если запрещено, код не будет оптимизироваться
и кешироваться. Опцию opcache.enable нельзя включить во
время исполнения с помощью ini_set(), но можно выключить.
Попытка включить её таким образом приведёт к генерации предупреждения.
opcache.enable_cli
bool
Разрешает кеширование опкодов для CLI-версии PHP.
opcache.memory_consumption
int
Размер разделяемой памяти в мегабайтах для OPcache.
Минимально допустимое значение - "8",
которое применяется, если установлено меньшее значение.
opcache.interned_strings_buffer
int
Количество памяти в мегабайтах для хранения интернированных строк.
opcache.max_accelerated_files
int
Максимальное количество ключей (и, соответственно, скриптов) в хеш-таблице
OPcache. Фактическое используемое значение будет первым числом из набора
{ 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987, 262237, 524521, 1048793 },
которое больше или равно заданному в этом параметре.
Минимум 200, максимум 1000000.
Значения за пределами этого диапазона ограничены до допустимого диапазона.
opcache.max_wasted_percentage
int
Максимальное значение потерянной памяти (в процентах) после которого планируется
перезапуск, если недостаточно свободной памяти.
Максимально допустимое значение: "50",
которое применяется, если установлено большее значение.
opcache.use_cwd
bool
Если включено, OPcache добавляет текущую рабочую директорию к ключу скрипта, тем самым устраняя возможность коллизий для файлов с одинаковым именем. Отключение этой опции повышает производительность, но может привести к сбоям.
opcache.validate_timestamps
bool
Если включено, OPcache будет проверять актуальность закешированных скриптов каждые opcache.revalidate_freq секунд. Когда запрещено, вы можете перезапустить OPcache вручную с помощью opcache_reset(), opcache_invalidate() или перезапустив веб-сервер для того, чтобы изменения вступили в силу.
Замечание: OPcache всё ещё может проверять временную метку файла, если для опций opcache.file_update_protection или opcache.max_file_size установлены ненулевые значения.
opcache.revalidate_freq
int
Как часто в секундах проверять временные метки файлов.
0 приведёт к тому, что OPcache будет производить эту проверку
при каждом запросе.
Эта директива игнорируется, если выключена opcache.validate_timestamps.
opcache.revalidate_path
bool
Если выключено, существующие закешированные файлы, использующие один и тот же include_path, будут повторно использоваться. Таким образом, если файл с тем же именем находится в другом месте в include_path, он не будет найден.
opcache.save_comments
bool
Если выключено, все комментарии будут отброшены из кеша опкодов для минимизации размера кода. Отключение этой опции может привести к тому, что некоторые фреймворки, полагающиеся на аннотации в комментариях, перестанут работать, включая Doctrine, Zend Framework 2 и PHPUnit.
opcache.fast_shutdown
bool
Если включено, то будет использована быстрая последовательность перезагрузки, при которой не происходит очистки всех выделенных блоков памяти. Вместо этого для освобождения всего набора переменных используется стандартный менеджер памяти Zend Engine.
Эта директива была удалена в PHP 7.2.0. Вариант быстрой последовательности перезагрузки был интегрирован в PHP и автоматически будет использоваться, если это возможно.
opcache.enable_file_override
bool
Если включено, то кеш опкодов будет проверять, закеширован ли уже файл при вызове функций file_exists(), is_file() и is_readable(). Это может повысить производительность для приложений, проверяющих присутствие и доступность для чтения скриптом PHP, но несёт риск возврата устаревших данных, если запрещена опция opcache.validate_timestamps.
opcache.optimization_level
int
Битовая маска, контролирующая, какие шаги оптимизации выполняются. По умолчанию применяются все безопасные оптимизации. Изменение значения по умолчанию в основном полезно для отладки/разработки оптимизатора (смотрите также opcache.opt_debug_level).
opcache.inherited_hack
bool
Эта директива игнорируется.
opcache.dups_fix
bool
Этот хак требуется только для обхода ошибок "Cannot redeclare class".
opcache.blacklist_filename
string
Местоположение чёрного списка OPcache. Файл чёрного списка содержит имена файлов, которые не нужно ускорять, по одной записи на строку. Допустимы шаблоны поиска и префиксы. Строки, начинающиеся с точки с запятой игнорируются
Пример простого чёрного списка:
; Указываем конкретный файл. /var/www/broken.php ; Префикс, обозначающий все файлы, начинающиеся с x. /var/www/x ; Шаблон поиска. /var/www/*-broken.php
opcache.max_file_size
int
Максимальный размер файла для кеширования в байтах.
Если задать 0, то кешироваться будут все файлы.
opcache.consistency_checks
int
Если не ноль, OPcache будет сверять контрольную сумму кеша каждые N запросов, где N - заданное в этой директиве значение. Рекомендуется включать только при отладке, так как сильно влияет на производительность.
opcache.force_restart_timeout
int
Количество секунд ожидания освобождения кеша, после которого будет принудительно произведён запланированный перезапуск. Если это время превышено, OPcache считает, что происходит что-то неправильное и убивает процесс, блокирующий кеш.
Если параметр opcache.log_verbosity_level задать равным 2 или больше, то, при возникновении подобной ситуации, в лог ошибок будет записано предупреждение.
Директива не поддерживается в Windows.
opcache.error_log
string
Лог ошибок OPcache. Пустая строка считается как stderr, и ошибки
будут выведены в стандартный поток ошибок (в большинстве случаев это лог
ошибок веб-сервера).
opcache.log_verbosity_level
int
Уровень подробности лога ошибок. По умолчанию будут записываться только фатальные ошибки (уровень 0) и ошибки (уровень 1). Также значения могут быть следующими: предупреждения (уровень 2), информационные сообщения (уровень 3) и сообщения отладки (уровень 4).
opcache.record_warnings
bool
Если включено, OPcache запишет предупреждения во время компиляции и воспроизведёт их при следующем включении, даже если оно выполняется из кеша.
opcache.preferred_memory_model
string
Предпочитаемая модель памяти для OPcache. Если оставить пустым, то OPcache самостоятельно выберет наиболее подходящую модель, которая будет вести себя корректно практически в любых случаях.
Возможные значения включают mmap, shm,
posix и win32.
opcache.protect_memory
bool
Защищает разделяемую память от неожиданной записи во время запуска скриптов. Полезно только для внутренней отладки.
opcache.mmap_base
string
Базовое значение для сегмента разделяемой памяти в Windows. Все процессы PHP должны отображать разделяемую память в одинаковое адресное пространство. Данная опция помогает починить ошибки типа "Unable to reattach to base address".
opcache.restrict_api
string
Позволяет вызывать функции API OPcache только скриптам, чей путь начинается с указанной строки. Значение по умолчанию "" означает отсутствие ограничений.
opcache.file_update_protection
string
Предотвращает кеширование файлов младше указанного количества секунд. Это помогает предотвратить кеширование не до конца обновлённых файлов. В случае, если у вас все обновления файлов атомарны, можно повысить производительность, задав этот параметр равным "0".
opcache.huge_code_pages
bool
Включает или отключает копирование кода PHP (текстового сегмента) в HUGE PAGES. Это может повысить производительность, но требует соответствующих системных настроек. Доступно в Linux начиная с PHP 7.0.0 и FreeBSD начиная с PHP 7.4.0.
opcache.lockfile_path
string
Абсолютный путь к хранилищу общих файлов блокировок (только *nix)
opcache.opt_debug_level
string
Производит вывод опкодов для отладки разных этапов оптимизации. 0x10000 приведёт к выводу опкодов как только они сгенерированы компилятором, до применения какой-либо оптимизации. 0x20000 приведёт к выводу опкодов после оптимизации.
opcache.file_cache
string
Разрешает и задаёт директорию кеша второго уровня. Это должно повысить производительность в случае, если память SHM заполнена, сервер перезапущен или SHM сброшена. Значение по умолчанию "" запрещает кеширование на файловой системе.
opcache.file_cache_only
bool
Включает или выключает кеширование опкодов в разделяемой памяти.
Замечание:
До PHP 8.1.0 отключение этой директивы с уже заполненным файловым кешем требовало ручной очистки файлового кеша.
opcache.file_cache_consistency_checks
bool
Включает или выключает проверку контрольной суммы при загрузке скрипта из файлового кеша.
opcache.file_cache_fallback
bool
Применяет opcache.file_cache_only=1 для некоторых процессов, которые завершились ошибкой при переподключении к разделяемой памяти (только для Windows). Требуется явно разрешённое кеширование на файловую систему.
Отключение этой опции конфигурации может помешать запуску процессов, и поэтому не рекомендуется.
opcache.validate_permission
bool
Проверяет права доступа к кешированному файлу для текущего пользователя.
opcache.validate_root
bool
Предотвращает коллизии имён в chroot-окружении. Должно быть включено для всех случаев использования chroot-окружений для предотвращения доступа к файлам за пределами chroot.
opcache.preload
string
Задаёт скрипт PHP, который будет скомпилирован и запущен при старте сервера и сможет предзагрузить другие файлы, либо с помощью include, либо используя функцию opcache_compile_file(). Все сущности (например функции и классы), определённые в этих файлах, автоматически будут доступны до момента выключения сервера.
Замечание:
Предварительная загрузка не поддерживается в Windows.
opcache.preload_user
string
Позволяет запускать предварительную загрузку от имени указанного пользователя системы.
Полезно для серверов, которые запускаются от имени root перед переключением на непривилегированного пользователя системы.
По умолчанию предварительная загрузка от имени root запрещена по соображениям безопасности,
если только этой директиве явно не установлено значение root.
opcache.cache_id
string
В Windows все процессы, выполняющие один и тот же PHP SAPI под одной и той же учётной записью пользователя с одинаковым идентификатором кеша, совместно используют один экземпляр OPcache. Значение идентификатора кеша может быть свободно выбрано.
Для IIS разные пулы приложений могут иметь собственный экземпляр OPcache,
используя переменную среды APP_POOL_ID как
opcache.cache_id.
opcache.jit
string|int
Для обычного использования параметр принимает одно из четырёх строковых значений:
disable: Полностью отключён, не может быть включён во время выполнения.off: Отключено, но может быть включено во время выполнения.tracing/on: Используйте трассировку JIT.
Включено по умолчанию и рекомендуется для большинства пользователей.
function: Используйте функцию JIT.
Для расширенного использования параметр принимает 4-значное целое число CRTO, где цифры означают:
C (Флаги оптимизации для процессора)0: Отключить оптимизацию для ЦП.1: Включите использование AVX, если ЦП поддерживает его.R (распределение регистров)0: Не выполнять распределение регистров.1: Выполнять выделение локального блочного регистра.2: Выполнять выделение глобального регистра.T (триггер)0: Компиляция всех функций при загрузке скрипта.1: Компиляция функций при первом выполнении.2: Профилирование функций при первом запросе и затем компилирование самых популярных функций.
3: Профилирование на лету и компиляция горячих функций.4: В настоящее время не используется.5: Использование трассировки JIT. Профилирование на лету и компиляция трассировки для горячих сегментов кода.
O (уровень оптимизации)0: Без JIT.1: Минимальный JIT (вызов стандартных обработчиков виртуальных машин).2: Встроенные обработчики виртуальных машин.3: Использовать вывод типа.4: Использовать график вызовов.5: Оптимизировать весь скрипт."tracing" соответствует CRTO = 1254,
Режим "function" соответствует CRTO = 1205.
opcache.jit_buffer_size
int
Объем разделяемой памяти, резервируемый для скомпилированного JIT-кода. Нулевое значение отключает JIT.
Если используется int, значение измеряется байтами. Вы также можете использовать сокращённую запись, которая описана в этом разделе FAQ.opcache.jit_debug
int
Битовая маска, определяющая, какой вывод отладки JIT следует включить.
Возможные значения смотрите в файле » zend_jit.h
(поиск макроопределений, начинающихся с ZEND_JIT_DEBUG).
opcache.jit_bisect_limit
int
Опция отладки, отключающая JIT-компиляцию после компиляции определённого количества функций.
Может быть полезно для разделения источника неправильной компиляции JIT.
Примечание: этот параметр работает, только если для триггера JIT установлено значение 0 (компиляция при загрузке скрипта)
или 1 (компиляция при первом выполнении), например, opcache.jit=1215.
Подробнее смотрите в разделе opcache.jit.
opcache.jit_prof_threshold
float
При использовании режима триггера "профилирование функций при первом запросе" этот порог определяет, считается ли функция горячей. Количество вызовов функции, разделённое на количество вызовов всех функций, должно быть выше порогового значения. Например, порог 0,005 означает, что функции, составляющие более 0,5% всех вызовов, будут скомпилированы JIT.
opcache.jit_max_root_traces
int
Максимальное количество корневых стеков вызова. Корневой стек вызова - это поток выполнения, проходящий по коду сначала по одному пути, что является единицей компиляции JIT. JIT не будет компилировать новый код, если он достигнет этого предела.
opcache.jit_max_side_traces
int
Максимальное количество боковых стеков вызова, которые может иметь корневой стек. Боковой стек вызова - это другой поток выполнения, который не следует по пути скомпилированного корневого стека вызова. Боковые стеки вызова, принадлежащие одному и тому же корневому стеку вызова, не будут компилироваться, если они достигают этого предела.
opcache.jit_max_exit_counters
int
Максимальное количество счётчиков выхода бокового стека вызова. Это ограничивает общее количество боковых стеков, которые могут быть во всех корневых стеках.
opcache.jit_hot_loop
int
Через сколько итераций цикл считается горячим.
Допустимый диапазон значений: [0,255]; для любого значения вне этого диапазона,
например, -1 или 256, будет использоваться значение по умолчанию.
В частности, нулевое значение отключит JIT для отслеживания и компиляции любых циклов.
opcache.jit_hot_func
int
Через сколько вызовов функция считается горячей.
Допустимый диапазон значений: [0,255]; для любого значения вне этого диапазона,
например, -1 или 256, будет использоваться значение по умолчанию.
В частности, нулевое значение отключит JIT для отслеживания и компиляции любых функций.
opcache.jit_hot_return
int
Через сколько возвратов возврат считается горячим.
Допустимый диапазон значений: [0,255]; для любого значения вне этого диапазона,
например, -1 или 256, будет использоваться значение по умолчанию.
В частности, нулевое значение отключит JIT для отслеживания и компиляции любых возвратов.
opcache.jit_hot_side_exit
int
Через сколько выходов боковой стек считается горячим.
Допустимый диапазон значений: [0,255]; для любого значения вне этого диапазона,
например, -1 или 256, будет использоваться значение по умолчанию.
В частности, нулевое значение отключит JIT для отслеживания и компиляции любых побочных выходов.
opcache.jit_blacklist_root_trace
int
Максимальное количество попыток компиляции корневой трассировки, прежде чем она будет занесена в чёрный список.
opcache.jit_blacklist_side_trace
int
Максимальное количество попыток компиляции боковой трассировки до того, как она будет занесена в чёрный список.
opcache.jit_max_loop_unrolls
int
Максимальное количество попыток развернуть цикл в боковой трассировке, пытаясь достичь корневой трассировки и закрыть внешний цикл.
opcache.jit_max_recursive_calls
int
Максимальное количество развёрнутых рекурсивных циклов вызова.
opcache.jit_max_recursive_returns
int
Максимальное количество развёрнутых рекурсивных циклов возврата.
opcache.jit_max_polymorphic_calls
int
Максимальное количество попыток встроенных полиморфных (динамических или методических) вызовов. Вызовы выше этого лимита обрабатываются как метаморфические и не встраиваются.
Данный модуль не определяет каких-либо типов ресурсов.
Начиная с PHP 7.4.0, можно настроить предзагрузку скриптов в opcache в момент старта PHP. Любые функции, классы, интерфейсы или трейты (но не константы) в этих файлах будут глобально доступны для всех запросов без необходимости их явной загрузки. Такая предзагрузка позволяет добиться больших удобства и производительности (потому, что код всегда доступен) за счёт использования большего количества памяти. Также, при внесении изменений в предзагруженные скрипты, чтобы эти изменения стали доступны, придётся перезагрузить PHP. Из этого следует, что предзагрузку имеет смысл использовать только в промышленном окружении, но не в разработческом.
Обратите внимание, что баланс повышения производительности и потребления памяти сильно зависит от вашего приложения. "Предзагрузка всего на свете" может быть простейшей стратегией, но совсем не обязательно лучшей. Также, предзагрузка будет работать только в случае, когда PHP работает в режиме обслуживания запросов без перезагрузки. Таким образом, хоть предзагрузку и можно использовать в режиме CLI с включённым opcache, но, в большинстве случаев бессмысленно. Исключением является использование предзагрузки с библиотеками FFI.
Замечание:
Предзагрузка не поддерживается в Windows.
Настройка предзагрузки состоит из двух этапов и требует включённого opcache. Для начала, настройте opcache.preload в php.ini:
opcache.preload=preload.php
preload.php - это обязательный файл, который будет запущен один раз при старте сервера
(PHP-FPM, mod_php, etc.) и который загрузит код в постоянную память. В серверах, которые запускаются от имени root
перед переключением на непривилегированного пользователя системы или если PHP запускается от имени root (не рекомендуется),
значение opcache.preload_user может указывать системного пользователя
для запуска предварительной загрузки.
Запуск предварительной загрузки от имени root по умолчанию запрещён.
Установите opcache.preload_user=root, чтобы явно разрешить это.
В скрипте preload.php, любой файл указанный в include,
include_once, require, require_once или
opcache_compile_file() будет загружен в постоянную память. В следующем примере,
будут загружены все файлы .php в директории src, если они не содержат
Test в имени.
<?php
$directory = new RecursiveDirectoryIterator(__DIR__ . '/src');
$fullTree = new RecursiveIteratorIterator($directory);
$phpFiles = new RegexIterator($fullTree, '/.+((?<!Test)+\.php$)/i', RecursiveRegexIterator::GET_MATCH);
foreach ($phpFiles as $key => $file) {
require_once($file[0]);
}
?>И include и opcache_compile_file() будут работать, но при этом будут немного по разному обработаны.
A и b.php определяет класс
B, который является наследником A, то opcache_compile_file() может
загрузить эти два файла в любом порядке. При использовании include, с другой стороны, a.php
должен быть загружен первым.(PHP 5 >= 5.5.5, PHP 7, PHP 8, PECL ZendOpcache > 7.0.2)
opcache_compile_file — Скомпилировать и закешировать, но не исполнять скрипт PHP
$filename): boolЭта функция компилирует PHP-скрипт и помещает его в кеш опкодов, но не запускает его. Можно использовать для прогрева кеша после перезапуска веб-сервера.
filenameПуть к скрипту PHP.
Возвращает true, если filename успешно скомпилирован или false в случае возникновения ошибки.
Если filename не может быть загружен или скомпилирован,
будет выдана ошибка уровня E_WARNING. Для подавления
предупреждения можно использовать @.
(PHP 5 >= 5.5.0, PHP 7, PHP 8, PECL ZendOpcache > 7.0.2)
opcache_get_configuration — Получить конфигурационную информацию кеша
Эта функция возвращает настройки конфигурации экземпляра кеша.
У этой функции нет параметров.
Возвращает массив с информацией, включая INI-настройки, чёрный список и версию
Если используется opcache.restrict_api и текущий путь подпадает под
запрет, то будет вызвана ошибка уровня E_WARNING и никаких данных возвращено
не будет.
(PHP 5 >= 5.5.0, PHP 7, PHP 8, PECL ZendOpcache > 7.0.2)
opcache_get_status — Получить информацию о состоянии кеша
$include_scripts = true): array|falseФункция возвращает информацию о состоянии экземпляра кеша в памяти. Она не возвращает никакой информации о файловом кеше.
include_scriptsВключить информацию о состоянии конкретного скрипта.
Возвращает массив, опционально содержащий информацию о состоянии конкретного скрипта или false в случае возникновения ошибки.
Если используется opcache.restrict_api и текущий путь подпадает под
запрет, то будет вызвана ошибка уровня E_WARNING и никаких данных возвращено
не будет.
(PHP 5 >= 5.5.0, PHP 7, PHP 8, PECL ZendOpcache >= 7.0.0)
opcache_invalidate — Аннулирует закешированный скрипт
$filename, bool $force = false): bool
Функция аннулирует закешированный скрипт. Если параметр
force не задан или задан как false, скрипт
аннулируется, только если скрипт был модифицирован после помещения в кеш.
Функция аннулирует только кеш в памяти, не затрагивая файловый кеш.
filenameПуть к скрипту.
force
Если установлено как true, кеш скрипта будет принудительно аннулирован независимо от того,
требуется ли это или нет
Возвращает true, если кеш опкодов для filename
аннулирован, либо если аннулировать нечего. В случае, если кеш опкодов
отключён, возвращается false.
(PHP 5 >= 5.5.11, PHP 7, PHP 8, PECL ZendOpcache >= 7.0.4)
opcache_is_script_cached — Проверяет, закеширован ли скрипт в OPCache
$filename): boolФункция проверяет, закеширован ли указанный скрипт в OPCache. Может быть использована для определения, прогрет ли кеш для конкретного скрипта. Функция проверяет только кеш в памяти, не проверяя файловый кеш.
filenameПуть к файлу скрипта.
Возвращает true, если filename закеширован в OPCache,
false если нет.
(PHP 5 >= 5.5.0, PHP 7, PHP 8, PECL ZendOpcache >= 7.0.0)
opcache_reset — Сбрасывает содержимое кеша опкодов
Функция сбрасывает весь кеш. После вызова opcache_reset() все скрипты будут заново загружены, скомпилированы и помещены в кеш после их следующего вызова. Функция сбрасывает только кеш в памяти, не затрагивая файловый кеш.
У этой функции нет параметров.
Возвращает true, если кеш опкодов был сброшен
или false, если кеш отключён, ожидается перезапуск или перезапуск выполняется
(смотрите opcache_get_status()).
Функции управления выводом позволяют вам контролировать вывод, отправляемый скриптом. Это может быть полезно в различных ситуациях, особенно если вам необходимо отправить заголовки в браузер после того, как ваш скрипт уже начал выводить данные. Функции управления выводом не влияют на заголовки, отправленные с помощью функций header() или setcookie(), а влияют только на такие функции, как echo и данные между блоками PHP-кода.
Для сборки этого модуля не требуются внешние библиотеки.
Для использования этих функций не требуется проведение установки, поскольку они являются частью ядра PHP.
Поведение этих функций зависит от установок в php.ini.
| Имя | По умолчанию | Место изменения | Список изменений |
|---|---|---|---|
| output_buffering | "0" | PHP_INI_PERDIR | |
| output_handler | NULL | PHP_INI_PERDIR | |
| implicit_flush | "0" | PHP_INI_ALL | |
| url_rewriter.tags | "a=href,area=href,frame=src,form=,fieldset=" | PHP_INI_ALL | До PHP 7.1.0 использовалась для установки перезаписи сессии "trans sid". С PHP 7.1.0 используется только output_add_rewrite_var(). |
| url_rewriter.hosts | $_SERVER['HTTP_HOST'] используется по умолчанию. |
PHP_INI_ALL | Доступно с PHP 7.1.0 |
Краткое разъяснение конфигурационных директив.
output_buffering
bool/integer
Вы можете разрешить буферизацию вывода для всех файлов, установив эту директиву в 'On'. Если вы хотите ограничить размер буфера до определённого размера, вы можете установить не 'On', а максимальное количество байт в этой директиве (например, output_buffering=4096). Эта директива всегда отключена в PHP-CLI.
output_handler
string
Вы можете перенаправить весь вывод вашего скрипта в функцию. Для примера, если вы установите output_handler в mb_output_handler(), то кодировка символов прозрачно преобразуется в соответствии с указанной кодировкой. Настройка любого обработчика вывода автоматически включает буферизацию вывода.
Замечание:
Вы не можете использовать вместе mb_output_handler() с ob_iconv_handler(), и вы не можете использовать вместе ob_gzhandler() и zlib.output_compression.
Замечание:
Только встроенные функции могут использоваться с этой директивой. Для функции, определённой пользователем, используйте ob_start().
implicit_flush
bool
false по умолчанию. Изменение значения на true указывает PHP не сохранять
данные в буфер, а после каждого отправленного блока автоматически
отправлять данные в выходной слой. Это эквивалентно вызову PHP-функции
flush() после каждого вызова
print или echo для
каждого HTML-блока.
При использовании PHP в веб-среде, включение этой опции
приведёт к серьёзной потере производительности, поэтому
рекомендуется использовать её только для отладки. Это значение
по умолчанию имеет true при работе в CLI SAPI.
Сморите также ob_implicit_flush().
url_rewriter.tags определяет, какие HTML-теги
будут перезаписаны значениями output_add_rewrite_var().
По умолчанию
a=href,area=href,frame=src,input=src,form=
form является специальным тегом. <input hidden="session_id" name="session_name"> добавляется как переменная формы.
Замечание: До PHP 7.1.0 надо было использовать url_rewriter.tags для указания session.trans_sid_tags. Начиная с PHP 7.1.0,
fieldsetбольше не рассматривается как специальный тег.
url_rewriter.hosts
string
url_rewriter.hosts указывает, какие хосты перезаписываются для включения
значений output_add_rewrite_var().
По умолчанию используется $_SERVER['HTTP_HOST']. Несколько хостов можно указать
перечислив их через запятую, между хостами не должно быть пробелов. То есть
php.net,wiki.php.net,bugs.php.net
Данный модуль не определяет каких-либо типов ресурсов.
Перечисленные ниже константы всегда доступны как часть ядра PHP.
PHP_OUTPUT_HANDLER_START
(int)
Служит признаком того, что буферирование вывода началось.
PHP_OUTPUT_HANDLER_WRITE
(int)
Служит признаком того, что буфер вывода очищается и в нем находятся данные для вывода.
PHP_OUTPUT_HANDLER_FLUSH
(int)
Обозначает, что буфер был сброшен (очищен и выведен).
PHP_OUTPUT_HANDLER_CLEAN
(int)
Обозначает, что буфер был очищен.
PHP_OUTPUT_HANDLER_FINAL
(int)
Обозначает, что это последняя операция буферирования.
PHP_OUTPUT_HANDLER_CONT
(int)
Обозначает, что буфер был очищен, но буферирование вывода будет продолжено.
Это синоним для
PHP_OUTPUT_HANDLER_WRITE.
PHP_OUTPUT_HANDLER_END
(int)
Обозначает, что буферирование вывода завершено.
Это синоним для
PHP_OUTPUT_HANDLER_FINAL.
PHP_OUTPUT_HANDLER_CLEANABLE
(int)
Определяет может ли буфер вывода, созданный ob_start(), быть очищенным.
PHP_OUTPUT_HANDLER_FLUSHABLE
(int)
Определяет может ли буфер вывода, созданный ob_start(), быть сброшен (выведен и очищен).
PHP_OUTPUT_HANDLER_REMOVABLE
(int)
Определяет может ли буфер вывода, созданный ob_start(), быть удалённым до завершения скрипта.
PHP_OUTPUT_HANDLER_STDFLAGS
(int)
Значение по умолчанию для флагов буфера вывода. Равняется
PHP_OUTPUT_HANDLER_CLEANABLE |
PHP_OUTPUT_HANDLER_FLUSHABLE |
PHP_OUTPUT_HANDLER_REMOVABLE.
Пример #1 Пример контроля вывода
<?php
ob_start();
echo "Привет\n";
setcookie("cookiename", "cookiedata");
ob_end_flush();
?>В приведённом выше примере вывод из echo будет храниться в буфере вывода до вызова ob_end_flush(). В то же время вызов setcookie() успешно сохранится в cookie браузера, не вызывая ошибки (заголовки не могут быть отправлены в браузер после того, как данные уже были отправлены).
Начиная с PHP 7.1.0, output_add_rewrite_var() и output_reset_rewrite_vars() используют отдельный буфер вывода, то есть не используют буфер вывода прозрачной поддержки sid.
Пример #1 Пример перезаписи вывода
<?php
// Этот код работает с PHP 7.1.0, 7.0.10, 5.6.25 и выше.
// HTTP_HOST - целевой хост по умолчанию. Зададим сами, чтобы код примера заработал.
$_SERVER['HTTP_HOST'] = 'php.net';
// Перезаписыватель вывода перезаписывает только "form". Добавим a=href.
// Теги должны указываться как tag_name=url_attr, то есть img=src,iframe=src
// Между настройками пробелы недопустимы.
// Тег "form" - специальный тег, в который добавляется скрытый "input"
ini_set('url_rewriter.tags','a=href,form=');
var_dump(ini_get('url_rewriter.tags'));
// Это добавлено в URL и "form"
output_add_rewrite_var('test', 'value');
?>
<a href="//php.net/index.php?bug=1234">bug1234</a>
<form action="https://php.net/?bug=1234&edit=1" action="post">
<input type="text" name="title" />
</form>Результат выполнения данного примера:
<a href="//php.net/?bug=1234&test=value">bug1234</a> <form action="https://php.net/?bug=1234&edit=1" method="post"><input type="hidden" name="test" value="value" /> <input type="text" name="title" /> </form>
С PHP 7.1.0, функции перезаписи вывода имеют свои собственные INI-настройки. url_rewriter.tags и url_rewriter.hosts.
Смотрите также header() и setcookie().
(PHP 4, PHP 5, PHP 7, PHP 8)
flush — Сброс системного буфера вывода
Функция очищает системный буфер вывода PHP, при этом всё содержимое буфера отправляется в браузер пользователя (с некоторыми исключениями), независимо от используемого бекенда PHP (CGI, веб-сервер и т.д.).
flush() не сможет переопределить схему буферизации вашего веб-сервера и никак не влияет на буферизацию браузера на стороне клиента. Функция также не влияет на механизм буферизации пользовательского PHP-кода. Это означает, что ob_flush() должен быть вызван перед flush(), чтобы очистить выходные буферы, если они используются.
Некоторые серверы, особенно под управлением Win32, будут по-прежнему продолжать буферизировать вывод вашего скрипта до передачи результатов в браузер.
Серверные модули для Apache, такие как mod_gzip, могут сами выполнять буферизацию, поэтому flush() не приводит к немедленной передаче данных клиенту.
Браузер может также буферизировать поступающие к нему данные перед отображением. Например, Netscape, буферизирует текст до тех пор, пока не получит конец строки или начало тега, и не будет отображать таблицы пока не будет замечен тег </table> самой внешней таблицы.
Некоторые версии Microsoft Internet Explorer начинают отображать страницу только после получения 256 байт вывода, поэтому может понадобиться отправить дополнительные пробелы перед сбросом, чтобы такие браузеры отобразили страницу.
У этой функции нет параметров.
Функция не возвращает значения после выполнения.
(PHP 4 >= 4.2.0, PHP 5, PHP 7, PHP 8)
ob_clean — Очистить (стереть) буфер вывода
Эта функция очищает содержимое выходного буфера, не отправляя его в браузер.
Эта функция не уничтожает буфер вывода, как это делает ob_end_clean().
Буфер вывода должен запускаться функцией ob_start() с флагом PHP_OUTPUT_HANDLER_CLEANABLE. Иначе ob_clean() не сработает.
У этой функции нет параметров.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PHP 4, PHP 5, PHP 7, PHP 8)
ob_end_clean — Очистить (стереть) буфер вывода и отключить буферизацию вывода
Эта функция удаляет содержимое самого верхнего буфера вывода и отключает эту буферизацию. Если вы хотите использовать содержимое буфера, то вам необходимо вызвать ob_get_contents() перед ob_end_clean(), так как все содержимое буфера удаляется при вызове ob_end_clean().
Буфер вывода должен запускаться функцией ob_start() с флагами PHP_OUTPUT_HANDLER_CLEANABLE и PHP_OUTPUT_HANDLER_REMOVABLE. Иначе не сработает ob_end_clean().
У этой функции нет параметров.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки. Основной причиной неудачного завершения работы функции
является её вызов без активного буфера или если буфер не может
быть удалён (специальный тип буфера).
Если функция завершается ошибкой, генерируется E_NOTICE.
Следующий пример показывает простой способ избавиться от всех выходных буферов:
Пример #1 Пример использования функции ob_end_clean()
<?php
ob_start();
echo 'Текст, который не отобразится.';
ob_end_clean();
?>
(PHP 4, PHP 5, PHP 7, PHP 8)
ob_end_flush — Сбросить (отправить) буфер вывод и отключить буферизацию вывода
Эта функция отправит содержимое самого верхнего буфера вывода (если оно имеется) и отключит этот буфер вывода. Если вы хотите использовать содержимое буфера, то вам необходимо вызвать ob_get_contents() перед ob_end_flush(), т.к. все содержимое буфера удаляется при вызове ob_end_flush().
Буфер вывода должен запускаться функцией ob_start() с флагами PHP_OUTPUT_HANDLER_FLUSHABLE и PHP_OUTPUT_HANDLER_REMOVABLE.
Замечание: Эта функция аналогична ob_get_flush(), за исключением того, что ob_get_flush() возвращает содержимое буфера в виде строки.
У этой функции нет параметров.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки. Основной причиной неудачного завершения работы функции
является её вызов без активного буфера или если буфер не может
быть удалён (специальный тип буфера).
Если функция завершается ошибкой, генерируется E_NOTICE.
Пример #1 Пример использования функции ob_end_flush()
Следующий пример показывает простой способ сброса и завершения всех буферов вывода:
<?php
while (@ob_end_flush());
?>
(PHP 4 >= 4.2.0, PHP 5, PHP 7, PHP 8)
ob_flush — Сбросить (отправить) буфер вывода
Эта функция отправит содержимое буфера вывода (если имеется). Если необходима дальнейшая обработка буфера вывода, то следует вызвать ob_get_contents() перед ob_flush(), так как содержимое буфера будет удалено после вызова ob_flush().
Эта функция не уничтожает буфер вывода, как это делает ob_end_flush().
У этой функции нет параметров.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)
ob_get_clean — Получить содержимое текущего буфера и удалить его
Получает содержимое текущего буфера и затем удаляет текущий буфер.
ob_get_clean() по сути выполняет ob_get_contents() и ob_end_clean().
Буфер вывода должен запускаться функцией ob_start() с флагами PHP_OUTPUT_HANDLER_CLEANABLE и PHP_OUTPUT_HANDLER_REMOVABLE. Иначе ob_get_clean() не сработает.
У этой функции нет параметров.
Возвращает содержимое буфера вывода и заканчивает буферизацию вывода.
Если буферизация вывода не активирована, то функция вернёт false.
Пример #1 Простой пример использования функции ob_get_clean()
<?php
ob_start();
echo "Привет мир";
$out = ob_get_clean();
$out = strtolower($out);
var_dump($out);
?>Результат выполнения данного примера:
string(11) "привет мир"
(PHP 4, PHP 5, PHP 7, PHP 8)
ob_get_contents — Возвращает содержимое буфера вывода
Получает содержимое буфера без его очистки.
У этой функции нет параметров.
Функция вернёт содержимое буфера вывода или false, если буферизация
вывода не активирована.
Пример #1 Простой пример использования функции ob_get_contents()
<?php
ob_start();
echo "Привет ";
$out1 = ob_get_contents();
echo "Мир";
$out2 = ob_get_contents();
ob_end_clean();
var_dump($out1, $out2);
?>Результат выполнения данного примера:
string(6) "Привет " string(11) "Привет Мир"
(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)
ob_get_flush — Сбросить буфер вывода, вернуть его в виде строки и отключить буферизацию вывода
ob_get_flush() сбрасывает буфер вывода, возвращая его содержимое в виде строки и отключает буферизацию вывода.
Буфер вывода должен запускаться функцией ob_start() с флагом PHP_OUTPUT_HANDLER_FLUSHABLE. Иначе не сработает ob_get_flush().
Замечание: Эта функция аналогична ob_end_flush() за исключением того, что эта функция также возвращает буфер в виде строки.
У этой функции нет параметров.
Возвращает буфер вывода или false, если буферизация не активна.
Пример #1 Пример использования функции ob_get_flush()
<?php
//Используется output_buffering=On
print_r(ob_list_handlers());
//сохранить буфер в файл
$buffer = ob_get_flush();
file_put_contents('buffer.txt', $buffer);
print_r(ob_list_handlers());
?>Результат выполнения данного примера:
Array
(
[0] => default output handler
)
Array
(
)
(PHP 4 >= 4.0.2, PHP 5, PHP 7, PHP 8)
ob_get_length — Возвращает размер буфера вывода
Вернёт размер в байтах содержимого в буфере вывода.
У этой функции нет параметров.
Возвращает размер в байтах содержимого буфера вывода или false, если
буферизация не активна.
Пример #1 Простой пример использования функции ob_get_length()
<?php
ob_start();
echo "Привет ";
$len1 = ob_get_length();
echo "Мир";
$len2 = ob_get_length();
ob_end_clean();
echo $len1 . ", " . $len2;
?>Результат выполнения данного примера:
13, 19
(PHP 4 >= 4.2.0, PHP 5, PHP 7, PHP 8)
ob_get_level — Возвращает уровень вложенности механизма буферизации вывода
Вернёт уровень вложенности механизма буферизации вывода.
У этой функции нет параметров.
Возвращает уровень вложенности обработчиков буферизации вывода или 0, если буферизация не активна.
(PHP 4 >= 4.2.0, PHP 5, PHP 7, PHP 8)
ob_get_status — Получить статус буфера вывода
$full_status = false): array
ob_get_status() возвращает информацию о состоянии буфера верхнего уровня
или на всех уровнях активных буферов, если full_status установлен в true.
full_status
Если true, то вернёт все уровни активных буферов. Если false или
не установлен, то вернёт статус только самого верхнего уровня.
Если функция вызвана без параметра full_status
или full_status = false, то возвращается
простой массив из следующих элементов:
Array
(
[level] => 2
[type] => 0
[status] => 0
[name] => URL-Rewriter
[del] => 1
)
| Ключ | Значение |
|---|---|
| level | Уровень вложенности вывода |
| type | PHP_OUTPUT_HANDLER_INTERNAL (0) или PHP_OUTPUT_HANDLER_USER (1) |
| type | 0 (внутренний обработчик) или 1 (предоставленный пользователем обработчик) |
| name | Название действующего обработчика вывода или 'default output handler', если не задан |
| del | Флаг очистки, установленный ob_start() |
Если функция вызвана с full_status = true,
то возвращается массив из элементов уровней активных буферов. В качестве
ключа используется уровень вывода, и каждый элемент массива содержит в
себе массив информации о статусе одного из активных элементов вывода.
Array
(
[0] => Array
(
[chunk_size] => 0
[size] => 40960
[block_size] => 10240
[type] => 1
[status] => 0
[name] => default output handler
[del] => 1
)
[1] => Array
(
[chunk_size] => 0
[size] => 40960
[block_size] => 10240
[type] => 0
[buffer_size] => 0
[status] => 0
[name] => URL-Rewriter
[del] => 1
)
)
Полный вывод содержит следующие дополнительные элементы:
| Ключ | Значение |
|---|---|
| chunk_size | Размер порции, установленный ob_start() |
| size | ... |
| blocksize | ... |
(PHP 4 >= 4.0.4, PHP 5, PHP 7, PHP 8)
ob_gzhandler — callback-функция, используемая для gzip-сжатия буфера вывода при вызове ob_start
$data, int $flags): string|false
Функция ob_gzhandler() предназначена для использования в
качестве callback-функции для ob_start(), чтобы
облегчить отправку gz-кодированных данных браузерам, поддерживающим
сжатие веб-страниц. Прежде чем ob_gzhandler()
отправит сжатые данные, она определяет, какой тип кодирования
содержимого сможет принять браузер ("gzip", "deflate" или вообще никакой)
и вернёт его содержимое соответствующим образом. Поддерживаются все
браузеры, отправляющие корректные заголовки о том, что они принимают
сжатые веб-страницы. Если браузер не поддерживает сжатие страниц, эта функция
вернёт false.
data
flags
Пример #1 Пример использования функции ob_gzhandler()
<?php
ob_start("ob_gzhandler");
?>
<html>
<body>
<p>Это должно быть сжатой страницей.</p>
</body>
</html>Замечание:
ob_gzhandler() требует наличие модуля zlib.
Замечание:
Вы не можете использовать одновременно ob_gzhandler() и zlib.output_compression. Также обратите внимание, что использование zlib.output_compression предпочтительнее, чем ob_gzhandler().
(PHP 4, PHP 5, PHP 7, PHP 8)
ob_implicit_flush — Включение/выключение неявного сброса
$enable = true): voidob_implicit_flush() включает или выключает неявный сброс. Неявный сброс приводит к тому, что операция сброса выполняется после каждого вывода, поэтому явные вызовы функции flush() больше не понадобятся.
enable
true для включения неявного сброса, false в противном случае.
Функция не возвращает значения после выполнения.
| Версия | Описание |
|---|---|
| 8.0.0 |
enable теперь принимает логическое значение (bool);
ранее принималось целое число (int).
|
(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)
ob_list_handlers — Список всех используемых обработчиков вывода
Список всех используемых обработчиков вывода.
У этой функции нет параметров.
Функция вернёт массив с используемыми обработчиками вывода (если имеются). Если включён output_buffering или использовалась анонимная функция вместе с ob_start(), то ob_list_handlers() вернёт "default output handler".
Пример #1 Пример использования функции ob_list_handlers()
<?php
//используется output_buffering=On
print_r(ob_list_handlers());
ob_end_flush();
ob_start("ob_gzhandler");
print_r(ob_list_handlers());
ob_end_flush();
// анонимная функция
ob_start(function($string) { return $string; });
print_r(ob_list_handlers());
ob_end_flush();
?>Результат выполнения данного примера:
Array
(
[0] => default output handler
)
Array
(
[0] => ob_gzhandler
)
Array
(
[0] => Closure::__invoke
)
(PHP 4, PHP 5, PHP 7, PHP 8)
ob_start — Включение буферизации вывода
$callback = null, int $chunk_size = 0, int $flags = PHP_OUTPUT_HANDLER_STDFLAGS): boolЭта функция включает буферизацию вывода. Если буферизация вывода активна, никакой вывод скрипта не отправляется (кроме заголовков), а сохраняется во внутреннем буфере.
Содержимое этого внутреннего буфера может быть скопировано в строковую переменную, используя ob_get_contents(). Для вывода содержимого внутреннего буфера следует использовать ob_end_flush(). В качестве альтернативы можно использовать ob_end_clean() для очистки содержимого буфера.
Некоторые веб-серверы (например, Apache) изменяют рабочую директорию скрипта
при вызове callback-функции. Вы можете вернуть её назад, используя
chdir(dirname($_SERVER['SCRIPT_FILENAME']))
в callback-функции.
Буферы вывода помещаются в стек, то есть допускается вызов ob_start() после вызова другой активной ob_start(). При этом необходимо вызывать ob_end_flush() соответствующее количество раз. Если активны несколько callback-функций, вывод последовательно фильтруется для каждой из них в порядке вложения.
Если буферизация вывода всё ещё активна, когда скрипт завершает работу, PHP автоматически выводит содержимое.
callback
Можно задать необязательный параметр callback.
Эта функция принимает строку в виде аргумента и должна также вернуть строку.
Она вызывается при сбросе (отправке) или очистке (с помощью
ob_flush(), ob_clean() или подобных функций)
или если буфер вывода сбрасывается в браузер по окончанию запроса.
При вызове функции callback, она получает
содержимое буфера и, как ожидается, должна вернуть обновлённое содержимое для буфера вывода,
которое будет отправлено браузеру.
Если callback не является допустимой функцией, то
эта функция вернёт false.
Описание функции для этого параметра:
$buffer, int $phase = ?): stringbufferphasePHP_OUTPUT_HANDLER_*.
Если callback вернёт false, то
оригинальная информация отправится в браузер без изменений.
Параметр callback может быть игнорирован
передачей значения null.
ob_end_clean(), ob_end_flush(),
ob_clean(), ob_flush() и
ob_start() не могут вызываться из callback-функций,
так как их поведение непредсказуемо.
Если вы хотите удалить содержимое буфера, то
верните "" (пустую строку) из callback-функции.
Вы также не можете использовать функции буферизации вывода, такие как
print_r($expression, true) или
highlight_file($filename, true)
из callback-функции.
Замечание:
Функция ob_gzhandler() была введена для облегчения отправки gz-кодированных данных браузерам, поддерживающим сжатые веб-страницы. ob_gzhandler() определяет тип кодировки содержимого, принимаемый браузером, и возвращает вывод соответствующим образом.
chunk_size
Если передан необязательный параметр chunk_size,
то буфер буден сброшен после любого вывода, превышающего или равного
по размеру chunk_size. Значение
по умолчанию 0 означает, что функция вывода будет
вызвана, когда буфер будет закрыт.
flags
Параметр flags является битовой маской, которая
управляет операциями, которые можно совершать над буфером вывода.
По умолчанию она позволяет буферу вывода быть очищенным, сброшенным и удалённым, что
равносильно значению
PHP_OUTPUT_HANDLER_CLEANABLE |
PHP_OUTPUT_HANDLER_FLUSHABLE |
PHP_OUTPUT_HANDLER_REMOVABLE или
PHP_OUTPUT_HANDLER_STDFLAGS как сокращение этой комбинации.
Каждый флаг управляет доступом к набору функций, как описано ниже:
| Константа | Функции |
|---|---|
PHP_OUTPUT_HANDLER_CLEANABLE |
ob_clean(), ob_end_clean() и ob_get_clean(). |
PHP_OUTPUT_HANDLER_FLUSHABLE |
ob_end_flush(), ob_flush() и ob_get_flush(). |
PHP_OUTPUT_HANDLER_REMOVABLE |
ob_end_clean(), ob_end_flush() и ob_get_flush(). |
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Пример callback-функции, определённой пользователем
<?php
function callback($buffer)
{
// заменить все яблоки апельсинами
return (str_replace("яблоки", "апельсины", $buffer));
}
ob_start("callback");
?>
<html>
<body>
<p>Это всё равно что сравнить яблоки и апельсины.</p>
</body>
</html>
<?php
ob_end_flush();
?>Результат выполнения данного примера:
<html> <body> <p>Это всё равно что сравнить апельсины и апельсины.</p> </body> </html>
Пример #2 Создание нестираемого буфера вывода
<?php
ob_start(null, 0, PHP_OUTPUT_HANDLER_STDFLAGS ^ PHP_OUTPUT_HANDLER_REMOVABLE);
?>
(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)
output_add_rewrite_var — Добавить значения в обработчик URL
$name, string $value): boolЭта функция добавляет ещё одну пару имя/значение к механизму перезаписи URL. Имя и значение будут добавлены к URL (в качестве GET-параметров) и формам (как скрытые поля ввода) так же, как и идентификатор сессии, если включена прозрачная перезапись ссылок с использованием session.use_trans_sid.
Поведение этой функции контролируется параметрами php.ini url_rewriter.tags и url_rewriter.hosts.
Обратите внимание, что функция может быть успешно вызвана не более одного раза за запрос.
Замечание: Вызов этой функции неявно запустит буферизацию вывода, если она ещё не активна.
nameИмя параметра.
valueЗначение параметра.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
| Версия | Описание |
|---|---|
| 7.1.0 | До PHP 7.1.0 переменные перезаписи, установленные функцией output_add_rewrite_var(), используют тот же буфер модуля сессии "trans sid". Начиная с PHP 7.1.0, используется отдельный буфер, url_rewriter.tags используется только для функций вывода, добавлен url_rewriter.hosts. |
Пример #1 Пример использования функции output_add_rewrite_var()
<?php
output_add_rewrite_var('var', 'value');
// несколько ссылок
echo '<a href="file.php">ссылка</a>
<a href="http://example.com">ссылка2</a>';
// форма
echo '<form action="script.php" method="post">
<input type="text" name="var2" />
</form>';
print_r(ob_list_handlers());
?>Результат выполнения данного примера:
<a href="file.php?var=value">ссылка</a>
<a href="http://example.com">ссылка2</a>
<form action="script.php" method="post">
<input type="hidden" name="var" value="value" />
<input type="text" name="var2" />
</form>
Array
(
[0] => URL-Rewriter
)
(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)
output_reset_rewrite_vars — Сбросить значения обработчика URL
Эта функция сбрасывает обработчик URL и удаляет все значения, установленные функцией output_add_rewrite_var().
У этой функции нет параметров.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
| Версия | Описание |
|---|---|
| 7.1.0 | До PHP 7.1.0, переменные перезаписи установленные функцией output_add_rewrite_var() используют тот же буфер модуля сессии "trans sid". С PHP 7.1.0, используется отдельный буфер и output_reset_rewrite_vars() только удаляет переменные перезаписи определённые output_add_rewrite_var(). |
Пример #1 Пример использования функции output_reset_rewrite_vars()
<?php
session_start();
output_add_rewrite_var('var', 'value');
echo '<a href="file.php">ссылка</a>';
ob_flush();
output_reset_rewrite_vars();
echo '<a href="file.php">ссылка</a>';
?>Результат выполнения данного примера:
<a href="file.php?PHPSESSID=xxx&var=value">ссылка</a> <a href="file.php">ссылка</a>
Эти функции позволяют вам получить множество информации о самом PHP, например, установки конфигурации, загруженные модули, версию и многое другое. Вы так же найдёте функции для установки параметров работы PHP. Вероятно, самую известную функцию в PHP - phpinfo() - можно найти здесь.
Для сборки этого модуля не требуются внешние библиотеки.
Для использования этих функций не требуется проведение установки, поскольку они являются частью ядра PHP.
Поведение этих функций зависит от установок в php.ini.
| Имя | По умолчанию | Место изменения | Список изменений |
|---|---|---|---|
| assert.active | "1" | PHP_INI_ALL | |
| assert.bail | "0" | PHP_INI_ALL | |
| assert.warning | "1" | PHP_INI_ALL | |
| assert.callback | NULL | PHP_INI_ALL | |
| assert.quiet_eval | "0" | PHP_INI_ALL | Удалено в PHP 8.0.0 |
| assert.exception | "1" | PHP_INI_ALL | До PHP 8.0.0 значение по умолчанию было "0". |
| enable_dl | "1" | PHP_INI_SYSTEM | Эта возможность устарела и будет обязательно удалена в будущем. |
| max_execution_time | "30" | PHP_INI_ALL | |
| max_input_time | "-1" | PHP_INI_PERDIR | |
| max_input_nesting_level | "64" | PHP_INI_PERDIR | |
| max_input_vars | 1000 | PHP_INI_PERDIR | |
| zend.enable_gc | "1" | PHP_INI_ALL |
Краткое разъяснение конфигурационных директив.
assert.active
bool
Включение выполнение assert(). zend.assertions следует использовать вместо этого для управления поведением функции assert().
assert.bail
bool
Завершение работы скрипта при провале проверки утверждений.
assert.warning
bool
Вызов предупреждений PHP для каждой проваленной проверки утверждения.
assert.callback
string
Пользовательская функция, вызываемая при провале проверки утверждений.
assert.quiet_eval
bool
Данная функциональность была УДАЛЕНА, начиная с PHP 8.0.0.
Используйте эту настройку функции error_reporting() во время выполнения проверки утверждений. При включении настройки сообщения об ошибках во время проверки утверждений показываться не будут (неявный вызов error_reporting(0)). Если настройка выключена, ошибки будут выдаваться в соответствии с настройками error_reporting()
assert.exception
bool
Генерирует исключение AssertionError для неудачной проверки утверждения.
enable_dl
bool
Директива позволяет включать и выключать динамическую подгрузку модулей PHP с помощью функции dl().
Главной причиной, по которой требуется выключение динамической загрузки, является безопасность. С помощью динамической загрузки можно обойти все open_basedir ограничения. По умолчанию динамическая загрузка разрешена.
max_execution_time
int
Эта директива задаёт максимальное время в секундах, в течение которого
скрипт должен полностью загрузиться. Если этого не происходит, парсер
завершает работу скрипта. Этот механизм помогает предотвратить зависание сервера
из-за плохо написанного скрипта. По умолчанию на загрузку даётся
30 секунд. Если PHP запущен из
командной строки, это значение
по умолчанию равно 0.
В системах, отличных от Windows, на максимальное время выполнения не влияют системные вызовы, потоковые операции и т.п. За дополнительной информацией обращайтесь к документации к функции set_time_limit().
Веб-серверы обычно имеют свои настройки времени ожидания, по превышении которого сами
завершают выполнение скрипта PHP. В Apache есть директива
Timeout, в IIS есть функция CGI timeout. В обоих случаях
по умолчанию установлено 300 секунд. Точные значения можно узнать из
документации к веб-серверу.
max_input_time
int
Эта директива задаёт максимальное время в секундах, в течение которого скрипт
должен разобрать все входные данные, переданные запросами вроде POST или GET.
Это время измеряется от момента, когда PHP вызван на сервере до
момента, когда скрипт начинает выполняться.
Значение по умолчанию -1, что означает, что будет использоваться
max_execution_time. Если установить
равным 0, то ограничений по времени не будет.
max_input_nesting_level
int
Задаёт максимальную глубину вложенности входных переменных (то есть $_GET, $_POST.)
max_input_vars
int
Сколько входных переменных
может быть принято в одном запросе (ограничение накладывается на каждую из
глобальных переменных $_GET, $_POST и $_COOKIE отдельно).
Использование этой директивы снижает
вероятность сбоев в случае атак с использованием хеш-коллизий. Если входных
переменных больше, чем задано директивой, выбрасывается предупреждение
E_WARNING, а все последующие переменные в запросе
игнорируются.
zend.enable_gc
bool
Включает или отключает сборщик циклических ссылок.
Данный модуль не определяет каких-либо типов ресурсов.
Перечисленные ниже константы всегда доступны как часть ядра PHP.
| Константы | Значение | Описание |
|---|---|---|
CREDITS_GROUP |
1 | Список разработчиков ядра PHP |
CREDITS_GENERAL |
2 | Главные разработчики: Дизайн и концепции языка, авторы PHP и модуля SAPI. |
CREDITS_SAPI |
4 | Список серверных API для PHP и их авторы. |
CREDITS_MODULES |
8 | Список модулей для PHP и их авторы. |
CREDITS_DOCS |
16 | Члены команды разработчиков документации. |
CREDITS_FULLPAGE |
32 | Обычно используется в сочетании с другими флагами. Означает, что HTML- страница должна печататься вместе с дополнительной информацией (за которую отвечают другие флаги). |
CREDITS_QA |
64 | Члены команды контроля качества. |
CREDITS_ALL |
-1 |
Все разработчики, аналогично использованию: CREDITS_DOCS +
CREDITS_GENERAL + CREDITS_GROUP + CREDITS_MODULES + CREDITS_QA
CREDITS_FULLPAGE. Будет сгенерирована HTML-страница с соответствующими
тегами. Это значение по умолчанию.
|
| Константы | Значение | Описание |
|---|---|---|
INFO_GENERAL |
1 | Строка конфигурации, местоположение php.ini, дата сборки, веб-сервер, система и др. |
INFO_CREDITS |
2 | Разработчики PHP. Смотрите также phpcredits(). |
INFO_CONFIGURATION |
4 | Текущие локальные и основные значения директив PHP. Смотрите также ini_get(). |
INFO_MODULES |
8 | Загруженные модули и их настройки. |
INFO_ENVIRONMENT |
16 | Информация о переменных среды, которая также доступна в $_ENV. |
INFO_VARIABLES |
32 |
Показывает все
предопределённые переменные из EGPCS (Environment,
GET, POST, Cookie, Server).
|
INFO_LICENSE |
64 | Информация о лицензии PHP. Смотрите также » FAQ по лицензии. |
INFO_ALL |
-1 | Константа по умолчанию. Показывает всю информацию описанную выше. |
| Константы | Значение | Описание |
|---|---|---|
INI_USER |
1 | Не используется |
INI_PERDIR |
2 | Не используется |
INI_SYSTEM |
4 | Не используется |
INI_ALL |
7 | Не используется |
Константы проверки утверждений. Эти значения используются для задания настроек assert_options().
| Константы | INI настройка | Описание |
|---|---|---|
ASSERT_ACTIVE |
assert.active | Включение assert() проверок. |
ASSERT_CALLBACK |
assert.callback | Обратный вызов при провале проверки утверждения. |
ASSERT_BAIL |
assert.bail | Прервать выполнение при провале проверки утверждения. |
ASSERT_EXCEPTION |
assert.exception | Выдаёт предупреждение PHP для каждого неудачного утверждения. |
ASSERT_WARNING |
assert.warning | Выдавать предупреждение PHP в случае провала проверки каждого утверждения |
ASSERT_QUIET_EVAL |
assert.quiet_eval |
Отключить error_reporting во время выполнения проверки
утверждения.
Удалено, начиная с PHP 8.0.0
|
Следующие константы доступны только под Windows. Они позволяют извлечь различную информацию о версиях программного обеспечения. Все константы доступны с PHP 5.3.0.
| Константы | Описание |
|---|---|
PHP_WINDOWS_VERSION_MAJOR |
Основной номер версии Windows, это может быть 4
(NT4/Me/98/95), 5 (XP/2003 R2/2003/2000) или
6 (Vista/2008/7/8/8.1).
|
PHP_WINDOWS_VERSION_MINOR |
Уточняющий номер версии Windows, это может быть 0
(Vista/2008/2000/NT4/95), 1 (XP), 2
(2003 R2/2003/XP x64), 10 (98) или 90
(ME).
|
PHP_WINDOWS_VERSION_BUILD |
Номер сборки Windows (например, Windows Vista SP1 имеет номер сборки 6001) |
PHP_WINDOWS_VERSION_PLATFORM |
Платформа, на которой PHP работает на данный момент. Возможны значения
2 для Windows Vista/XP/2000/NT4, Server 2008/2003, а для
Windows ME/98/95 это значение будет 1.
|
PHP_WINDOWS_VERSION_SP_MAJOR |
Основной номер версии установленного сервис-пакета. Возможно значение
0, если пакетов не установлено. Например, в Windows XP
с 3м сервис паком это значение будет 3.
|
PHP_WINDOWS_VERSION_SP_MINOR |
Дополнительный номер установленного пакета обновлений. Значение
0 говорит от том, что пакетов не установлено.
|
PHP_WINDOWS_VERSION_SUITEMASK |
Битовая маска указывающая, какая дополнительная функциональность установлена в системе Windows. Ниже приведена таблица с возможными значениями битового поля. |
PHP_WINDOWS_VERSION_PRODUCTTYPE |
Содержит значение, определяющее константы вида
PHP_WINDOWS_NT_*. Этим значением может быть одна из
констант PHP_WINDOWS_NT_* указывающая на тип платформы.
|
PHP_WINDOWS_NT_DOMAIN_CONTROLLER |
Контроллер домена |
PHP_WINDOWS_NT_SERVER |
Серверная система (напр. Server 2008/2003/2000). Надо учесть, что если сервер
является контроллером домена, вместо этой константы будет выдаваться
PHP_WINDOWS_NT_DOMAIN_CONTROLLER.
|
PHP_WINDOWS_NT_WORKSTATION |
Система рабочей станции (напр. Vista/XP/2000/NT4) |
Таблица значений битовой маски PHP_WINDOWS_VERSION_SUITEMASK.
| Биты | Описание |
|---|---|
0x00000004 |
Установлены компоненты Microsoft BackOffice. |
0x00000400 |
Установлен Windows Server 2003 Web Edition. |
0x00004000 |
Установлен Windows Server 2003 Compute Cluster Edition. |
0x00000080 |
Установлен Windows Server 2008 Datacenter, Windows Server 2003, Datacenter Edition или Windows 2000 Datacenter Server. |
0x00000002 |
Установлен Windows Server 2008 Enterprise, Windows Server 2003, Enterprise Edition, Windows 2000 Advanced Server или Windows NT Server 4.0 Enterprise Edition. |
0x00000040 |
Установлен Windows XP Embedded. |
0x00000200 |
Установлен Windows Vista Home Premium, Windows Vista Home Basic или Windows XP Home Edition. |
0x00000100 |
Поддерживается удалённый рабочий стол, но только в интерактивном режиме. Это значение устанавливается до тех пор, пока система не будет запущена в режиме сервера приложений. |
0x00000001 |
Microsoft Small Business Server был установлен изначально, однако мог быть проведён апгрейд системы до другой версии Windows. |
0x00000020 |
Microsoft Small Business Server установлен с ограниченной лицензией. |
0x00002000 |
Установлен Windows Storage Server 2003 R2 или Windows Storage Server 2003. |
0x00000010 |
Установлены терминальные службы. Это значение всегда установлено. Если это
значение установлено, значение 0x00000100 не задано,
то система работает в режиме сервера приложений.
|
0x00008000 |
Установлен Windows Home Server. |
(PHP 4, PHP 5, PHP 7, PHP 8)
assert_options — Установка и получение настроек механизма проверки утверждений
Задание значений настроек механизма проверки утверждений assert() или получение их текущих значений.
Замечание: Использование assert_options() не рекомендуется в пользу установки и получения php.ini директив zend.assertions и assert.exception с помощью ini_set() и ini_get() соответственно.
option
| Настройка | INI-параметр | Значение по умолчанию | Описание |
|---|---|---|---|
| ASSERT_ACTIVE | assert.active | 1 | включение механизма проверки утверждений |
| ASSERT_EXCEPTION | assert.exception | 1 | выбрасывает AssertionError для каждого неудачного утверждения |
| ASSERT_WARNING | assert.warning | 1 | вывод предупреждения PHP для каждой неудачной проверки |
| ASSERT_BAIL | assert.bail | 0 | завершить выполнение в случае неудачной проверки |
| ASSERT_QUIET_EVAL | assert.quiet_eval | 0 | отключить error_reporting во время проверки утверждения. Удалено начиная с PHP 8.0.0. |
| ASSERT_CALLBACK | assert.callback | (null) |
Callback-функция, которую необходимо вызвать для провалившего проверку утверждения |
valueНеобязательный аргумент, новое значение настройки.
У callback-функции, установленной с помощью ASSERT_CALLBACK или assert.callback,
должна быть следующая сигнатура:
$file,$line,$assertion,$description = ?filelineassertionnull.
descriptionvalue сбрасывает assert callback.
Возвращает исходное значение настройки.
Функция выбрасывает ValueError,
если параметр option не является допустимой опцией.
| Версия | Описание |
|---|---|
| 8.0.0 |
Если параметр option не является допустимой опцией,
теперь выбрасывается ошибка ValueError;
ранее возвращалось значение false.
|
Пример #1 Пример использования assert_options()
<?php
// Наша функция обработчик
// неудавшихся проверок
function function assert_failure($file, $line, $assertion, $message)
{
echo "Проверка $assertion в $file на строке $line провалена: $message";
}
// Тестовая функция
function test_assert($parameter)
{
assert(is_bool($parameter));
}
// настройки проверки
assert_options(ASSERT_ACTIVE, true);
assert_options(ASSERT_BAIL, true);
assert_options(ASSERT_WARNING, false);
assert_options(ASSERT_CALLBACK, 'assert_failure');
// заведомо ошибочное утверждение
test_assert(1);
// Этот код не будет выполняться, пока ASSERT_BAIL
// равен true
echo 'Никогда не будет выведено';
?>(PHP 4, PHP 5, PHP 7, PHP 8)
assert — Проверяет утверждение
assert() - это не функция, а языковая конструкция. Позволяет определять ожидания: утверждения, которые вступают в силу в средах разработки и тестирования, но оптимизированы так, что в производственной среде имеют нулевую стоимость.
Утверждения следует использовать только в качестве отладочной функции.
Один из вариантов их использования - проверка на вменяемость предварительных условий,
которые всегда должны быть true и если они не выполняются,
это указывает на ошибки программирования.
Другой случай использования - убедиться в наличии определённых возможностей,
например, функций модуля или определённых ограничений и возможностей системы.
Поскольку утверждения могут быть настроены на отказ от них, их не следует использовать для обычных операций во время выполнения, таких как проверка входных параметров. Как правило, код должен вести себя так, как ожидается, даже если проверка утверждений отключена.
assert() проверяет, что ожидание, заданное в параметре assertion, выполняется.
Если нет, и результат будет значение false, то будет предпринято соответствующее действие
в зависимости от того, как была настроена конструкция assert().
Поведение конструкции assert() определяется следующими настройками INI:
| Имя | По умолчанию | Описание | Список изменений |
|---|---|---|---|
| zend.assertions | 1 |
|
|
| assert.active | true |
Если false, assert() не проверяет ожидание
и возвращает true, безоговорочно.
|
|
| assert.callback | null |
Определяемая пользователем функция, вызываемая в случае неудачной проверки утверждения.
Её сигнатура должна быть следующей:
assert_callback(
string $file,int $line,null $assertion,string $description = ?): void |
До PHP 8.0.0 сигнатура callback-функции должна быть:
assert_callback(
string $file,int $line,string $assertion,string $description = ?): void |
| assert.exception | true |
Если true, будет выброшена ошибка AssertionError
в случае неудачной проверки утверждения.
|
|
| assert.bail | false |
Если true, выполнение PHP-скрипта прервётся в случае неудачной проверки утверждении.
|
|
| assert.warning | true |
Если true, будет выдана ошибка уровня E_WARNING в случае неудачной проверки утверждения.
Эта INI-настройка неэффективна, если включена assert.exception.
|
assert., могут быть настроены с помощью
функции assert_options(). Однако это не рекомендуется.
assertionЛюбое выражение, возвращающее значение, которое будет выполнено, а результат используется для указания того, удалась или не удалась проверка утверждения.
До версии PHP 8.0.0, если параметр assertion представлял
собой строку (string), он интерпретировался как PHP-код
и выполнялся с помощью функции eval().
Эта строка передавалась в callback-функцию в качестве третьего аргумента.
Это поведение УСТАРЕЛО в PHP 7.2.0 и УДАЛЕНО в PHP 8.0.0.
description
Если параметр description является экземпляром
класса Throwable, он будет выброшен только в том случае,
если проверка утверждения assertion не удастся.
Замечание:
Начиная с PHP 8.0.0, это делается до вызова потенциально определённой callback-функции утверждения.
Замечание:
Начиная с PHP 8.0.0, объект (object) будет выброшен независимо от конфигурации параметра assert.exception.
Замечание:
Начиная с PHP 8.0.0, параметр assert.bail не имеет никакого эффекта в этом случае.
Если параметр description является строкой (string),
это сообщение будет использоваться в случае выбрасывания исключения или предупреждения.
Необязательное описание, которое будет включено в сообщение,
если проверка утверждения assertion не удастся.
Если параметр description опущен.
Во время компиляции создаётся описание по умолчанию,
равное исходному коду для вызова assert().
Возвращает false, если проверка провалена, true в противном случае.
| Версия | Описание |
|---|---|
| 8.0.0 |
assert() больше не будет оценивать строковые аргументы,
вместо этого они будут рассматриваться как любой другой аргумент.
Вместо assert($a == $b) следует использовать assert('$a == $b').
Директива assert.quiet_eval php.ini и константа ASSERT_QUIET_EVAL
также были удалены, поскольку они больше не будут иметь никакого эффекта.
|
| 8.0.0 |
Если параметр description является экземпляром класса Throwable,
объект выбрасывается в случае неудачной проверки утверждения,
независимо от значения assert.exception.
|
| 8.0.0 |
Если параметр description является экземпляром класса Throwable,
пользовательская callback-функция не вызывается, даже если она установлена.
|
| 8.0.0 |
Объявление функции с именем assert() внутри пространства имён
больше не допускается и выдаёт ошибку уровня E_COMPILE_ERROR.
|
| 7.3.0 |
Объявление функции assert() внутри пространства имён устарело.
Такое объявление теперь выдаёт ошибку уровня E_DEPRECATED.
|
| 7.2.0 |
Использование строки (string) в качестве assertion
устарело. Теперь оно выдаёт ошибку уровня E_DEPRECATED,
когда значение и assert.active и
zend.assertions равно 1.
|
<?php
assert(true == false);
echo 'Привет!';
?>Если zend.assertions установить значение 0, то приведённый выше пример выведет:
Привет!
Если zend.assertions установить значение 1, а assert.exception установить значение 0, то приведённый выше пример выведет:
Warning: assert(): assert(true == false) failed in - on line 2 Привет!
Если zend.assertions установить значение 1, а assert.exception установить значение 1, то приведённый выше пример выведет:
Fatal error: Uncaught AssertionError: assert(true == false) in -:2
Stack trace:
#0 -(2): assert(false, 'assert(true == ...')
#1 {main}
thrown in - on line 2
Пример #1 Ожидания при использовании пользовательского исключения
<?php
class CustomError extends AssertionError {}
assert(true == false, new CustomError('True не является false!'));
echo 'Привет!';
?>Если zend.assertions установить значение 0, то приведённый выше пример выведет:
Привет!
Если zend.assertions установить значение 1, а assert.exception установить значение 0, то приведённый выше пример выведет:
Warning: assert(): CustomError: True не является false! in -:4
Stack trace:
#0 {main} failed in - on line 4
Привет!
Если zend.assertions установить значение 1, а assert.exception установить значение 1, то приведённый выше пример выведет:
Fatal error: Uncaught CustomError: True не является false! in -:4
Stack trace:
#0 {main}
thrown in - on line 4
При использовании оцениваемых утверждений callback-функции assert() могут быть особенно полезны, поскольку код, использованный для утверждения, передаётся callback-функции вместе с информацией о том, где было выполнено утверждение.
Пример #2 Обработка неудачной проверки утверждения с помощью пользовательского обработчика
<?php
// Активируйте утверждение и отключите error_reporting
assert_options(ASSERT_ACTIVE, 1);
assert_options(ASSERT_WARNING, 0);
assert_options(ASSERT_QUIET_EVAL, 1);
// Создайте функцию-обработчик
function my_assert_handler($file, $line, $code)
{
echo "<hr>Утверждение не выполнено:
Файл '$file'<br />
Строка '$line'<br />
Код '$code'<br /><hr />";
}
// Настройте callback-функцию
assert_options(ASSERT_CALLBACK, 'my_assert_handler');
// Создайте утверждение, которое должно потерпеть неудачу
$array = [];
assert('count($array);');
?>Результат выполнения данного примера в PHP 7.2:
Deprecated: assert(): Calling assert() with a string argument is deprecated in test.php on line 21
<hr>Утверждение не выполнено:
Файл 'test.php'<br />
Строка '21'<br />
Код 'count($array);'<br /><hr />
Результат выполнения данного примера в PHP 7.1:
<hr>Утверждение не выполнено:
Файл 'test.php'<br />
Строка '21'<br />
Код 'count($array);'<br /><hr />
Пример #3 Использование пользовательского обработчика для вывода описания
<?php
// Активируйте утверждение и отключите error_reporting
assert_options(ASSERT_ACTIVE, 1);
assert_options(ASSERT_WARNING, 0);
assert_options(ASSERT_QUIET_EVAL, 1);
// Создайте функцию-обработчик
function my_assert_handler($file, $line, $code, $desc = null)
{
echo "Утверждение не выполнено в $file:$line: $code";
if ($desc) {
echo ": $desc";
}
echo "\n";
}
// Настройте callback-функцию
assert_options(ASSERT_CALLBACK, 'my_assert_handler');
// Создайте утверждение, которое должно потерпеть неудачу
assert('2 < 1');
assert('2 < 1', 'Два меньше, чем один');
?>Результат выполнения данного примера в PHP 7.2:
Deprecated: assert(): Calling assert() with a string argument is deprecated in test.php on line 21 Утверждение не выполнено в test.php:21: 2 < 1 Deprecated: assert(): Calling assert() with a string argument is deprecated in test.php on line 22 Утверждение не выполнено в test.php:22: 2 < 1: Два меньше, чем один
Результат выполнения данного примера в PHP 7.1:
Утверждение не выполнено в test.php:21: 2 < 1 Утверждение не выполнено в test.php:22: 2 < 1: Два меньше, чем один
(PHP 5 >= 5.5.0, PHP 7, PHP 8)
cli_get_process_title — Возвращает заголовок текущего процесса
Возвращает заголовок текущего процесса, установленный cli_set_process_title(). Обратите внимание, что в зависимости от вашей операционной системы, это имя может не совпадать с тем, что покажут утилиты ps и top.
Эта функция доступна только в режиме CLI.
У этой функции нет параметров.
Возвратит строку с заголовком процесса или null в случае возникновения ошибки.
Если команда не поддерживается вашей операционной системой, то будет
вызвана ошибка уровня E_WARNING.
Пример #1 Пример использования cli_get_process_title()
<?php
echo "Заголовок процесса: " . cli_get_process_title() . "\n";
?>(PHP 5 >= 5.5.0, PHP 7, PHP 8)
cli_set_process_title — Устанавливает заголовок процесса
$title): boolУстанавливает заголовок процесса, видимое утилитами top и ps. Эта функция доступна только в режиме CLI.
titleНовое имя.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Если команда не поддерживается вашей операционной системой, то будет
вызвана ошибка уровня E_WARNING.
Пример #1 Пример использования cli_set_process_title()
<?php
$title = "Мой потрясающий PHP-скрипт";
$pid = getmypid(); // вы можете использовать это, чтобы увидеть заголовок процесса в ps
if (!cli_set_process_title($title)) {
echo "Не удалось установить заголовок процесса для PID $pid...\n";
exit(1);
} else {
echo "Заголовок процесса '$title' для PID $pid был установлен!\n";
sleep(5);
}
?>(PHP 4, PHP 5, PHP 7, PHP 8)
dl — Загружает модуль PHP во время выполнения
$extension_filename): bool
Загружает модуль PHP, заданный аргументом extension_filename.
Чтобы проверить, что заданный модуль уже загружен, используйте функцию extension_loaded(). Функция работает как для встроенных модулей, так и для динамически загруженных (т.е. загруженных как через php.ini, так и через dl()).
Функция доступна только для CLI и встроенного SAPI, а также для CGI SAPI при запуске из командной строки.
extension_filenameАргумент содержит только имя файла модуля, который требуется загрузить. Это имя зависит от платформы. Например, модуль sockets (если скомпилирован, как загружаемый модуль, а не модуль по умолчанию!) будет называться sockets.so на Unix-платформах, и php_sockets.dll в среде Windows.
Директория, из которой модуль должен быть загружен, также зависит от платформы:
Windows - Если явно не задано в php.ini, модуль будет грузиться из C:\php5\ по умолчанию.
Unix - Если явно не задано в php.ini, директория по умолчанию зависит от
--enable-debug или без неё
ZEND_MODULE_API_NO
(номер внутреннего модуля Zend API, который, как правило, является датой
основного изменения API модуля, например 20010901)
<install-dir>/lib/php/extensions/ <debug-or-not>-<zts-or-not>-ZEND_MODULE_API_NO,
например,
/usr/local/php/lib/php/extensions/debug-non-zts-20010901
или
/usr/local/php/lib/php/extensions/no-debug-zts-20010901.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки. Если механизм загрузки модулей недоступен или отключён
(значение off настройки enable_dl в php.ini), будет выдана ошибка
E_ERROR и выполнение прекращается. Если
dl() не сможет загрузить заданную библиотеку, то в дополнение
к false будет выдано сообщение E_WARNING.
Пример #1 Примеры использования dl()
<?php
// Пример загрузки модуля, основываясь на ОС
if (!extension_loaded('sqlite')) {
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
dl('php_sqlite.dll');
} else {
dl('sqlite.so');
}
}
// Или на константе PHP_SHLIB_SUFFIX
if (!extension_loaded('sqlite')) {
$prefix = (PHP_SHLIB_SUFFIX === 'dll') ? 'php_' : '';
dl($prefix . 'sqlite.' . PHP_SHLIB_SUFFIX);
}
?>Замечание:
dl() чувствительна к регистру на Unix-платформах.
(PHP 4, PHP 5, PHP 7, PHP 8)
extension_loaded — Определяет, загружен ли модуль
$extension): boolОпределяет, загружен ли указанный модуль.
extensionИмя модуля. Этот параметр регистронезависимый.
Чтобы посмотреть все имена модулей, воспользуйтесь функцией
phpinfo(). Если вы работаете с
CGI- или CLI-версией PHP, используйте
параметр -m для отображения списка доступных модулей:
$ php -m [PHP Modules] xml tokenizer standard sockets session posix pcre overload mysql mbstring ctype [Zend Modules]
Возвращает true, если модуль с заданным именем extension
загружен или false в противном случае.
Пример #1 Пример использования extension_loaded()
<?php
if (!extension_loaded('gd')) {
if (!dl('gd.so')) {
exit;
}
}
?>
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
gc_collect_cycles — Принудительный запуск сборщика мусора
Явным образом запускает механизм поиска циклических ссылок.
У этой функции нет параметров.
Возвращает число найденных ссылок.
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
gc_disable — Отключает сборщик циклических ссылок
Отключает сборщик циклических ссылок, путём установки значения
zend.enable_gc в 0.
У этой функции нет параметров.
Функция не возвращает значения после выполнения.
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
gc_enable — Включает сборщик циклических ссылок
У этой функции нет параметров.
Функция не возвращает значения после выполнения.
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
gc_enabled — Возвращает текущее состояние сборщика циклических ссылок
Возвращает текущее состояние сборщика циклических ссылок.
У этой функции нет параметров.
Возвращает true, если сборщик мусора включён или false в противном случае.
Пример #1 Пример использования gc_enabled()
<?php
if(gc_enabled()) gc_collect_cycles();
?>(PHP 7, PHP 8)
gc_mem_caches — Освобождает память, используемую менеджером памяти Zend Engine
Освобождает память, используемую менеджером памяти Zend Engine.
У этой функции нет параметров.
Возвращает количество освобождённых байт.
(PHP 7 >= 7.3.0, PHP 8)
gc_status — Возвращает информацию о текущем статусе сборщика мусора
Возвращает информацию о текущем статусе сборщика мусора.
У этой функции нет параметров.
Возвращает ассоциативный массив со следующими элементами:
"runs"
"collected"
"threshold"
"roots"
Пример #1 Использование gc_status()
<?php
// создадим дерево объектов, для которых понадобится собирать мусор
$a = new stdClass();
$a->b = [];
for ($i = 0; $i < 100000; $i++) {
$b = new stdClass();
$b->a = $a;
$a->b[] = $b;
}
unset($a);
unset($b);
gc_collect_cycles();
var_dump(gc_status());Результатом выполнения данного примера будет что-то подобное:
array(4) {
["runs"]=>
int(5)
["collected"]=>
int(100002)
["threshold"]=>
int(50001)
["roots"]=>
int(0)
}
(PHP 4, PHP 5, PHP 7, PHP 8)
get_cfg_var — Извлекает значение настройки конфигурации PHP
$option): string|array|false
Извлекает значение настройки конфигурации PHP option.
Функция не вернёт никакой информации, заданной при сборке PHP или указанной в конфигурационном файле Apache.
Чтобы проверить, что система использует файл конфигурации, попробуйте получить значение настройки конфигурации cfg_file_path. Если эта настройка доступна, значит используется файл конфигурации.
optionИмя настройки конфигурации.
Возвращает текущее значение настройки конфигурации PHP
option или false в случае возникновения ошибки.
(PHP 4, PHP 5, PHP 7, PHP 8)
get_current_user — Получает имя владельца текущего скрипта PHP
Возвращает имя владельца текущего PHP-скрипта.
У этой функции нет параметров.
Возвращает имя пользователя в виде строки.
Пример #1 Пример использования get_current_user()
<?php
echo 'Текущий владелец скрипта: ' . get_current_user();
?>Результатом выполнения данного примера будет что-то подобное:
Текущий владелец скрипта: SYSTEM
(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8)
get_defined_constants — Возвращает ассоциативный массив с именами всех констант и их значений
$categorize = false): arrayВозвращает ассоциативный массив с именами и значениями всех определённых в настоящее время констант. Массив будет включать в себя константы, определённые модулями, а также созданные функцией define().
categorizeИспользование этого аргумента даёт возможность получить многомерный массив, в котором в первом измерении будут содержаться категории констант, а во втором соответствующие имена и значения.
<?php
define("MY_CONSTANT", 1);
print_r(get_defined_constants(true));
?>Результатом выполнения данного примера будет что-то подобное:
Array
(
[Core] => Array
(
[E_ERROR] => 1
[E_WARNING] => 2
[E_PARSE] => 4
[E_NOTICE] => 8
[E_CORE_ERROR] => 16
[E_CORE_WARNING] => 32
[E_COMPILE_ERROR] => 64
[E_COMPILE_WARNING] => 128
[E_USER_ERROR] => 256
[E_USER_WARNING] => 512
[E_USER_NOTICE] => 1024
[E_ALL] => 2047
[TRUE] => 1
)
[pcre] => Array
(
[PREG_PATTERN_ORDER] => 1
[PREG_SET_ORDER] => 2
[PREG_OFFSET_CAPTURE] => 256
[PREG_SPLIT_NO_EMPTY] => 1
[PREG_SPLIT_DELIM_CAPTURE] => 2
[PREG_SPLIT_OFFSET_CAPTURE] => 4
[PREG_GREP_INVERT] => 1
)
[user] => Array
(
[MY_CONSTANT] => 1
)
)
Возвращает массив вида "имя константы" => "значение константы", с возможностью сгруппировать его по имени модуля, зарегистрировавшего константу.
Пример #1 Пример использования get_defined_constants()
<?php
print_r(get_defined_constants());
?>Результатом выполнения данного примера будет что-то подобное:
Array
(
[E_ERROR] => 1
[E_WARNING] => 2
[E_PARSE] => 4
[E_NOTICE] => 8
[E_CORE_ERROR] => 16
[E_CORE_WARNING] => 32
[E_COMPILE_ERROR] => 64
[E_COMPILE_WARNING] => 128
[E_USER_ERROR] => 256
[E_USER_WARNING] => 512
[E_USER_NOTICE] => 1024
[E_ALL] => 2047
[TRUE] => 1
)
(PHP 4, PHP 5, PHP 7, PHP 8)
get_extension_funcs — Возвращает массив имён функций модуля
$extension): array|false
Функция возвращает имена всех функций, определённых в модуле с именем
extension.
extensionИмя модуля.
Замечание:
Значение этого аргумента должно задаваться в нижнем регистре.
Возвращает массив имён функций или false, если
extension не является допустимым модулем.
Пример #1 Выводит функции XML
<?php
print_r(get_extension_funcs("xml"));
?>Результатом выполнения данного примера будет что-то подобное:
Array
(
[0] => xml_parser_create
[1] => xml_parser_create_ns
[2] => xml_set_object
[3] => xml_set_element_handler
[4] => xml_set_character_data_handler
[5] => xml_set_processing_instruction_handler
[6] => xml_set_default_handler
[7] => xml_set_unparsed_entity_decl_handler
[8] => xml_set_notation_decl_handler
[9] => xml_set_external_entity_ref_handler
[10] => xml_set_start_namespace_decl_handler
[11] => xml_set_end_namespace_decl_handler
[12] => xml_parse
[13] => xml_parse_into_struct
[14] => xml_get_error_code
[15] => xml_error_string
[16] => xml_get_current_line_number
[17] => xml_get_current_column_number
[18] => xml_get_current_byte_index
[19] => xml_parser_free
[20] => xml_parser_set_option
[21] => xml_parser_get_option
)
(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)
get_include_path — Получение текущего значения настройки конфигурации include_path
У этой функции нет параметров.
Возвращает путь к файлу в виде строки или false в случае возникновения ошибки.
Пример #1 Пример использования get_include_path()
<?php
echo get_include_path();
// или используя ini_get()
echo ini_get('include_path');
?>
(PHP 4, PHP 5, PHP 7, PHP 8)
get_included_files — Возвращает массив имён включённых в скрипт файлов
Получает имена всех файлов, которые были включены в скрипт с использованием include, include_once, require или require_once.
У этой функции нет параметров.
Возвращает массив, содержащий имена всех файлов.
Скрипт, который был загружен изначально, рассматривается как "включённый файл", поэтому он также попадёт в список файлов включённых функцией include или другими.
Файлы, добавляемые в скрипт неоднократно, попадут в массив только в одном экземпляре.
Пример #1 Пример использования get_included_files()
<?php
// Этот скрипт расположен в файле abc.php
include 'test1.php';
include_once 'test2.php';
require 'test3.php';
require_once 'test4.php';
$included_files = get_included_files();
foreach ($included_files as $filename) {
echo "$filename\n";
}
?>Результат выполнения данного примера:
/path/to/abc.php /path/to/test1.php /path/to/test2.php /path/to/test3.php /path/to/test4.php
(PHP 4, PHP 5, PHP 7, PHP 8)
get_loaded_extensions — Возвращает массив имён всех скомпилированных и загруженных модулей
$zend_extensions = false): arrayФункция возвращает массив имён всех скомпилированных и загруженных в интерпретаторе PHP модулей.
zend_extensions
Возвращать только модули Zend или обычные модули, такие как mysqli.
По умолчанию false (возврат обычных модулей).
Возвращает индексированный массив имён всех модулей.
Пример #1 Пример использования get_loaded_extensions()
<?php
print_r(get_loaded_extensions());
?>Результатом выполнения данного примера будет что-то подобное:
Array
(
[0] => Core
[1] => date
[2] => libxml
[3] => pcre
[4] => sqlite3
[5] => zlib
[6] => ctype
[7] => dom
[8] => fileinfo
[9] => filter
[10] => hash
[11] => json
[12] => mbstring
[13] => SPL
[14] => PDO
[15] => session
[16] => posix
[17] => Reflection
[18] => standard
[19] => SimpleXML
[20] => pdo_sqlite
[21] => Phar
[22] => tokenizer
[23] => xml
[24] => xmlreader
[25] => xmlwriter
[26] => gmp
[27] => iconv
[28] => intl
[29] => bcmath
[30] => sodium
[31] => Zend OPcache
)
(PHP 4, PHP 5, PHP 7)
get_magic_quotes_gpc — Получение текущего значения настройки конфигурации magic_quotes_gpc
Эта функция УСТАРЕЛА, начиная с PHP 7.4.0 и была УДАЛЕНА, начиная с PHP 8.0.0. Использовать эту функцию крайне не рекомендуется.
Всегда возвращает false.
У этой функции нет параметров.
Всегда возвращает false.
| Версия | Описание |
|---|---|
| 7.4.0 | Функция объявлена устаревшей. |
(PHP 4, PHP 5, PHP 7)
get_magic_quotes_runtime — Получение текущего значения настройки конфигурации magic_quotes_runtime
Эта функция УСТАРЕЛА, начиная с PHP 7.4.0 и была УДАЛЕНА, начиная с PHP 8.0.0. Использовать эту функцию крайне не рекомендуется.
Всегда возвращает false.
У этой функции нет параметров.
Всегда возвращает false.
| Версия | Описание |
|---|---|
| 7.4.0 | Функция объявлена устаревшей. |
Функция является псевдонимом: get_included_files().
(PHP 7, PHP 8)
get_resources — Возвращает активные ресурсы
$type = null): arrayВозвращает массив всех текущих активных ресурсов (resource), опционально отфильтрованный по типу ресурса.
Замечание: Функция предназначена для отладки и тестирования. Функцию не следует использовать в рабочем окружении, особенно для доступа или даже управления ресурсами, которые обычно недоступны (например, базовый ресурс потока экземпляров SplFileObject).
typeЕсли задано, то get_resources() вернёт только ресурсы указанного типа. Список доступных типов ресурсов.
Если в качестве типа задана строка Unknown, то будут возвращены
только ресурсы неизвестного типа.
Если не задано, то будут возвращены все ресурсы.
Возвращает массив текущих активных ресурсов, проиндексированных по номеру ресурса.
| Версия | Описание |
|---|---|
| 8.0.0 |
type теперь допускает значение null.
|
Пример #1 Пример использования get_resources()
<?php
$fp = tmpfile();
var_dump(get_resources());
?>Результатом выполнения данного примера будет что-то подобное:
array(1) {
[1]=>
resource(1) of type (stream)
}
Пример #2 Пример использования get_resources() с фильтрацией
<?php
$fp = tmpfile();
var_dump(get_resources('stream'));
var_dump(get_resources('curl'));
?>Результатом выполнения данного примера будет что-то подобное:
array(1) {
[1]=>
resource(1) of type (stream)
}
array(0) {
}
(PHP 4, PHP 5, PHP 7, PHP 8)
getenv — Получает значение одной или всех переменных окружения
$name = null, bool $local_only = false): string|array|falseПолучает значение одной или всех переменных окружения.
Список всех переменных окружения можно посмотреть с помощью функции phpinfo(). Многие из этих переменных есть в документе » RFC 3875, по большей части в разделе 4.1, "Request Meta-Variables".
name
Имя переменной в виде строки (string) или null.
local_only
Если установлено значение true, возвращаются только локальные переменные окружения,
установленные операционной системой или командой putenv.
Это имеет значение только в том случае, если параметр name
является строкой (string).
Возвращает значение переменной окружения name
или false, если переменная окружения name не существует.
Если name равно null, возвращаются все переменные окружения
в виде ассоциативного массива (array).
| Версия | Описание |
|---|---|
| 8.0.0 |
Параметр name теперь допускает значение null.
|
| 7.1.0 |
Параметр name теперь может быть опущен для получения ассоциативного массива (array) всех переменных окружения.
|
| 7.0.9 |
Был добавлен параметр local_only.
|
Пример #1 Пример использования getenv()
<?php
// Пример использования getenv()
$ip = getenv('REMOTE_ADDR');
// Можно ещё воспользоваться суперглобальной переменной ($_SERVER или $_ENV)
$ip = $_SERVER['REMOTE_ADDR'];
// Гарантированно получаем значение переменной окружения, не обращая внимания,
// была ли она переопределена SAPI или изменена с помощью putenv
$ip = getenv('REMOTE_ADDR', true) ?: getenv('REMOTE_ADDR');
?>
Если PHP запущен в SAPI, например как Fast CGI, эта функция будет возвращать
значения переменных окружения установленных SAPI, даже если вы использовали
putenv() для установки локальной переменной с таким же именем.
Используйте параметр local_only для получения установленных
локально переменных.
(PHP 4, PHP 5, PHP 7, PHP 8)
getlastmod — Получает время последней модификации страницы
Получает время последней модификации запущенного скрипта.
Если требуется получить время модификации произвольного файла, используйте функцию filemtime().
У этой функции нет параметров.
Возвращает время последней модификации текущей страницы. Значение является
меткой времени Unix, подходящая для функции date().
Функция вернёт false в случае возникновения ошибки.
Пример #1 Пример использования getlastmod()
<?php
// Выводит нечто вроде 'Последнее изменение: March 04 1998 20:43:59.'
echo "Последнее изменение: " . date ("F d Y H:i:s.", getlastmod());
?>
(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8)
getmygid — Получить GID владельца скрипта PHP
Получает идентификатор группы текущего скрипта.
У этой функции нет параметров.
Возвращает групповой идентификатор текущего скрипта или false в случае возникновения ошибки.
(PHP 4, PHP 5, PHP 7, PHP 8)
getmyinode — Получает значение inode текущего скрипта
Получает inode текущего скрипта.
У этой функции нет параметров.
Возвращает inode текущего скрипта в виде целого числа или false в случае
ошибки.
(PHP 4, PHP 5, PHP 7, PHP 8)
getmypid — Получение ID процесса PHP
Получает идентификатор процесса PHP.
У этой функции нет параметров.
Возвращает идентификатор процесса PHP или false в случае возникновения ошибки.
Идентификаторы процессов в системе не уникальны, поэтому являются слабым источником энтропии. Мы не рекомендуем полагаться на pid в контекстах, влияющих на безопасность.
(PHP 4, PHP 5, PHP 7, PHP 8)
getmyuid — Получение UID владельца скрипта PHP
Получает идентификатор пользователя текущего скрипта.
У этой функции нет параметров.
Возвращает идентификатор пользователя текущего скрипта или false в случае
ошибки.
(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)
getopt — Получает параметры из списка аргументов командной строки
$short_options, array $long_options = [], int &$rest_index = null): array|falseАнализирует параметры переданные в скрипт.
short_options-).
Например, строка параметров "x" распознается, как
параметр -x.
Допускаются только символы a-z, A-Z и 0-9.
long_options--).
Например, элемент longopts "opt" будет расшифровываться
как --opt.
rest_indexrest_index, то индекс, на котором
остановился разбор, будет записан в него.
Аргумент short_options может содержать следующие элементы:
Замечание: Необязательные значения нельзя отделять от других пробелом
" ".
Значения массива long_options могут содержать:
Замечание:
Форматы
short_optionsиlong_optionsпрактически совпадают. Различие состоит только в том, чтоlong_optionsпринимает массив параметров (в котором каждый элемент является параметром) в то время, какshort_optionsпринимает строку (где параметром является каждый символ).
Функция вернёт массив пар параметров / аргументов или false в случае возникновения ошибки.
Замечание:
Как только встретится первый символ, не являющийся параметром, разбор строки команды будет завершён, а оставшаяся часть строки будет проигнорирована.
| Версия | Описание |
|---|---|
| 7.1.0 |
Добавлен параметр rest_index.
|
Пример #1 Пример использования getopt(): основы
<?php
// Скрипт example.php
$options = getopt("f:hp:");
var_dump($options);
?>shell> php example.php -fvalue -h
Результат выполнения данного примера:
array(2) {
["f"]=>
string(5) "value"
["h"]=>
bool(false)
}
Пример #2 Пример использования getopt(): добавление длинных опций
<?php
// Скрипт example.php
$shortopts = "";
$shortopts .= "f:"; // Обязательное значение
$shortopts .= "v::"; // Необязательное значение
$shortopts .= "abc"; // Эти параметры не принимают никаких значений
$longopts = array(
"required:", // Обязательное значение
"optional::", // Необязательное значение
"option", // Нет значения
"opt", // Нет значения
);
$options = getopt($shortopts, $longopts);
var_dump($options);
?>shell> php example.php -f "value for f" -v -a --required value --optional="optional value" --option
Результат выполнения данного примера:
array(6) {
["f"]=>
string(11) "value for f"
["v"]=>
bool(false)
["a"]=>
bool(false)
["required"]=>
string(5) "value"
["optional"]=>
string(14) "optional value"
["option"]=>
bool(false)
}
Пример #3 Пример использования getopt(): Передача нескольких параметров как одного
<?php
// Скрипт example.php
$options = getopt("abc");
var_dump($options);
?>shell> php example.php -aaac
Результат выполнения данного примера:
array(2) {
["a"]=>
array(3) {
[0]=>
bool(false)
[1]=>
bool(false)
[2]=>
bool(false)
}
["c"]=>
bool(false)
}
Пример #4 Пример getopt() с параметром rest_index
<?php
// Скрипт example.php
$rest_index = null;
$opts = getopt('a:b:', [], $rest_index);
$pos_args = array_slice($argv, $rest_index);
var_dump($pos_args);shell> php example.php -a 1 -b 2 -- test
Результат выполнения данного примера:
array(1) {
[0]=>
string(4) "test"
}
(PHP 4, PHP 5, PHP 7, PHP 8)
getrusage — Получает информацию об использовании текущего ресурса
$mode = 0): array|falseЭто интерфейс к getrusage(2). Функция получает данные, возвращаемые из системного вызова.
mode
Если аргумент mode равен 1, getrusage будет вызвана с
RUSAGE_CHILDREN.
Возвращает ассоциативный массив, содержащий данные возвращённые из системного
вызова. Имена элементов соответствуют документированным именам полей.
Возвращает false в случае возникновения ошибки.
| Версия | Описание |
|---|---|
| 7.0.0 | Добавлен поддержка этой функции в Windows. |
Пример #1 Пример использования getrusage()
<?php
$dat = getrusage();
echo $dat["ru_oublock"]; // количество операций вывода блока
echo $dat["ru_inblock"]; // количество операций приёма блока
echo $dat["ru_msgsnd"]; // количество отправленных сообщений IPC
echo $dat["ru_msgrcv"]; // количество принятых сообщений IPC
echo $dat["ru_maxrss"]; // наибольший размер установленной резидентной памяти
echo $dat["ru_ixrss"]; // суммарное значение размера разделяемой памяти
echo $dat["ru_idrss"]; // суммарное значение размера неразделяемых данных
echo $dat["ru_minflt"]; // количество исправленных страниц (лёгкая ошибка страницы)
echo $dat["ru_majflt"]; // количество ошибочных страниц (тяжёлая ошибка страницы)
echo $dat["ru_nsignals"]; // количество полученных сигналов
echo $dat["ru_nvcsw"]; // количество согласованных переключений контекста
echo $dat["ru_nivcsw"]; // количество несогласованных переключений контекста
echo $dat["ru_nswap"]; // количество свопов
echo $dat["ru_utime.tv_usec"]; // время на задачи пользователя (user time) (микросекунды)
echo $dat["ru_utime.tv_sec"]; // время на задачи пользователя (user time) (секунды)
echo $dat["ru_stime.tv_usec"]; // время на системные задачи (system time) (микросекунды)
echo $dat["ru_stime.tv_sec"]; // время на системные задачи (system time) (секунды)
?>Замечание:
В Windows getrusage() возвращает только следующее:
"ru_stime.tv_sec""ru_stime.tv_usec""ru_utime.tv_sec""ru_utime.tv_usec""ru_majflt"(только еслиmode-RUSAGE_SELF)"ru_maxrss"(только еслиmode-RUSAGE_SELF)Если getrusage() вызвана с
modeравным1(RUSAGE_CHILDREN), то будет собираться информация по использованию ресурсов потоками (что означает, что внутри функция будет вызываться сRUSAGE_THREAD).
Замечание:
В BeOS 2000, возвращается только следующее:
"ru_stime.tv_sec""ru_stime.tv_usec""ru_utime.tv_sec""ru_utime.tv_usec"
Функция является псевдонимом: ini_set().
(PHP 4 >= 4.2.0, PHP 5, PHP 7, PHP 8)
ini_get_all — Получает все настройки конфигурации
$extension = null, bool $details = true): array|falseВозвращает все зарегистрированные настройки конфигурации.
extension
Необязательное имя модуля. Если не null и не строка (string) core,
функция возвращает только параметры.
details
Выводить детальные сведения о настройках или только текущие значения.
По умолчанию true (выводить детальные сведения).
Возвращает ассоциативный массив с именами директив в качестве ключей.
Возвращает false и вызывает ошибку
уровня E_WARNING,
если extension не существует.
Если details равен true (по умолчанию), в массиве будут
содержаться global_value (значение настройки php.ini),
local_value (например, заданное с помощью ini_set()
или .htaccess) и access (уровень доступа).
Если details равен false, значением массива будет
соответствующее текущее значение настройки.
Смотрите соответствующий раздел руководства, в котором приводится описание уровней доступа.
Замечание:
Директива может иметь несколько уровней доступа, в этом случае
accessбудет содержать соответствующую битовую маску.
Пример #1 Примеры использования ini_get_all()
<?php
print_r(ini_get_all("pcre"));
print_r(ini_get_all());
?>Результатом выполнения данного примера будет что-то подобное:
Array
(
[pcre.backtrack_limit] => Array
(
[global_value] => 100000
[local_value] => 100000
[access] => 7
)
[pcre.recursion_limit] => Array
(
[global_value] => 100000
[local_value] => 100000
[access] => 7
)
)
Array
(
[allow_call_time_pass_reference] => Array
(
[global_value] => 0
[local_value] => 0
[access] => 6
)
[allow_url_fopen] => Array
(
[global_value] => 1
[local_value] => 1
[access] => 4
)
...
)
Пример #2 Отключение details
<?php
print_r(ini_get_all("pcre", false)); // Добавлено в PHP 5.3.0
print_r(ini_get_all(null, false)); // Добавлено в PHP 5.3.0
?>Результатом выполнения данного примера будет что-то подобное:
Array
(
[pcre.backtrack_limit] => 100000
[pcre.recursion_limit] => 100000
)
Array
(
[allow_call_time_pass_reference] => 0
[allow_url_fopen] => 1
...
)
Замечание:
ini_get_all() игнорирует опции типа "массив" такие как pdo.dsn.*.
(PHP 4, PHP 5, PHP 7, PHP 8)
ini_get — Получает значение настройки конфигурации
$option): string|falseВ случае успешного выполнения возвращает значение настройки конфигурации.
optionИмя настройки конфигурации.
Возвращает значение настройки конфигурации в виде строки. Для значений
null будет возвращаться пустая строка. Функция вернёт
false, если указанная настройка не существует.
Пример #1 Несколько примеров использования ini_get()
<?php
/*
Наш файл php.ini содержит следующие настройки:
display_errors = On
register_globals = Off
post_max_size = 8M
*/
echo 'display_errors = ' . ini_get('display_errors') . "\n";
echo 'register_globals = ' . ini_get('register_globals') . "\n";
echo 'post_max_size = ' . ini_get('post_max_size') . "\n";
echo 'post_max_size+1 = ' . (ini_get('post_max_size')+1) . "\n";
echo 'post_max_size in bytes = ' . return_bytes(ini_get('post_max_size'));
function return_bytes($val) {
$val = trim($val);
$last = strtolower($val[strlen($val)-1]);
switch($last) {
// Модификатор 'G' доступен
case 'g':
$val *= 1024;
case 'm':
$val *= 1024;
case 'k':
$val *= 1024;
}
return $val;
}
?>Результатом выполнения данного примера будет что-то подобное:
display_errors = 1 register_globals = 0 post_max_size = 8M post_max_size+1 = 9 post_max_size in bytes = 8388608
Замечание: Возвращаемые логические значения
Boolean-значение ini-настройки
offбудет возвращено в виде пустой строки или строки "0", в то время как значениюonбудет соответствовать строка "1". Функция также может возвращать буквенные значения INI-настройки.
Замечание: Возвращаемые значения количества памяти
Многие ini-настройки, значения которых измеряются количеством памяти, такие как upload_max_filesize, сохраняются в php.ini в сокращённом виде. ini_get() вернёт именно то, что записано в файле php.ini, а НЕ целочисленный (int) эквивалент этой величины. Попытка использования полученной величины в арифметических операциях не даст желаемого результата. В приведённом выше примере продемонстрировано, как можно перевести сокращённую запись в число байт.
Замечание:
ini_get() не может прочесть опции типа "массив", такие как pdo.dsn.*, и возвращает
falseтаких случаях.
(PHP 8 >= 8.2.0)
ini_parse_quantity — Get interpreted size from ini shorthand syntax
$shorthand): intВ случае успешного выполнения возвращает интерпретируемый размер в байтах из сокращений байтовых значений.
shorthand
Сокращение байтовых значений для разбора, должно быть числом,
за которым следует необязательный множитель.
Поддерживаются следующие множители: k/K (1024),
m/M (1048576),
g/G (1073741824).
Число может быть десятичным, шестнадцатеричным (с префиксом 0x или 0X),
восьмеричным (с префиксом 0o, 0O или 0)
или двоичным (с префиксом 0b или 0B).
Возвращает интерпретируемый размер в байтах в виде целого числа (int).
Если значение не может быть разобрано или используется недопустимый множитель,
то выдаётся ошибка уровня E_WARNING.
Пример #1 Пример использования ini_parse_quantity()
<?php
var_dump(ini_parse_quantity('1024'));
var_dump(ini_parse_quantity('1024M'));
var_dump(ini_parse_quantity('512K'));
var_dump(ini_parse_quantity('0xFFk'));
var_dump(ini_parse_quantity('0b1010k'));
var_dump(ini_parse_quantity('0o1024'));
var_dump(ini_parse_quantity('01024'));
var_dump(ini_parse_quantity('Foobar'));
var_dump(ini_parse_quantity('10F'));
?>Результатом выполнения данного примера будет что-то подобное:
int(1024) int(1073741824) int(524288) int(261120) int(10240) int(532) int(532) Warning: Invalid quantity "Foobar": no valid leading digits, interpreting as "0" for backwards compatibility int(0) Warning: Invalid quantity "10F": unknown multiplier "F", interpreting as "10" for backwards compatibility int(10)
(PHP 4, PHP 5, PHP 7, PHP 8)
ini_restore — Восстанавливает значение настройки конфигурации
$option): voidВосстанавливает исходное значение настройки конфигурации.
optionИмя настройки.
Функция не возвращает значения после выполнения.
Пример #1 Пример использования ini_restore()
<?php
$setting = 'html_errors';
echo 'Текущее значение настройки \'' . $setting . '\': ' . ini_get($setting), PHP_EOL;
ini_set($setting, ini_get($setting) ? 0 : 1);
echo 'Новое значение настройки \'' . $setting . '\': ' . ini_get($setting), PHP_EOL;
ini_restore($setting);
echo 'Исходное значение настройки \'' . $setting . '\': ' . ini_get($setting), PHP_EOL;
?>Результат выполнения данного примера:
Текущее значение настройки 'html_errors': 1 Новое значение настройки 'html_errors': 0 Исходное значение настройки 'html_errors': 1
(PHP 4, PHP 5, PHP 7, PHP 8)
ini_set — Устанавливает значение настройки конфигурации
$option, string|int|float|bool|null $value): string|falseУстанавливает значение заданной настройки конфигурации. Настройка будет хранить установленное значение пока выполняется скрипт. После завершения работы скрипта значение настройки вернётся к исходному.
option
Не все доступные настройки можно изменять функцией ini_set(). Список доступных настроек приведён в приложении.
valueНовое значение настройки.
В случае успешного выполнения возвращает старое значение или false в случае возникновения ошибки.
| Версия | Описание |
|---|---|
| 8.1.0 |
Параметр value теперь принимает любой скалярный тип (включая null).
Ранее допускались только строковые (string) значения.
|
Пример #1 Установка значения ini-настройки
<?php
echo ini_get('display_errors');
if (!ini_get('display_errors')) {
ini_set('display_errors', '1');
}
echo ini_get('display_errors');
?>
(PHP 5 >= 5.2.0, PHP 7, PHP 8)
memory_get_peak_usage — Возвращает пиковое значение объёма памяти, выделенное PHP
$real_usage = false): intВозвращает максимальный объем памяти в байтах, который был выделен PHP-скрипту.
real_usage
Передача true в качестве этого аргумента позволяет получить реальный объем
памяти, выделенный системой. Если аргумент не задан или равен false,
возвращаются сведения только о памяти, выделенной функцией
emalloc().
Возвращает максимальный объем памяти в байтах.
(PHP 4 >= 4.3.2, PHP 5, PHP 7, PHP 8)
memory_get_usage — Возвращает количество памяти, выделенное для PHP
$real_usage = false): intВозвращает количество памяти в байтах, которое было выделено PHP-скрипту на данный момент.
real_usage
Передача true позволяет узнать реальное количество памяти, выделенной PHP
скрипту системой, включая неиспользуемые страницы. Если аргумент не задан или равен
false, будет возвращено только количество используемой памяти.
Замечание:
PHP не отслеживает память, которая выделялась не
emalloc()
Возвращает количество памяти в байтах.
Пример #1 Пример использования memory_get_usage()
<?php
// Это просто пример, цифры ниже будут
// отличаться в зависимости от вашей системы
echo memory_get_usage() . "\n"; // 36640
$a = str_repeat("Hello", 4242);
echo memory_get_usage() . "\n"; // 57960
unset($a);
echo memory_get_usage() . "\n"; // 36744
?>
(PHP 8 >= 8.2.0)
memory_reset_peak_usage — Сбрасывает пиковое использование памяти
Сбрасывает пиковое использование памяти, возвращаемое функцией memory_get_peak_usage().
У этой функции нет параметров.
Функция не возвращает значения после выполнения.
Пример #1 Пример использования memory_reset_peak_usage()
<?php
var_dump(memory_get_peak_usage());
$a = str_repeat("Hello", 424242);
var_dump(memory_get_peak_usage());
unset($a);
memory_reset_peak_usage();
$a = str_repeat("Hello", 2424);
var_dump(memory_get_peak_usage());
?>Результатом выполнения данного примера будет что-то подобное:
int(422440) int(2508672) int(399208)
(PHP 5 >= 5.2.4, PHP 7, PHP 8)
php_ini_loaded_file — Получить путь к загруженному файлу php.ini
Проверяет, загружен ли файл php.ini, и возвращает его путь.
У этой функции нет параметров.
Путь к загруженному файлу php.ini или false, если файл не загружен.
Пример #1 Пример использования php_ini_loaded_file()
<?php
$inipath = php_ini_loaded_file();
if ($inipath) {
echo 'Загруженный php.ini: ' . $inipath;
} else {
echo 'Файл php.ini не загружен';
}
?>Результатом выполнения данного примера будет что-то подобное:
Loaded php.ini: /usr/local/php/php.ini
(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)
php_ini_scanned_files — Возвращает список .ini-файлов, найденных в дополнительной ini-директории
php_ini_scanned_files() возвращает список разделённых запятыми конфигурационных файлов, проанализированных после php.ini. Директории, в которых производится поиск, задаются при компиляции и, опционально, переменной окружения во время исполнения. Больше информации можно найти в инструкции по установке.
Возвращаемые имена файлов включают полный путь.
У этой функции нет параметров.
При успехе возвращает строку с разделёнными запятыми именами .ini-файлов.
За каждой запятой следует новая строка. Если директива --with-config-file-scan-dir не задана и переменная окружения
PHP_INI_SCAN_DIR тоже не задана, функция вернёт
false. Если директива задана и она пуста, будет возвращена пустая
строка. Если файл не удаётся распознать, он всё же будет включён в список, но
при этом PHP сообщит об ошибке. Эта ошибка будет возникать как при
компиляции, так и во время работы php_ini_scanned_files().
Пример #1 Простой пример вывода списка ini-файлов
<?php
if ($filelist = php_ini_scanned_files()) {
if (strlen($filelist) > 0) {
$files = explode(',', $filelist);
foreach ($files as $file) {
echo "<li>" . trim($file) . "</li>\n";
}
}
}
?>
(PHP 4 >= 4.0.1, PHP 5, PHP 7, PHP 8)
php_sapi_name — Возвращает тип интерфейса между веб-сервером и PHP
Возвращает строку в нижнем регистре, содержащую описание типа интерфейса (Server API, SAPI), который использует PHP. Например, в CLI PHP эта строка будет "cli", в то время как с Apache может быть несколько разных значений в зависимости от конкретного SAPI. Возможные значение приведены ниже.
У этой функции нет параметров.
Возвращает тип интерфейса в виде строки в нижнем регистре или false в случае возникновения ошибки.
Возможные возвращаемые значения (список может быть неполным):
apache,
apache2handler,
cgi (до PHP 5.3),
cgi-fcgi, cli, cli-server,
embed, fpm-fcgi,
litespeed,
phpdbg.
Пример #1 Пример использования php_sapi_name()
В этом примере проверяется подстрока cgi, так как это также
может быть cgi-fcgi.
<?php
$sapi_type = php_sapi_name();
if (substr($sapi_type, 0, 3) == 'cgi') {
echo "Вы используете CGI PHP\n";
} else {
echo "Вы используете не CGI PHP\n";
}
?>Замечание: Альтернативный вариант
Константа PHP
PHP_SAPIхранит то же значение, что и php_sapi_name().
Имя SAPI может определиться неточно, так как, например,
в случае с apache интерфейс может быть определён как
apache2handler.
(PHP 4 >= 4.0.2, PHP 5, PHP 7, PHP 8)
php_uname — Возвращает информацию об операционной системе, на которой запущен PHP
$mode = "a"): string
php_uname() возвращает описание операционной системы,
на которой запущен PHP. Это та же строка, с которой начинается вывод
phpinfo(). Для вывода названия операционной системы
также можно использовать константу PHP_OS, но имейте в виду,
что эта константа содержит название операционной системы, на которой
PHP был собран (built).
На некоторых старых UNIX-платформах получить информацию о текущей ОС может оказаться невозможным. В таких случаях функция выдаст название ОС, на которой PHP был собран. Такое случается, когда библиотека, которой пользуется uname(), недоступна или работает некорректно.
mode
mode - одиночный символ, определяющий,
какая информация будет выводиться:
'a': По умолчанию. Содержит все режимы в
следующей последовательности "s n r v m".
's': Название операционной системы, например,
FreeBSD.
'n': Имя хоста, например,
localhost.example.com.
'r': Номер релиза, например,
5.1.2-RELEASE.
'v': Информация о версии. Может сильно
различаться в разных ОС.
'm': Архитектура процессора, например,
i386.
Возвращает описание ОС в виде строки.
Пример #1 Несколько примеров использования php_uname()
<?php
echo php_uname();
echo PHP_OS;
/* Разные варианты:
Linux localhost 2.4.21-0.13mdk #1 Fri Mar 14 15:08:06 EST 2003 i686
Linux
FreeBSD localhost 3.2-RELEASE #15: Mon Dec 17 08:46:02 GMT 2001
FreeBSD
Windows NT XN1 5.1 build 2600
WINNT
*/
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
echo 'Сервер работает под управлением Windows!';
} else {
echo 'Сервер работает под управлением ОС, отличной от Windows!';
}
?>Ниже приведено несколько Предопределённых PHP-констант, которые могут оказаться полезными:
Пример #2 Некоторые константы OS
<?php
// *nix
echo DIRECTORY_SEPARATOR; // /
echo PHP_SHLIB_SUFFIX; // so
echo PATH_SEPARATOR; // :
// Win*
echo DIRECTORY_SEPARATOR; // \
echo PHP_SHLIB_SUFFIX; // dll
echo PATH_SEPARATOR; // ;
?>
(PHP 4, PHP 5, PHP 7, PHP 8)
phpcredits — Выводит список разработчиков PHP
$flags = CREDITS_ALL): trueЭта функция выводит список разработчиков PHP, модулей и т.д. Она генерирует соответствующий HTML-код для вставки на страницу.
flags
Использование аргумента flags позволяет произвольно
компоновать информацию об отдельных группах разработчиков.
| Имя | Описание |
|---|---|
| CREDITS_ALL |
Все разработчики, эквивалентно использованию:
CREDITS_DOCS +
CREDITS_GENERAL + CREDITS_GROUP +
CREDITS_MODULES + CREDITS_FULLPAGE.
В этом случае будет сгенерирована полностью независимая HTML-страница с
соответствующими тэгами.
|
| CREDITS_DOCS | Участники команды документирования |
| CREDITS_FULLPAGE | Обычно используется в комбинации с другими флагами. Указывает на то, что независимая HTML страница должна содержать информацию других флагов. |
| CREDITS_GENERAL | Главные разработчики: Концепция и дизайн языка, авторы PHP и модуля SAPI. |
| CREDITS_GROUP | Список разработчиков ядра языка |
| CREDITS_MODULES | Список модулей для PHP и их авторов |
| CREDITS_SAPI | Список модулей серверных API и их авторов |
Функция всегда возвращает true.
Пример #1 Выводит основных разработчиков
<?php
phpcredits(CREDITS_GENERAL);
?>
Пример #2 Выводит разработчиков ядра и участников команды документирования
<?php
phpcredits(CREDITS_GROUP | CREDITS_DOCS | CREDITS_FULLPAGE);
?>
Пример #3 Вывод всех разработчиков
<html>
<head>
<title>Сведения об авторах</title>
</head>
<body>
<?php
// какой-то код
phpcredits(CREDITS_ALL - CREDITS_FULLPAGE);
// ещё код
?>
</body>
</html>Замечание:
В режиме работы из командной строки (CLI) phpcredits() выводит обычный текст вместо HTML.
(PHP 4, PHP 5, PHP 7, PHP 8)
phpinfo — Выводит информацию о текущей конфигурации PHP
$flags = INFO_ALL): trueВыводит большое количество информации о текущем состоянии PHP. Сюда входит информация о настройках компиляции PHP, о модулях, о версии, информация о сервере и среде выполнения (если PHP компилировался как модуль), окружении PHP, версии ОС, о путях, об основных и локальных значениях настроек конфигурации, о HTTP-заголовках и лицензии PHP.
Так как каждая система имеет свои особенности, phpinfo() используется в основном для проверки настроек конфигурации и для просмотра доступных предопределённых констант в данной системе.
phpinfo() также используется в целях отладки, так как содержит все данные EGPCS (Environment, GET, POST, Cookie, Server).
flags
Вывод функции можно настраивать, передавая битовую маску из
одной или более приведённых ниже констант (constants).
Эта маска передаётся в качестве необязательного аргумента
flags. Отдельные константы или битовые значения
можно комбинировать с помощью побитового оператора ИЛИ.
| Имя (константа) | Значение | Описание |
|---|---|---|
| INFO_GENERAL | 1 | Строка конфигурации, расположение php.ini, дата сборки, сервер, система и др. |
| INFO_CREDITS | 2 | Разработчики PHP. Смотрите также phpcredits(). |
| INFO_CONFIGURATION | 4 | Текущие значение основных и локальных PHP директив. Смотрите также ini_get(). |
| INFO_MODULES | 8 | Загруженные модули и их настройки. Смотрите также get_loaded_extensions(). |
| INFO_ENVIRONMENT | 16 | Информация о переменных окружения, которая также доступна в $_ENV. |
| INFO_VARIABLES | 32 | Выводит все предопределённые переменные из EGPCS (Environment, GET, POST, Cookie, Server). |
| INFO_LICENSE | 64 | Информация о лицензии PHP. Смотрите также » license FAQ. |
| INFO_ALL | -1 | Выводит все приведённое выше. |
Функция всегда возвращает true.
Пример #1 Пример использования phpinfo()
<?php
// Показывать всю информацию, по умолчанию INFO_ALL
phpinfo();
// Показывать информацию только о загруженных модулях.
// phpinfo(8) выдаёт тот же результат.
phpinfo(INFO_MODULES);
?>Замечание:
В версиях PHP до 5.5, часть информации не выводится, если настройка expose_php установлена в
off. Это PHP и Zend логотипы и информация о разработчиках.
Замечание:
В режиме CLI phpinfo() выводит обычный текст вместо HTML.
(PHP 4, PHP 5, PHP 7, PHP 8)
phpversion — Получает текущую версию PHP
$extension = null): string|falseВозвращает строку с номером версии текущего PHP-интерпретатора или модуля.
extensionНеобязательное имя модуля.
Возвращает текущую версию PHP в виде строки (string).
Если в параметре extension указано строковое значение (string), phpversion()
вернёт версию этого модуля или false, если информации о версии нет или модуль в данный момент не включён.
| Версия | Описание |
|---|---|
| 8.0.0 |
extension теперь допускает значение null.
|
Пример #1 Пример использования phpversion()
<?php
// Выводит строку типа 'Текущая версия PHP: 4.1.1'
echo 'Текущая версия PHP: ' . phpversion();
// Выводит строку типа '2.0' или ничего, если модуль не включён
echo phpversion('tidy');
?>
Пример #2 Пример использования PHP_VERSION_ID
<?php
// PHP_VERSION_ID доступна в версиях PHP 5.2.7 и выше. Если
// наша версия ниже, можно её сэмулировать
if (!defined('PHP_VERSION_ID')) {
$version = explode('.', PHP_VERSION);
define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));
}
// PHP_VERSION_ID определена как число. Чем больше число, тем новее
// PHP. Эта константа задаётся по той же схеме, что приведена выше:
//
// $version_id = $major_version * 10000 + $minor_version * 100 + $release_version;
//
// Теперь с PHP_VERSION_ID можно проверять, какая функциональность есть в
// текущей версии PHP. Не обязательно пользоваться version_compare()
// каждый раз, когда требуется проверить, поддерживает ли PHP нужную
// нам функцию.
//
// Например, мы можем задать значения констант PHP_VERSION_*,
// которые недоступны в версиях ранее 5.2.7
if (PHP_VERSION_ID < 50207) {
define('PHP_MAJOR_VERSION', $version[0]);
define('PHP_MINOR_VERSION', $version[1]);
define('PHP_RELEASE_VERSION', $version[2]);
// и так далее ...
}
?>Замечание:
Эта информация также доступна через предопределённую константу
PHP_VERSION. Более детальную информацию можно получить с помощью константPHP_VERSION_*.
Замечание:
Некоторые модули могут определять свой собственный номер версии. Однако большинство модулей, входящих в комплект поставки, в качестве номера версии используют версию PHP.
(PHP 4, PHP 5, PHP 7, PHP 8)
putenv — Устанавливает значение переменной среды
$assignment): bool
Добавляет assignment в переменные окружения сервера.
Переменная будет существовать только на время выполнения текущего запроса.
По его завершении переменная вернётся в изначальное состояние.
assignment
Установка вида "FOO=BAR"
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Установка значения переменной среды
<?php
putenv("UNIQID=$uniqid");
?>
(PHP 4 >= 4.3.0, PHP 5, PHP 7)
restore_include_path — Восстанавливает изначальное значение настройки конфигурации include_path
Эта функция УСТАРЕЛА, начиная с PHP 7.4.0 и была УДАЛЕНА, начиная с PHP 8.0.0. Использовать эту функцию крайне не рекомендуется.
Восстанавливает исходное значение настройки конфигурации include_path, которое записано в php.ini
У этой функции нет параметров.
Функция не возвращает значения после выполнения.
Пример #1 Пример использования restore_include_path()
<?php
echo get_include_path(); // .:/usr/local/lib/php
set_include_path('/inc');
echo get_include_path(); // /inc
restore_include_path();
// или так
ini_restore('include_path');
echo get_include_path(); // .:/usr/local/lib/php
?>
(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)
set_include_path — Устанавливает значение настройки конфигурации include_path
$include_path): string|falseЗадаёт значение настройки конфигурации include_path на время выполнения скрипта.
Возвращает старое значение include_path
в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Пример использования set_include_path()
<?php
set_include_path('/usr/lib/pear');
// Или так
ini_set('include_path', '/usr/lib/pear');
?>
Пример #2 Составление более длинного пути include path
Используя константу PATH_SEPARATOR, можно добавить
к пути вложенные директории независимо от операционной системы.
В этом примере мы добавим /usr/lib/pear в конец
существующего пути include_path.
<?php
$path = '/usr/lib/pear';
set_include_path(get_include_path() . PATH_SEPARATOR . $path);
?>
(PHP 4, PHP 5, PHP 7, PHP 8)
set_time_limit — Ограничение времени выполнения скрипта
$seconds): bool
Задаёт время в секундах, в течение которого скрипт должен завершить работу.
Если скрипт не успевает, вызывается фатальная ошибка. По умолчанию даётся
30 секунд, либо время, записанное в настройке
max_execution_time в php.ini (если такая настройка
установлена).
При вызове set_time_limit() перезапускает счётчик с нуля.
Другими словами, если время ожидания изначально было 30 секунд, и через 25 секунд
после запуска скрипта будет вызвана функция set_time_limit(20),
то скрипт будет работать максимум 45 секунд.
secondsМаксимальное время выполнения в секундах. Если задан ноль, время выполнения неограниченно.
Возвращает true в случае успешного выполнения, иначе false.
Замечание:
Функция set_time_limit() и директива max_execution_time влияют на время выполнения только самого скрипта. Время, затраченное на различные действия вне скрипта, такие как системные вызовы функции system(), потоковые операции, запросы к базам данных и т.п. не включаются в расчёт времени выполнения скрипта. Это не относится к системам Windows, где рассчитывается абсолютное время выполнения.
(PHP 5 >= 5.2.1, PHP 7, PHP 8)
sys_get_temp_dir — Возвращает путь к директории временных файлов
Возвращает путь к директории, где PHP по умолчанию хранит временные файлы.
У этой функции нет параметров.
Возвращает путь к директории временных файлов.
Пример #1 Пример использования sys_get_temp_dir()
<?php
// Создание временного файла в директории
// временных файлов, используя sys_get_temp_dir()
$temp_file = tempnam(sys_get_temp_dir(), 'Tux');
echo $temp_file;
?>Результатом выполнения данного примера будет что-то подобное:
C:\Windows\Temp\TuxA318.tmp
(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8)
version_compare — Сравнивает две "стандартизованные" строки с номером версии PHP
$version1, string $version2, ?string $operator = null): int|boolversion_compare() сравнивает две "PHP-стандартизованные" строки с номерами версий.
Функция сначала заменяет _, - и
+ на точку . в строках версий, а
также добавляет точки . перед и после каждого символа, не
являющегося числом. Например, '4.3.2RC1' преобразуется в '4.3.2.RC.1'. После этого
сравнивает части строк слева направо. Если часть строки содержит специальные
символы версий, они обрабатываются следующим образом:
любая строка, не найденная в этом списке <
dev < alpha =
a < beta =
b < RC =
rc < # <
pl = p. Таким образом можно сравнивать
не только версии разных уровней, вроде '4.1' и '4.1.2', но и специфичные
версии, включающие статус разработки.
version1Номер первой версии.
version2Номер второй версии.
operator
Необязательный параметр operator.
Возможные значения:
<,
lt, <=,
le, >,
gt, >=,
ge, ==,
=, eq,
!=, <>,
ne.
Аргумент чувствителен к регистру, поэтому значения должны быть в нижнем регистре.
По умолчанию функция version_compare() возвращает
-1, если первая версия меньше второй;
0, когда они равны;
1, если вторая меньше первой.
При использовании аргумента operator функция
вернёт true, если выражение в соответствии с оператором верно, и
false в противном случае.
В примере ниже используется константа PHP_VERSION,
она содержит номер версии PHP, который выполняет код.
Пример #1 Пример использования version_compare()
<?php
if (version_compare(PHP_VERSION, '7.0.0') >= 0) {
echo 'Я использую PHP версии не ниже 7.0.0, моя версия: ' . PHP_VERSION . "\n";
}
if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
echo 'Я использую PHP версии не ниже 5.3.0, моя версия: ' . PHP_VERSION . "\n";
}
if (version_compare(PHP_VERSION, '5.0.0', '>=')) {
echo 'Я использую PHP 5.0.0 или выше, моя версия: ' . PHP_VERSION . "\n";
}
if (version_compare(PHP_VERSION, '5.0.0', '<')) {
echo 'Я до сих пор использую PHP 4, моя версия: ' . PHP_VERSION . "\n";
}
?>Замечание:
Константа
PHP_VERSIONхранит номер текущей версии PHP.
Замечание:
Заметьте, что дорелизные версии, такие как 5.3.0-dev, считаются меньше, чем финальные (вида 5.3.0).
Замечание:
Специальные слова вроде
alphaиbetaчувствительны к регистру. Строки версий, не придерживающиеся PHP-стандарта, нужно приводить к нижнему регистру функцией strtolower() до вызова version_compare().
(PHP 5, PHP 7, PHP 8)
zend_thread_id — Возвращает уникальный идентификатор текущего потока выполнения
Эта функция возвращает уникальный идентификатор текущего потока выполнения.
У этой функции нет параметров.
Возвращает идентификатор потока выполнения в виде целого числа.
Пример #1 Пример использования zend_thread_id()
<?php
$thread_id = zend_thread_id();
echo 'Идентификатор текущего потока выполнения: ' . $thread_id;
?>Результатом выполнения данного примера будет что-то подобное:
Идентификатор текущего потока выполнения: 7864
Замечание:
Эта функция доступна, только если PHP собран с поддержкой ZTS (Zend Thread Safety) и работает в режиме отладки (
--enable-debug).
(PHP 4, PHP 5, PHP 7, PHP 8)
zend_version — Получает версию движка Zend
Возвращает строку с номером версии работающего в данный момент ядра Zend Engine.
У этой функции нет параметров.
Возвращает номер версии Zend Engine в виде строки.
Пример #1 Пример использования zend_version()
<?php
echo "Версия движка Zend: " . zend_version();
?>Результатом выполнения данного примера будет что-то подобное:
Версия движка Zend: 2.2.0
Поскольку phpdbg реализован в виде модуля SAPI, то он может полностью контролировать окружение без воздействия на функциональность и скорость выполнения вашего кода.
Phpdbg претендует на то, чтобы считаться легковесным, мощным и простым в использовании отладчиком для PHP. Он предоставляет следующие возможности:
| Опция | Пример аргумента | Описание |
|---|---|---|
| -c | -c/my/php.ini | Указывает php.ini, который надо загрузить |
| -d | -dmemory_limit=4G | Установка соответствующей директивы php.ini |
| -n | Запрет использования стандартного php.ini | |
| -q | Не показывать приветственный баннер | |
| -v | Разрешить вывод oplog | |
| -b | Запретить использование цветов | |
| -i | -imy.init | Задать файл .phpdbginit |
| -I | Игнорировать стандартный .phpdbginit | |
| -O | -Omy.oplog | Задать файл для записи oplog |
| -r | Запустить контекст исполнения | |
| -rr | Запустить контекст исполнения и выйти после запуска (не обращать внимание на точки останова) | |
| -e | Генерировать расширенную информацию для отладчика/профилировщика | |
| -E | Разрешить пошаговый eval. Будьте осторожны! | |
| -s | -s=, -s=foo | Прочитать код для исполнения из стандартного потока ввода с опциональным разделителем |
| -S | -Scli | Переопределить имя SAPI. Будьте осторожны! |
|
|
||
| -l | -l4000 | Задать порт удалённой консоли |
| -a | -a192.168.0.3 | Задать адрес удалённой консоли |
| -x | Включить вывод в формате xml (вместо стандартного текстового) | |
| -p | -p, -p=func, -p* | Вывести опкоды и выйти |
| -h | Вывести справочный раздел | |
| -V | Напечатать номер версии | |
| -- | -- arg1 arg2 | Используется для разделения аргументов phpdbg и php $argv; любые $argv добавляйте после него |
Поведение этих функций зависит от установок в php.ini.
| Имя | По умолчанию | Место изменения | Список изменений |
|---|---|---|---|
| phpdbg.eol | 2 | PHP_INI_ALL | Удалено, начиная с PHP 8.1.0 |
| phpdbg.path | 6 | Удалено, начиная с PHP 8.1.0 |
Краткое разъяснение конфигурационных директив.
phpdbg.eol
mixed
Тип окончания строки, используемый для вывода. Для установки значения необходимо использовать один из псевдонимов строк.
| int Значение | string Псевдоним |
|---|---|
0 |
CRLF, crlf,
DOS, dos
|
1 |
LF, lf,
UNIX, unix
|
2 |
CR, cr,
MAC, mac
|
phpdbg.path
string
Перечисленные ниже константы определены данным модулем и могут быть доступны только в том случае, если PHP был собран с поддержкой этого модуля или же в том случае, если данный модуль был динамически загружен во время выполнения.
PHPDBG_VERSION
(string)
PHPDBG_FILE
(int)
PHPDBG_METHOD
(int)
PHPDBG_LINENO
(int)
PHPDBG_FUNC
(int)
PHPDBG_COLOR_PROMPT
(int)
PHPDBG_COLOR_NOTICE
(int)
PHPDBG_COLOR_ERROR
(int)
(PHP 5 >= 5.6.3, PHP 7, PHP 8)
phpdbg_break_file — Добавить точку прерывания на конкретную строку файла
$file, int $line): void
Добавляет точку прерывания на строку line файла
file.
fileИмя файла.
lineНомер строки.
Функция не возвращает значения после выполнения.
(PHP 5 >= 5.6.3, PHP 7, PHP 8)
phpdbg_break_function — Добавить точку прерывания на вызов функции
$function): void
Добавляет точку прерывания на вызов функции function.
functionИмя функции.
Функция не возвращает значения после выполнения.
(PHP 5 >= 5.6.3, PHP 7, PHP 8)
phpdbg_break_method — Добавить точку прерывания на вызов метода класса
$class, string $method): void
Добавляет точку прерывания на вызов метода method
класса class.
classИмя класса.
methodИмя метода.
Функция не возвращает значения после выполнения.
(PHP 5 >= 5.6.3, PHP 7, PHP 8)
phpdbg_break_next — Добавить точку прерывания на следующий опкод
Добавляет точку прерывания на следующий опкод.
У этой функции нет параметров.
Функция не возвращает значения после выполнения.
(PHP 5 >= 5.6.0, PHP 7, PHP 8)
phpdbg_clear — Убрать все точки прерывания
Удаляет все заданные ранее точки прерывания. Работает как для заданных с помощью функций phpdbg_break_*(), так и для добавленных вручную через консоль.
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
Функция не возвращает значения после выполнения.
(PHP 5 >= 5.6.0, PHP 7, PHP 8)
phpdbg_color — Задать цвет для элемента
$element, string $color): void
Устанавливает цвет color для элемента element.
element
Одна из констант PHPDBG_COLOR_*.
color
Имя цвета. Одно из: white, red,
green, yellow, blue,
purple, cyan или black.
Опционально можно использовать суффиксы -bold
или -underline.
К примеру white-bold или green-underline.
Функция не возвращает значения после выполнения.
(PHP 7, PHP 8)
phpdbg_end_oplog —
$options = []): ?array
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
options
(PHP 5 >= 5.6.0, PHP 7, PHP 8)
phpdbg_exec — Попытаться задать контекст исполнения
$context): string|bool
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
context
Предыдущий контекст исполнения, если он был задан.
true, если контекст исполнения ранее не был задан.
Если запрос на установку контекста завершится с ошибкой, то будет
возвращено false и вызвана ошибка уровня E_WARNING.
(PHP 7, PHP 8)
phpdbg_get_executable —
$options = []): array
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
options
(PHP 5 >= 5.6.0, PHP 7, PHP 8)
phpdbg_prompt — Установить приглашение командной строки
$string): void
Устанавливает приглашение командной строки как задано в string.
stringСтрока, которая будет использована как приглашение.
Функция не возвращает значения после выполнения.
(PHP 7, PHP 8)
phpdbg_start_oplog —
К настоящему времени эта функция ещё не была документирована; для ознакомления доступен только список аргументов.
У этой функции нет параметров.
Функция не возвращает значения после выполнения.
Модуль runkit7 предоставляет средства для изменения констант, пользовательских функций и пользовательских классов. Также предусмотрены пользовательские суперглобальные переменные.
Этот пакет является форком пакета » runkit, обеспечивающего поддержку PHP 7.
Изменение констант, функций, классов и методов так же как и Пользовательские суперглобальные переменные работает со всеми выпусками PHP 7. Никаких особых требований не требуется.
Этот модуль » PECL не поставляется вместе с PHP.
Информация по установке этого модуля PECL может быть найдена в главе руководства Установка PECL модулей. Дополнительная информация, такая как новые версии, скачивание, исходные файлы, информация о разработчике и CHANGELOG, может быть найдена здесь: » https://pecl.php.net/package/runkit7.
Бинарные файлы Windows (файлы DLL) для этого модуля PECL доступны на сайте PECL.
Поведение этих функций зависит от установок в php.ini.
| Имя | По умолчанию | Место изменения | Список изменений |
|---|---|---|---|
| runkit.superglobal | "" | PHP_INI_PERDIR | |
| runkit.internal_override | "0" | PHP_INI_SYSTEM |
Краткое разъяснение конфигурационных директив.
runkit.superglobal
string
Пример #1 Пользовательские суперглобальные файлы с runkit.superglobal=_FOO,_BAR в php.ini
<?php
function show_values() {
echo "Foo is $_FOO\n";
echo "Bar is $_BAR\n";
echo "Baz is $_BAZ\n";
}
$_FOO = 'foo';
$_BAR = 'bar';
$_BAZ = 'baz';
/* Отобразит foo и bar, но не baz */
show_values();
?>runkit.internal_override
bool
Данный модуль не определяет каких-либо типов ресурсов.
Перечисленные ниже константы определены данным модулем и могут быть доступны только в том случае, если PHP был собран с поддержкой этого модуля или же в том случае, если данный модуль был динамически загружен во время выполнения.
RUNKIT7_IMPORT_FUNCTIONS
(int)
RUNKIT7_IMPORT_CLASS_METHODS
(int)
RUNKIT7_IMPORT_CLASS_CONSTS
(int)
RUNKIT7_IMPORT_CLASS_PROPS
(int)
RUNKIT7_IMPORT_CLASS_STATIC_PROPS
(int)
RUNKIT7_IMPORT_CLASSES
(int)
RUNKIT7_IMPORT_CLASS_*.
RUNKIT7_IMPORT_OVERRIDE
(int)
RUNKIT7_ACC_RETURN_REFERENCE
(int)
RUNKIT7_ACC_PUBLIC
(int)
RUNKIT7_ACC_PROTECTED
(int)
RUNKIT7_ACC_PRIVATE
(int)
RUNKIT7_ACC_STATIC
(int)
RUNKIT7_FEATURE_MANIPULATION
(int)
RUNKIT7_FEATURE_SUPERGLOBALS
(int)
RUNKIT7_FEATURE_SANDBOX
(int)
(PECL runkit7 >= Unknown)
runkit7_constant_add — Аналогичен define(), но также позволяет определить константу класса
constant_name
Имя объявляемой константы. Либо строка для обозначения глобальной константы,
либо classname::constname для определения константы класса.
valueЗначение константы (NULL, Bool, Long, Double, String, Array или Resource).
newVisibility
Видимость константы для констант класса. По умолчанию общедоступный.
Одна из констант RUNKIT7_ACC_*.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PECL runkit7 >= Unknown)
runkit7_constant_redefine — Переопределяет уже определённую константу
constant_name
Константа, которую необходимо переопределить.
Либо имя глобальной константы, либо classname::constname для переопределения константы класса.
valueЗначение, присваиваемое константе.
new_visibility
Новая видимость константы для констант класса.
По умолчанию без изменений.
Одна из констант RUNKIT7_ACC_*.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PECL runkit7 >= Unknown)
runkit7_constant_remove — Удаляет уже определённую константу
$constant_name): boolconstant_name
Константа, которую необходимо удалить.
Либо имя глобальной константы, либо classname::constname для удаления константы класса.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PECL runkit7 >= Unknown)
runkit7_function_add — Добавляет новую функцию, функция аналогична create_function()
$function_name,$argument_list,$code,$return_by_reference = null,$doc_comment = null,$return_type = ?,$is_strict = ?$function_name,$closure,$doc_comment = null,$return_type = ?,$is_strict = ?function_nameИмя создаваемой функции.
argument_listСписок аргументов, разделённых запятыми.
codeКод, составляющий функцию.
closureЗамыкание (closure), определяющее функцию.
return_by_referenceОпределяет, должна ли функция возвращаться по ссылке.
doc_commentДокументальный комментарий функции.
return_typeТип возвращаемого значения функции.
is_strict
Определяет, должна ли функция вести себя так, как если бы она была объявлена в файле с strict_types=1.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Пример использования runkit7_function_add()
<?php
runkit7_function_add('testme','$a,$b','echo "Значение A - $a\n"; echo "Значение B - $b\n";');
testme(1,2);
?>Результат выполнения данного примера:
Значение A - 1 Значение B - 2
(PECL runkit7 >= Unknown)
runkit7_function_copy — Копирует функцию в новое имя функции
$source_name, string $target_name): boolsource_nameИмя существующей функции.
target_nameИмя новой функции, в которую нужно скопировать определение.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Пример использования runkit7_function_copy()
<?php
function original() {
echo "В функции\n";
}
runkit7_function_copy('original','duplicate');
original();
duplicate();
?>Результат выполнения данного примера:
В функции В функции
(PECL runkit7 >= Unknown)
runkit7_function_redefine — Заменяет определение функции новой реализацией
$function_name,$argument_list,$code,$return_by_reference = null,$doc_comment = null,$return_type = ?,$is_strict = ?$function_name,$closure,$doc_comment = null,$return_type = ?,$is_strict = ?Замечание: По умолчанию, только пользовательские функции могут быть удалены, переименованы или изменены. Для перекрытия внутренних функций, необходимо включить в php.ini опцию
runkit.internal_override.
function_nameИмя функции для переопределения.
argument_listНовый список аргументов, принимаемых функцией.
codeРеализация нового кода.
closureЗамыкание (closure), определяющее функцию.
return_by_referenceОпределяет, должна ли функция возвращаться по ссылке.
doc_commentДокументальный комментарий функции.
return_typeТип возвращаемого значения функции.
is_strict
Определяет, должна ли функция вести себя так, как если бы она была объявлена в файле с strict_types=1.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Пример использования runkit7_function_redefine()
<?php
function testme() {
echo "Оригинальная реализация Testme\n";
}
testme();
runkit7_function_redefine('testme','','echo "Новая реализация Testme\n";');
testme();
?>Результат выполнения данного примера:
Оригинальная реализация Testme Новая реализация Testme
(PECL runkit7 >= Unknown)
runkit7_function_remove — Удаляет определение функции
$function_name): boolЗамечание: По умолчанию, только пользовательские функции могут быть удалены, переименованы или изменены. Для перекрытия внутренних функций, необходимо включить в php.ini опцию
runkit.internal_override.
function_nameИмя удаляемой функции.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PECL runkit7 >= Unknown)
runkit7_function_rename — Изменяет имя функции
$source_name, string $target_name): boolЗамечание: По умолчанию, только пользовательские функции могут быть удалены, переименованы или изменены. Для перекрытия внутренних функций, необходимо включить в php.ini опцию
runkit.internal_override.
source_nameТекущее имя функции.
target_nameНовое имя функции.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PECL runkit7 >= Unknown)
runkit7_import — Обрабатывает функцию импорта файла PHP и определения классов, при необходимости перезаписывая
Функционал был удалён в PECL runkit7 4.0.0.
$filename, int $flags = ?): bool
Функция подобна include. Однако любой код, находящийся за пределами функции или класса, просто игнорируется.
Кроме того, в зависимости от значения flags, любые функции или классы,
которые уже существуют в текущей запущенной среде, могут быть автоматически перезаписаны их новыми определениями.
filenameИмя файла для импорта определений функций и классов.
flags
Побитовое ИЛИ констант RUNKIT7_IMPORT_*.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PECL runkit7 >= Unknown)
runkit7_method_add — Динамически добавляет новый метод в заданный класс
$class_name,$method_name,$argument_list,$code,$flags = RUNKIT7_ACC_PUBLIC,$doc_comment = null,$return_type = ?,$is_strict = ?$class_name,$method_name,$closure,$flags = RUNKIT7_ACC_PUBLIC,$doc_comment = null,$return_type = ?,$is_strict = ?class_nameКласс, в котором нужно добавить метод.
method_nameИмя метода, который нужно добавить.
argument_listРазделённый запятыми список аргументов для нового метода.
code
Код, который будет выполняться
при вызове method_name.
closureЗамыкание (closure), определяющее метод.
flags
Метод может быть
RUNKIT7_ACC_PUBLIC,
RUNKIT7_ACC_PROTECTED или
RUNKIT7_ACC_PRIVATE, и, при необходимости,
объединён с помощью побитового ИЛИ с
RUNKIT7_ACC_STATIC.
doc_commentДокументальный комментарий метода.
return_typeТип возвращаемого значения метода.
is_strict
Определяет, будет ли метод вести себя так,
как если бы он был объявлен в файле с strict_types=1.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Пример использования runkit7_method_add()
<?php
class Example {
function foo() {
echo "foo!\n";
}
}
// создание объекта Example
$e = new Example();
// добавление нового общедоступного метода
runkit7_method_add(
'Example',
'add',
'$num1, $num2',
'return $num1 + $num2;',
RUNKIT7_ACC_PUBLIC
);
// добавление 12 + 4
echo $e->add(12, 4);
?>Результат выполнения данного примера:
16
(PECL runkit7 >= Unknown)
runkit7_method_copy — Копирует метод из одного класса в другой
$destination_class,$destination_method_name,$source_class,$source_method_name = ?destination_classЦелевой класс для скопированного метода.
destination_method_nameНазвание метода назначения.
source_classИсходный класс скопированного метода.
source_method_name
Имя метода для копирования из исходного класса.
Если этот параметр опущен, предполагается значение destination_method_name.
Пример #1 Пример использования runkit7_method_copy()
<?php
class Foo {
function example() {
return "foo!\n";
}
}
class Bar {
// изначально никаких методов
}
// копирование метода example() из класса Foo в класс Bar как baz()
runkit7_method_copy('Bar', 'baz', 'Foo', 'example');
// функция вывода скопирована
echo Bar::baz();
?>Результат выполнения данного примера:
foo!
(PECL runkit7 >= Unknown)
runkit7_method_redefine — Динамически изменяет код заданного метода
$class_name,$method_name,$argument_list,$code,$flags = RUNKIT7_ACC_PUBLIC,$doc_comment = null,$return_type = ?,$is_strict = ?$class_name,$method_name,$closure,$flags = RUNKIT7_ACC_PUBLIC,$doc_comment = null,$return_type = ?,$is_strict = ?class_nameКласс, в котором нужно переопределить метод.
method_nameИмя метода, который нужно переопределить.
argument_listРазделённый запятыми список аргументов для переопределённого метода.
code
Новый код, который будет выполняться
при вызове method_name.
closureЗамыкание (closure), определяющее метод.
flags
Переопределённый метод может быть
RUNKIT7_ACC_PUBLIC,
RUNKIT7_ACC_PROTECTED или
RUNKIT7_ACC_PRIVATE, и, при необходимости,
объединён с помощью побитового ИЛИ с
RUNKIT7_ACC_STATIC.
doc_commentДокументальный комментарий метода.
return_typeТип возвращаемого значения метода.
is_strict
Определяет, будет ли метод вести себя так,
как если бы он был объявлен в файле с strict_types=1.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Пример использования runkit7_method_redefine()
<?php
class Example {
function foo() {
return "foo!\n";
}
}
// создание объекта Example
$e = new Example();
// вывод Example::foo() (до переопределения)
echo "До: " . $e->foo();
// Переопределение метода 'foo'
runkit7_method_redefine(
'Example',
'foo',
'',
'return "bar!\n";',
RUNKIT7_ACC_PUBLIC
);
// вывод Example::foo() (после переопределения)
echo "После: " . $e->foo();
?>Результат выполнения данного примера:
До: foo! После: bar!
(PECL runkit7 >= Unknown)
runkit7_method_remove — Динамически удаляет заданный метод
$class_name, string $method_name): boolЗамечание: Эта функция не может быть использована для влияния на работающие в данный момент (или цепные) методы.
class_nameКласс, в котором нужно удалить метод.
method_nameИмя удаляемого метода.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Пример использования runkit7_method_remove()
<?php
class Example {
function foo() {
return "foo!\n";
}
function bar() {
return "bar!\n";
}
}
// Remove the 'foo' method
runkit7_method_remove(
'Example',
'foo'
);
echo implode(' ', get_class_methods('Example'));
?>Результат выполнения данного примера:
bar
(PECL runkit7 >= Unknown)
runkit7_method_rename — Динамически изменяет имя заданного метода
$class_name, string $source_method_name, string $target_method_name): boolЗамечание: Эта функция не может быть использована для влияния на работающие в данный момент (или цепные) методы.
class_nameКласс, в котором нужно переименовать метод.
source_method_nameМетод, который нужно переименовать.
target_method_nameНовое имя метода.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Пример использования runkit7_method_rename()
<?php
class Example {
function foo() {
return "foo!\n";
}
}
// Переименование метода 'foo' в 'bar'
runkit7_method_rename(
'Example',
'foo',
'bar'
);
// Вывод переименованной функции
echo (new Example)->bar();
?>Результат выполнения данного примера:
foo!
(PECL runkit7 >= Unknown)
runkit7_object_id — Возвращает дескриптор целочисленного объекта для данного объекта
$obj): intФункция эквивалентна spl_object_id().
Функция возвращает уникальный идентификатор объекта. Идентификатор объекта уникален на протяжении всего времени существования объекта. После уничтожения объекта его идентификатор может быть повторно использован для других объектов. Поведение похоже на spl_object_hash().
objЛюбой объект.
Целочисленный идентификатор, уникальный для каждого существующего в данный момент объекта и всегда одинаковый для каждого объекта.
Замечание:
Когда объект уничтожен, его идентификатор может быть повторно использован для других объектов.
(PECL runkit7 >= Unknown)
runkit7_superglobals — Возвращает числовой индексированный массив зарегистрированных суперглобальных переменных
У этой функции нет параметров.
Возвращает числовой индексированный массив зарегистрированных суперглобальных переменных. Например: _GET, _POST, _REQUEST, _COOKIE, _SESSION, _SERVER, _ENV, _FILES.
(PECL runkit7 >= Unknown)
runkit7_zval_inspect — Возвращает информацию о переданном значении с типами данных, количеством ссылок и так далее
$value): arrayvalueЗначение, чтобы вернуть представление.
Массив, возвращаемый этой функцией, содержит следующие элементы:
addressrefcount (необязательный)is_ref (необязательный)type
Пример #1 Пример использования runkit7_zval_inspect()
<?php
$var = new DateTime();
var_dump(runkit7_zval_inspect($var));
$var = 1;
var_dump(runkit7_zval_inspect($var));
?>Результат выполнения данного примера:
array(4) {
["address"]=>
string(14) "0x7f45ab21b1e0"
["refcount"]=>
int(2)
["is_ref"]=>
bool(false)
["type"]=>
int(8)
}
array(2) {
["address"]=>
string(14) "0x7f45ab21b1e0"
["type"]=>
int(4)
}
Модуль uopz (User Operations for Zend) предоставляет функциональность Zend Engine, обычно используемую во время компиляции и выполнении, чтобы разрешить модификацию внутренних структур, представляющих PHP-код, и для взаимодействия пользовательского кода с виртуальной машиной.
uopz поддерживает следующие действия:
Замечание:
Все поддерживаемые действия совместимы с opcache
PECL uopz 6.1.1 несовместим с Xdebug >= 2.9.4. Более поздние версии uopz несовместимы с Xdebug < 2.9.4.
Для uopz 5.0 требуется PHP 7.0. Начиная с uopz 5.1 требуется PHP 7.1+.
Релизы uopz распространяются через PECL, а исходный код находится на » github, самый простой путь к установке - через PECL: » https://pecl.php.net/package/uopz.
Пользователи Windows могут загрузить готовый исполняемый релиз с сайта » PECL.
Начиная с 5.0.0, модуль должен загружаться как обычный модуль PHP (extension). Ранее его надо было загружать как zend_extension.
Поведение этих функций зависит от установок в php.ini.
| Имя | По умолчанию | Место изменения | Список изменений |
|---|---|---|---|
| uopz.disable | "0" | PHP_INI_SYSTEM | Доступно начиная с uopz 5.0.2 |
| uopz.exit | "0" | PHP_INI_SYSTEM | Доступно начиная с uopz 6.0.1 |
| uopz.overloads | "1" | PHP_INI_SYSTEM | Доступно начиная с uopz 2.0.2. Удалено начиная с uopz 5.0.0. |
Краткое разъяснение конфигурационных директив.
uopz.disable
bool
Если включено, uopz перестанет влиять на работу PHP.
uopz.exit
bool
Позволять ли модулю исполнять опкод exit(выход). Эта настройка может быть переопределена во время исполнения с помощью функции uopz_allow_exit().
uopz.overloads
bool
Даёт возможность использовать uopz_overload().
Замечание: При работе с включённым OPcache может потребоваться отключить все оптимизации OPcache (
opcache.optimization_level=0).
Данный модуль не определяет каких-либо типов ресурсов.
Перечисленные ниже константы определены данным модулем и могут быть доступны только в том случае, если PHP был собран с поддержкой этого модуля или же в том случае, если данный модуль был динамически загружен во время выполнения.
Следующие опкоды определяются как константы с помощью uopz до версии 5.0.0:
ZEND_EXIT
(int)
true для выхода, false для продолжения
ZEND_NEW
(int)
ZEND_THROW
(int)
ZEND_FETCH_CLASS
(int)
ZEND_ADD_TRAIT
(int)
ZEND_ADD_INTERFACE
(int)
ZEND_INSTANCEOF
(int)
Следующие константы управляют поведением виртуальной машины после вызова обработчика пользователя, будьте предельно осторожны! Эти константы удалены с uopz версии 5.0.0.
ZEND_USER_OPCODE_CONTINUE
(int)
ZEND_USER_OPCODE_ENTER
(int)
ZEND_USER_OPCODE_LEAVE
(int)
ZEND_USER_OPCODE_DISPATCH
(int)
ZEND_USER_OPCODE_DISPATCH_TO
(int)
ZEND_USER_OPCODE_RETURN
(int)
Следующие модификаторы регистрируются как константы uopz
ZEND_ACC_PUBLIC
(int)
ZEND_ACC_PROTECTED
(int)
ZEND_ACC_PRIVATE
(int)
ZEND_ACC_STATIC
(int)
ZEND_ACC_FINAL
(int)
ZEND_ACC_ABSTRACT
(int)
ZEND_ACC_CLASS
(int)
ZEND_ACC_INTERFACE
(int)
ZEND_ACC_TRAIT
(int)
ZEND_ACC_FETCH
(int)
(PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_add_function — Добавляет несуществующую функцию или метод
$class,$function,$handler,&$flags = ZEND_ACC_PUBLIC,&$all = trueДобавляет несуществующую функцию или метод.
classИмя класса.
functionИмя функции или метода.
handlerОбъект Closure, который определяет новую функцию или метод.
flagsФлаги для установки новой функции или метода.
all
Будут ли затронуты все классы, которые происходят от класса (class).
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
uopz_add_function() выбрасывает RuntimeException, если добавляемая функция или метод уже существует.
Пример #1 Простое использование uopz_add_function()
<?php
uopz_add_function('foo', function () {echo 'bar';});
foo();
?>Результат выполнения данного примера:
bar
(PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_allow_exit — Позволяет управлять отключённым опкодом exit
$allow): voidПо умолчанию uopz отключает опкод exit, поэтому вызовы exit() практически игнорируются. uopz_allow_exit() позволяет контролировать это поведение.
allowРазрешить выполнение опкодов exit или нет.
Функция не возвращает значения после выполнения.
Пример #1 Пример использования uopz_allow_exit()
<?php
exit(1);
echo 1;
uopz_allow_exit(true);
exit(2);
echo 2;
?>Результат выполнения данного примера:
1
OPcache оптимизирует мёртвый код после безусловного завершения.
(PECL uopz 1 >= 1.0.3, PECL uopz 2)
uopz_backup — Резервирует функцию
Эта функция была УДАЛЕНА в PECL uopz 5.0.0.
$function): void$class, string $function): voidРезервирует функцию во время выполнения, которая будет восстановлена при завершении работы скрипта
classИмя класса, содержащего функцию для резервирования
functionИмя функции
Пример #1 Пример использования uopz_backup()
<?php
uopz_backup("fgets");
uopz_function("fgets", function(){
return true;
});
var_dump(fgets());
?>Результат выполнения данного примера:
bool(true)
(PECL uopz 1, PECL uopz 2)
uopz_compose — Составить класс
Эта функция была УДАЛЕНА в PECL uopz 5.0.0.
$name,$classes,$methods = ?,$properties = ?,$flags = ?Создаёт класс заданного имени, который реализует, наследует или использует все предоставленные классы
nameКорректное имя класса
classesМассив имён классов, интерфейсов и трейтов
methodsАссоциативный массив методов, где значения либо замыкания, либо представлены структурой [модификаторы => замыкание]
propertiesАссоциативный массив свойств, где ключи - имена, а значения - модификаторы
flagsТип записи, по умолчанию ZEND_ACC_CLASS
Пример #1 Пример использования uopz_compose()
<?php
class myClass {}
trait myTrait {}
interface myInterface {}
uopz_compose(
Composed::class, [
myClass::class,
myTrait::class,
myInterface::class
], [
"__construct" => function() {
/* ... */
}
]);
var_dump(
class_uses(Composed::class),
class_parents(Composed::class),
class_implements(Composed::class));
?>Результат выполнения данного примера:
array(1) {
["myTrait"]=>
string(7) "myTrait"
}
array(1) {
["myClass"]=>
string(7) "myClass"
}
array(1) {
["myInterface"]=>
string(11) "myInterface"
}
(PECL uopz 1 >= 1.0.4, PECL uopz 2)
uopz_copy — Скопировать функцию
Эта функция была УДАЛЕНА в PECL uopz 5.0.0.
Скопировать функцию по имени
classИмя класса, содержащего функцию для копирования
functionИмя функции
Объект Closure для определённой функции
Пример #1 Пример использования uopz_copy()
<?php
$strtotime = uopz_copy('strtotime');
uopz_function("strtotime", function($arg1, $arg2) use($strtotime) {
/* зесь можно вызвать оригинальную функцию strtotime */
var_dump($arg1);
});
var_dump(strtotime('dummy'));
?>Результат выполнения данного примера:
string(5) "dummy"
(PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_del_function — Удаляет ранее добавленную функцию или метод
$function): bool$class, string $function, int &$all = true): boolУдаляет ранее добавленную функцию или метод.
classИмя класса.
functionИмя функции или метода.
all
Будут ли затронуты все классы, которые происходят от класса (class).
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
uopz_del_function() выбрасывает RuntimeException, если удаляемые функция или метод не были добавлены с помощью uopz_add_function().
Пример #1 Простое использование uopz_del_function()
<?php
uopz_add_function('foo', function () {echo 'bar';});
var_dump(function_exists('foo'));
uopz_del_function('foo');
var_dump(function_exists('foo'));
?>Результат выполнения данного примера:
bool(true) bool(false)
(PECL uopz 1, PECL uopz 2)
uopz_delete — Удалить функцию
Эта функция была УДАЛЕНА в PECL uopz 5.0.0.
$function): void$class, string $function): voidУдаляет функцию или метод
class
function
Пример #1 Пример использования uopz_delete()
<?php
uopz_delete("strlen");
echo strlen("Hello World");
?>Результатом выполнения данного примера будет что-то подобное:
PHP Fatal error: Call to undefined function strlen() in /path/to/script.php on line 4
Пример #2 Пример использования uopz_delete() с классом
<?php
class My {
public static function strlen($arg) {
return strlen($arg);
}
}
uopz_delete(My::class, "strlen");
echo My::strlen("Hello World");
?>Результатом выполнения данного примера будет что-то подобное:
PHP Fatal error: Call to undefined method My::strlen() in /path/to/script.php on line 10
(PECL uopz 1, PECL uopz 2, PECL uopz 5, PECL uopz 6, PECL uopz 7 < 7.1.0)
uopz_extend — Расширить класс во время выполнения
$class, string $parent): bool
Расширяет текущий класс class родительским parent
classНазвание класса для расширения
parentНазвание класса для наследования
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Начиная с PHP 7.4.0, uopz_extends() выбрасывает RuntimeException,
если OPcache включён
и запись класса либо class,
либо parent (если это признак) неизменны.
Пример #1 Пример использования uopz_extend()
<?php
class A {}
class B {}
uopz_extend(A::class, B::class);
var_dump(class_parents(A::class));
?>Результат выполнения данного примера:
array(1) {
["B"]=>
string(1) "B"
}
(PECL uopz 2 >= 2.0.2, PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_flags — Получить или установить флаги для функции или класса
$function, int $flags = PHP_INT_MAX): int$class, string $function, int $flags = PHP_INT_MAX): intПолучить или установить флаги для записи функции или класса во время выполнения
classИмя класса
function
Имя функции. Если задан class и пустая строка
передана как function, uopz_flags()
получает или устанавливает флаги записи класса.
flagsКорректный набор флагов ZEND_ACC_. Если не заданы, uopz_flags() используется как геттер.
При установке новых флагов, возвращает старые флаги, иначе возвращает текущие флаги
Начиная с PHP 7.4.0, если передан параметр flags,
uopz_extends() выбрасывает RuntimeException,
если OPcache включён
и запись класса либо class,
либо parent (если это признак) неизменны.
| Версия | Описание |
|---|---|
| PECL uopz 5.0.0 |
Параметр flags теперь необязательный. Ранее
ZEND_ACC_FETCH должен был передаваться, чтобы uopz_flags()
использовался как геттер.
|
Пример #1 Пример использования uopz_flags()
<?php
class Test {
public function method() {
return __CLASS__;
}
}
$flags = uopz_flags("Test", "method");
var_dump((bool) (uopz_flags("Test", "method") & ZEND_ACC_PRIVATE));
var_dump((bool) (uopz_flags("Test", "method") & ZEND_ACC_STATIC));
var_dump(uopz_flags("Test", "method", $flags|ZEND_ACC_STATIC|ZEND_ACC_PRIVATE));
var_dump((bool) (uopz_flags("Test", "method") & ZEND_ACC_PRIVATE));
var_dump((bool) (uopz_flags("Test", "method") & ZEND_ACC_STATIC));
?>Результат выполнения данного примера:
bool(false) bool(false) int(1234567890) bool(true) bool(true)
Пример #2 "Отменить final" класса
<?php
final class MyClass
{
}
$flags = uopz_flags(MyClass::class, '');
uopz_flags(MyClass::class, '', $flags & ~ZEND_ACC_FINAL);
var_dump((new ReflectionClass(MyClass::class))->isFinal());
?>Результат выполнения данного примера:
bool(false)
(PECL uopz 1, PECL uopz 2)
uopz_function — Создаёт функцию во время выполнения
Эта функция была УДАЛЕНА в PECL uopz 5.0.0.
Создаёт функцию во время выполнения
classИмя класса для получения новой функции
functionИмя функции
handlerЗамыкание для функции
modifiersМодификаторы для функции, по умолчанию скопированы или ZEND_ACC_PUBLIC
Пример #1 Пример использования uopz_function()
<?php
uopz_function("my_strlen", function($arg) {
return strlen($arg);
});
echo my_strlen("Привет, Мир");
?>Результат выполнения данного примера:
11
Пример #2 Пример использования uopz_function() с классом
<?php
class My {}
uopz_function(My::class, "strlen", function($arg) {
return strlen($arg);
}, ZEND_ACC_STATIC);
echo My::strlen("Привет, Мир");
?>Результат выполнения данного примера:
11
(PECL uopz 5, PECL uopz , PECL uopz 7)
uopz_get_exit_status — Получить последний установленный статус выхода
Получает последний установленный статус выхода, то есть значение, переданное в exit().
У этой функции нет параметров.
Эта функция возвращает последний статус выхода или null, если exit()
не был вызван.
Пример #1 Пример использования uopz_get_exit_status()
<?php
exit(123);
echo uopz_get_exit_status();?>Результат выполнения данного примера:
123
OPcache оптимизирует мёртвый код после безусловного завершения.
(PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_get_hook — Получает ранее установленный обработчик на функцию или метод
Получает ранее установленный обработчик на функцию или метод.
classИмя класса.
functionИмя функции или метода.
Возвращает ранее установленный обработчик на функцию или метод, либо null, если
обработчик не был установлен.
Пример #1 Простое использование uopz_get_hook()
<?php
function foo() {
echo 'foo';
}
uopz_set_hook('foo', function () {echo 'bar';});
var_dump(uopz_get_hook('foo'));
?>Результатом выполнения данного примера будет что-то подобное:
object(Closure)#2 (0) {
}
(PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_get_mock — Получить текущий имитатор (mock) для класса
classНазвание имитированного класса
Либо строка, содержащая название имитатора, либо объект,
либо null, если имитатор не задан.
Пример #1 Пример использования uopz_get_mock()
<?php
class A {
public static function who() {
echo "A";
}
}
class mockA {
public static function who() {
echo "mockA";
}
}
uopz_set_mock(A::class, mockA::class);
echo uopz_get_mock(A::class);
?>Результат выполнения данного примера:
mockA
(PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_get_property — Получает значение класса или свойство экземпляра
Устанавливает значение существующего статического свойства класса,
если указан класс (class),
либо значение существующего свойства экземпляра, если передан экземпляр (instance).
classИмя класса.
instanceЭкземпляр объекта.
propertyИмя свойства.
Возвращает значение класса или свойство экземпляра,
либо null, если свойство не определено.
Пример #1 Простое использование uopz_get_property()
<?php
class Foo {
private static $staticBar = 10;
private $bar = 100;
}
$foo = new Foo;
var_dump(uopz_get_property('Foo', 'staticBar'));
var_dump(uopz_get_property($foo, 'bar'));
?>Результатом выполнения данного примера будет что-то подобное:
int(10) int(100)
(PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_get_return — Получает предыдущее установленное возвращаемое значение для функции
Получает возвращаемое значение function, ранее установленное с помощью uopz_set_return().
classИмя класса, содержащего функцию
functionИмя функции
Ранее установленное возвращаемое значение или объект Closure.
Пример #1 Пример использования uopz_get_return()
<?php
uopz_set_return("strlen", 42);
echo uopz_get_return("strlen");
?>Результат выполнения данного примера:
42
(PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_get_static — Возвращает статические переменные из области видимости функции или метода
$class, string $function): array$function): arrayВозвращает статические переменные из области видимости функции или метода.
classИмя класса.
functionИмя функции или метода.
Возвращает ассоциативный массив (array) имён переменных,
сопоставленный с их текущим значениям в случае успешного выполнения,
либо null, если функция или метод не существуют.
Пример #1 Простое использование uopz_get_static()
<?php
function foo() {
static $bar = 'baz';
}
var_dump(uopz_get_static('foo'));
?>Результат выполнения данного примера:
array(1) {
["bar"]=>
string(3) "baz"
}
(PECL uopz 1, PECL uopz 2, PECL uopz 5, PECL uopz 6, PECL uopz 7 < 7.1.0)
uopz_implement — Реализует интерфейс во время выполнения
$class, string $interface): bool
Делает class, реализующий interface
class
interface
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Начиная с PHP 7.4.0, uopz_implements() выбрасывает RuntimeException,
если OPcache включён
и запись класса class неизменна.
Пример #1 Пример использования uopz_implement()
<?php
interface myInterface {}
class myClass {}
uopz_implement(myClass::class, myInterface::class);
var_dump(class_implements(myClass::class));
?>Результат выполнения данного примера:
array(1) {
["myInterface"]=>
string(11) "myInterface"
}
(PECL uopz 1, PECL uopz 2)
uopz_overload — Перегрузить опкод VM
Эта функция была УДАЛЕНА в PECL uopz 5.0.0.
Перегружает определённый opcode с помощью пользовательской функции
opcodeКорректный опкод, смотрите константы для получения поддерживаемых опкодов
callable
Пример #1 Пример использования uopz_overload()
<?php
uopz_overload(ZEND_EXIT, function(){});
exit();
echo "Привет, Мир";
?>Результат выполнения данного примера:
Привет, Мир
(PECL uopz 1, PECL uopz 2, PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_redefine — Переопределить константу
Переопределяет заданную константу constant на значение value
classИмя класса, содержащего константу
constantИмя константы
valueНовое значение константы, должно быть корректным типом для постоянной переменной
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Пример использования uopz_redefine()
<?php
define("MY", 100);
uopz_redefine("MY", 1000);
echo MY;
?>Результат выполнения данного примера:
1000
(PECL uopz 1, PECL uopz 2)
uopz_rename — Переименовать функцию во время выполнения
Эта функция была УДАЛЕНА в PECL uopz 5.0.0.
$function, string $rename): void$class, string $function, string $rename): void
Переименовывает функцию function на rename
Замечание:
Если обе функции существуют, эта функция по сути поменяет имена
classИмя класса, содержащего функцию
functionИмя существующей функции
renameНовое имя функции
Пример #1 Пример использования uopz_rename()
<?php
uopz_rename("strlen", "original_strlen");
echo original_strlen("Hello World");
?>Результатом выполнения данного примера будет что-то подобное:
11
Пример #2 Пример использования uopz_rename() с классом
<?php
class My {
public function strlen($arg) {
return strlen($arg);
}
}
uopz_rename(My::class, "strlen", "original_strlen");
echo My::original_strlen("Hello World");
?>Результат выполнения данного примера:
11
(PECL uopz 1 >= 1.0.3, PECL uopz 2)
uopz_restore — Восстановить ранее зарезервированную функцию
Эта функция была УДАЛЕНА в PECL uopz 5.0.0.
$function): void$class, string $function): voidВосстановить ранее зарезервированную функцию
classИмя класса, содержащего функцию для восстановления
functionИмя функции
Пример #1 Пример использования uopz_restore()
<?php
uopz_backup("fgets");
uopz_function("fgets", function(){
return true;
});
var_dump(fgets());
uopz_restore('fgets');
fgets();
?>Результатом выполнения данного примера будет что-то подобное:
Warning: fgets() expects at least 1 parameter, 0 given in /path/to/script.php on line 8
(PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_set_hook — Устанавливает обработчик для выполнения при вызове функции или метода
Устанавливает обработчик для выполнения при вызове функции или метода.
classИмя класса.
functionИмя функции или метода.
hookЗамыкание, выполняемое при вызове функции или метода.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Простое использование uopz_set_hook()
<?php
function foo() {
echo 'foo';
}
uopz_set_hook('foo', function () {echo 'bar';});
foo();
?>Результат выполнения данного примера:
barfoo
(PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_set_mock — Использовать имитатор вместо класса для новых объектов
Если mock - это строка, содержащая имя класса, тогда он
будет создан вместо class. mock
также может быть объектом.
Замечание:
Только динамический доступ к свойствам и методам будет использовать объект
mock. Статический доступ будет использовать оригинальныйclass. Смотрите пример ниже.
classИмя класса, который будет имитирован.
mock
Имитатор в виде строки, содержащей имя используемого класса, либо объект.
Если передана строка, она должна быть содержать абсолютное имя класса.
В этом случае рекомендуется использовать магическую константу ::class.
Функция не возвращает значения после выполнения.
| Версия | Описание |
|---|---|
| uopz 6.0.0 | Имитирование статических функций более не поддерживаются этой функцией. Вместо это го следует использовать uopz_redefine() и uopz_set_return(), или Componere. |
Пример #1 Пример использования uopz_set_mock()
<?php
class A {
public function who() {
echo "A";
}
}
class mockA {
public function who() {
echo "mockA";
}
}
uopz_set_mock(A::class, mockA::class);
(new A)->who();
?>Результат выполнения данного примера:
mockA
Пример #2 Пример использования uopz_set_mock()
<?php
class A {
public function who() {
echo "A";
}
}
uopz_set_mock(A::class, new class {
public function who() {
echo "mockA";
}
});
(new A)->who();
?>Результат выполнения данного примера:
mockA
Пример #3 uopz_set_mock() и статические члены класса
Начиная с uopz 6.0.0, имитация статических членов класса не поддерживается.
<?php
class A {
public static function who() {
echo "A";
}
}
uopz_set_mock(A::class, new class {
const CON = 'mockA';
public static function who() {
echo "mockA";
}
});
echo A::CON, PHP_EOL;
A::who();Результат выполнения данного примера:
A A
Вывод примера в uopz 5:
mockA mockA
(PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_set_property — Устанавливает значение существующего свойства класса или экземпляра
Задаёт значение существующего статического свойства класса,
если задан класс (class),
либо значение существующего свойства экземпляра (вне зависимости от того, существует ли свойство экземпляра),
если передан экземпляр (instance).
classИмя класса.
instanceЭкземпляр объекта.
propertyИмя свойства.
valueЗначение, присваиваемое свойству.
Функция не возвращает значения после выполнения.
Пример #1 Простое использование uopz_set_property()
<?php
class Foo {
private static $staticBar;
private $bar;
public static function testStaticBar() {
return self::$staticBar;
}
public function testBar() {
return $this->bar;
}
}
$foo = new Foo;
uopz_set_property('Foo', 'staticBar', 10);
uopz_set_property($foo, 'bar', 100);
var_dump(Foo::testStaticBar());
var_dump($foo->testBar());
?>Результат выполнения данного примера:
int(10)
(PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_set_return — Предоставить возвращаемое значение для существующей функции
Установить возвращаемое значение для function на value. Если value
замыкание и установлен execute, замыкание будет выполняться вместо исходной функции.
Можно вызвать исходную функцию из замыкания.
Замечание:
Эта функция заменяет uopz_rename().
classИмя класса, содержащего функцию
functionИмя существующей функции
valueВозвращаемое значение функцией. Если передано замыкание и параметр execute установлен, замыкание будет выполнено вместо исходной функции.
executeЕсли true, и в параметре value передано замыкание, замыкание будет выполнено вместо исходной функции.
True в случае успешного выполнения, false в противном случае.
Пример #1 Пример использования uopz_set_return()
<?php
uopz_set_return("strlen", 42);
echo strlen("Banana");
?>Результат выполнения данного примера:
42
Пример #2 Пример использования uopz_set_return()
<?php
uopz_set_return("strlen", function($str) { return strlen($str) * 2; }, true );
echo strlen("Banana");
?>Результат выполнения данного примера:
12
Пример #3 Пример использования uopz_set_return() с классом
<?php
class My {
public static function strlen($arg) {
return strlen($arg);
}
}
uopz_set_return(My::class, "strlen", function($str) { return strlen($str) * 2; }, true );
echo My::strlen("Banana");
?>Результат выполнения данного примера:
12
(PECL uopz 5, PECL uopz , PECL uopz 7)
uopz_set_static — Устанавливает статические переменные в области видимости функции или метода
$function, array $static): void$class, string $function, array $static): voidУстанавливает статические переменные в области видимости функции или метода.
classИмя класса.
functionИмя функции или метода.
staticАссоциативный массив (array) имён переменных, сопоставленных с их значениями.
Функция не возвращает значения после выполнения.
Пример #1 Простое использование uopz_set_static()
<?php
function foo() {
static $bar = 'baz';
var_dump($bar);
}
uopz_set_static('foo', ['bar' => 'qux']);
foo();
?>Результат выполнения данного примера:
string(3) "qux"
(PECL uopz 1, PECL uopz 2, PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_undefine — Отменяет определение константы
$constant): bool$class, string $constant): boolУдаляет константу во время выполнения
class
Название класса, содержащего constant
constantИмя существующей константы
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Пример использования uopz_undefine()
<?php
define("MY", true);
uopz_undefine("MY");
var_dump(defined("MY"));
?>Результат выполнения данного примера:
bool(false)
(PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_unset_hook — Удаляет ранее установленную функцию или метод
$function): bool$class, string $function): boolУдаляет ранее установленную функцию или метод.
classИмя класса.
functionИмя функции или метода.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Простое использование uopz_unset_hook()
<?php
function foo() {
echo 'foo';
}
uopz_set_hook('foo', function () {echo 'bar';});
foo();
echo PHP_EOL;
uopz_unset_hook('foo');
foo();
?>Результат выполнения данного примера:
barfoo foo
(PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_unset_mock — Удалить ранее установленный имитатор
$class): void
Удаляет ранее установленный имитатор для class.
classИмя имитированного класса.
Функция не возвращает значения после выполнения.
Выбрасывает RuntimeException, если ранее не был
задан имитатор для class.
Пример #1 Пример использования uopz_unset_mock()
<?php
class A {
public static function who() {
echo "A";
}
}
class mockA {
public static function who() {
echo "mockA";
}
}
uopz_set_mock(A::class, mockA::class);
uopz_unset_mock(A::class);
A::who();
?>Результат выполнения данного примера:
A
(PECL uopz 5, PECL uopz 6, PECL uopz 7)
uopz_unset_return — Отменяет ранее установленное возвращаемое значение для функции
$function): bool$class, string $function): bool
Отменяет возвращаемое значение function, ранее заданное функцией uopz_set_return().
classИмя класса, содержащего функцию
functionИмя функции
True в случае успешного выполнения
Пример #1 Пример использования uopz_unset_return()
<?php
uopz_set_return("strlen", 42);
$len = strlen("Banana");
uopz_unset_return("strlen");
echo $len + strlen("Banana");
?>Результат выполнения данного примера:
48
Windows Cache Extension для PHP - это кеширующий модуль, позволяющий увеличить скорость работы PHP-приложений на Windows и Windows Server. Как только вы включаете Windows Cache Extension и он загружается движком PHP, приложения начинают получать все его преимущества без необходимости менять их код.
Модуль включает 5 различных типов кешей. Далее рассказывается про назначение и преимущества каждого типа кеша.
PHP Opcode Cache - PHP является скриптовым языком, который читает входящий поток данных, содержащий текст и/или инструкции языка и выдаёт новый поток данных, обычно в формате HTML. Т.е. на стороне веб-сервера, PHP читает, разбирает, компилирует и запускает PHP-скрипт каждый раз, когда его запрашивает клиент. Чтение, разбор и компиляция создают дополнительную нагрузку на процессорные ядра и файловую систему сервера, что сказывается на конечной производительности приложения. Кеширование байт-кода (опкода) PHP позволяет держать уже скомпилированный код в разделяемой памяти и использовать его при следующих запросах к тому же скрипту.
Поддержка кеширования опкодов была удалена в Wincache 2.0.0.
Так что если она вам нужна, то следует использовать модуль
OPcache, который включён в PHP.
File Cache - даже если включено кеширование опкодов, PHP всё равно обращается к файлам на файловой системе. Когда PHP-скрипт размещён в удалённой файловой папке, файловые операции значительно снижают производительность. Windows Cache Extension включает файловое кеширование, которое используется для сохранения контента скриптов в разделяемой памяти, что сильно сокращает количество операций доступа к файловой системе для PHP.
Resolve File Path Cache - скрипты PHP довольно часто включают или оперируют файлами, используя относительные пути. Каждый такой путь сначала нормализуется PHP до абсолютного пути. Когда приложение использует большое количество файлов и обращается к ним по относительным путям, операции выведения абсолютных путей могут негативно сказаться на производительности. Модуль Windows Cache Extension предоставляет инструмент кеширования Resolve File Path, который используется для сохранения сопоставления относительных и абсолютных файловых путей, позволяя снизить количество операций их выведения.
User Cache (доступно с версии 1.1.0) - скрипты PHP могут получить преимущества кеширования в разделяемой памяти посредством API пользовательского кеширования. Объекты и переменные PHP могут быть сохранены в пользовательском кеше и переиспользованы в последующих запросах. Это может как повысить производительность приложения, так и разделить данные между несколькими процессами PHP.
Session Handler (доступно с версии 1.1.0) - обработчик сессий WinCache может быть использован для сохранения данных сессии в кеше в разделяемой памяти. Это позволяет избежать дисковых операций при записи и чтении данных сессии, что может сильно увеличить производительность, если таких данных много.
В данный момент модуль поддерживается только для следующих конфигураций:
Windows OS:
PHP:
Замечание: Модуль WinCache может использоваться только если IIS настроен использовать PHP через FastCGI.
Этот модуль » PECL не поставляется вместе с PHP.
Информация по установке этого модуля PECL может быть найдена в главе руководства Установка PECL модулей. Дополнительная информация, такая как новые версии, скачивание, исходные файлы, информация о разработчике и CHANGELOG, может быть найдена здесь: » https://pecl.php.net/package/wincache.
Существует два пакета для этого модуля: один пакет для PHP 5.2.X, а другой для PHP 5.3.X. Выбор необходимого пакета зависит от вашей версии PHP.
Для установки и включения модуля следуйте следующей инструкции:
Разархивируйте пакет во временную папку.
Скопируйте php_wincache.dll в каталог с модулями PHP. Обычно этот каталог называется "ext" и расположен там же, где установлен PHP. К примеру: C:\Program Files\PHP\ext.
Используя текстовый редактор откройте файл php.ini, который обычно лежит там же, где установлен PHP. К примеру: C:\Program Files\PHP\php.ini.
Добавьте в конец файла строку:
extension = php_wincache.dll.
Сохраните и закройте файл php.ini.
Пересоздайте пул приложений IIS для того, чтобы изменения вступили в силу. Для проверки того, что модуль включён, создайте файл phpinfo.php с кодом, вызывающим функцию PHP phpinfo.
Сохраните phpinfo.php в корневом каталоге веб-сайта и
обратитесь к нему через веб-браузер по следующей ссылке
http://localhost/phpinfo.php. Найдите в выводе секцию
wincache. Если модуль включён, то
функция phpinfo покажет
список конфигурационных параметров WinCache.
Замечание: Не забудьте удалить файл phpinfo.php после того, как он перестанет быть нужен.
Поведение этих функций зависит от установок в php.ini.
В таблице представлен список конфигурационных параметров модуля WinCache:
| Имя | По умолчанию | Минимум | Максимум | Место изменения | Список изменений |
|---|---|---|---|---|---|
| wincache.fcenabled | "1" | "0" | "1" | PHP_INI_ALL | Доступно с WinCache 1.0.0 |
| wincache.fcenabledfilter | "NULL" | "NULL" | "NULL" | PHP_INI_SYSTEM | Доступно с WinCache 1.0.0 |
| wincache.fcachesize | "24" | "5" | "255" | PHP_INI_SYSTEM | Доступно с WinCache 1.0.0 |
| wincache.fcndetect | "1" | "0" | "1" | PHP_INI_SYSTEM | Доступно с WinCache 1.1.0 |
| wincache.maxfilesize | "256" | "10" | "2048" | PHP_INI_SYSTEM | Доступно с WinCache 1.0.0 |
| wincache.ocenabled | "1" | "0" | "1" | PHP_INI_ALL | Доступно с WinCache 1.0.0. Удалено в 2.0.0.0 |
| wincache.ocenabledfilter | "NULL" | "NULL" | "NULL" | PHP_INI_SYSTEM | Доступно с WinCache 1.0.0. Удалено в 2.0.0.0 |
| wincache.ocachesize | "96" | "15" | "255" | PHP_INI_SYSTEM | Доступно с WinCache 1.0.0. Удалено в 2.0.0.0 |
| wincache.filecount | "4096" | "1024" | "16384" | PHP_INI_SYSTEM | Доступно с WinCache 1.0.0 |
| wincache.chkinterval | "30" | "0" | "300" | PHP_INI_SYSTEM | Доступно с WinCache 1.0.0 |
| wincache.ttlmax | "1200" | "0" | "7200" | PHP_INI_SYSTEM | Доступно с WinCache 1.0.0 |
| wincache.enablecli | 0 | 0 | 1 | PHP_INI_SYSTEM | Доступно с WinCache 1.0.0 |
| wincache.ignorelist | NULL | NULL | NULL | PHP_INI_ALL | Доступно с WinCache 1.0.0 |
| wincache.namesalt | NULL | NULL | NULL | PHP_INI_SYSTEM | Доступно с WinCache 1.0.0 |
| wincache.ucenabled | 1 | 0 | 1 | PHP_INI_SYSTEM | Доступно с WinCache 1.1.0 |
| wincache.ucachesize | 8 | 5 | 85 | PHP_INI_SYSTEM | Доступно с WinCache 1.1.0 |
| wincache.scachesize | 8 | 5 | 85 | PHP_INI_SYSTEM | Доступно с WinCache 1.1.0 |
| wincache.rerouteini | NULL | NULL | NULL | PHP_INI_SYSTEM | Доступно с WinCache 1.2.0. Удалено в 1.3.7 |
| wincache.reroute_enabled | 1 | 0 | 1 | PHP_INI_SYSTEM | PHP_INI_PERDIR | Доступно с WinCache 1.3.7 |
| wincache.srwlocks | 1 | 0 | 1 | PHP_INI_SYSTEM | Доступно с WinCache 1.3.6.3. Удалено в 2.0.0.0 |
| wincache.filemapdir | NULL | NULL | NULL | PHP_INI_SYSTEM | Доступно с WinCache 1.3.7.4 |
Краткое разъяснение конфигурационных директив.
wincache.fcenabled
bool
wincache.fcenabledfilter
string
wincache.fcenabled: если
wincache.fcenabled установлено в 1, то для серверов,
перечисленных в wincache.fcenabledfilter файловое кеширование
будет отключено; если wincache.fcenabled установлено как 0, то
для серверов, перечисленных в wincache.fcenabledfilter
файловое кеширование будет включено.
wincache.fcachesize
int
wincache.fcndetect
bool
wincache.chkinterval
интервалы времени.
wincache.maxfilesize
int
wincache.ocenabled
bool
Эта опция была УДАЛЕНА в версии 2.0.0.0
wincache.ocenabledfilter
string
Эта опция была УДАЛЕНА в версии 2.0.0.0
wincache.ocenabled: если
wincache.ocenabled установлено в 1, то для серверов,
перечисленных в wincache.ocenabledfilter файловое кеширование
будет отключено; если wincache.ocenabled установлено как 0, то
для серверов, перечисленных в wincache.ocenabledfilter
файловое кеширование будет разрешено.
wincache.ocachesize
int
Эта опция была УДАЛЕНА в версии 2.0.0.0
wincache.filecount
int
wincache.chkinterval
int
wincache.ttlmax
int
wincache.enablecli
bool
wincache.ignorelist
string
Определяет список файлов, которые не нужно кешировать. Указываются только имена файлов. Символ разделитель - вертикальная черта "|".
Пример #1 Пример использования wincache.ignorelist
wincache.ignorelist = "index.php|misc.php|admin.php"
wincache.namesalt
string
wincache.ucenabled
bool
wincache.ucachesize
int
wincache.scachesize
int
wincache.rerouteini
string
Эта опция была УДАЛЕНА в версии 1.3.7.
Начиная с 1.3.7. вместо неё используйте wincache.reroute_enabled.
wincache.reroute_enabled
bool
wincache.srwlocks
bool
Эта опция была УДАЛЕНА в версии 2.0.0.0
wincache.filemapdir
string
Установочный пакет WinCache содержит PHP-скрипт, wincache.php, который можно использовать для получения статистики использования кеша.
Если модуль WinCache был установлен с помощью Microsoft Web Platform Installer, то скрипт будет располагаться по пути %SystemDrive%\Program Files\IIS\Windows Cache for PHP\. На 64-разрядных версиях Windows Server, скрипт лежит по пути %SystemDrive%\Program Files (x86)\IIS\Windows Cache for PHP. Если модуль устанавливался самостоятельно, то wincache.php будет лежать в том же каталоге, в который вы распаковывали установочный пакет.
Для использования wincache.php, скопируйте его в корневой каталог веб-сайта или в любой его подкаталог. Для защиты скрипта, откройте его в текстовом редакторе и измените значения констант USERNAME и PASSWORD. Если для аутентификации в IIS используется другой механизм, то следуйте инструкциям в комментариях:
Пример #1 Настройка аутентификации для wincache.php
<?php
/**
* ======================== CONFIGURATION SETTINGS ==============================
* If you do not want to use authentication for this page, set USE_AUTHENTICATION to 0.
* If you use authentication then replace the default password.
*/
define('USE_AUTHENTICATION', 1);
define('USERNAME', 'wincache');
define('PASSWORD', 'wincache');
/**
* The Basic PHP authentication will work only when IIS is configured to support
* Anonymous Authentication' and nothing else. If IIS is configured to support/use
* any other kind of authentication like Basic/Negotiate/Digest etc, this will not work.
* In that case use the array below to define the names of users in your
* domain/network/workgroup which you want to grant access to.
*/
$user_allowed = array('DOMAIN\user1', 'DOMAIN\user2', 'DOMAIN\user3');
/**
* If the array contains string 'all', then all the users authenticated by IIS
* will have access to the page. Uncomment the below line and comment above line
* to grant access to all users who gets authenticated by IIS.
*/
/* $user_allowed = array('all'); */
/** ===================== END OF CONFIGURATION SETTINGS ========================== */
?>Замечание: Всегда защищайте скрипт wincache.php с помощью встроенного механизма, либо с помощью механизма аутентификации веб-сервера. Оставляя доступ к скрипту открытым вы можете скомпрометировать ваше приложение и веб-сервер.
Обработчик сессий WinCache (доступен с WinCache 1.1.0) может использоваться для хранения данных сессий в кеше в разделяемой памяти. Использование памяти вместо файловой системы поможет улучшить производительность вашего приложения, если оно сохраняет большое количество сессионных данных. Кеш сессий Wincache использует дублирование данных на диске, что позволяет сохранить сессионные данные при пересоздании пула приложений IIS.
Для настройки использования обработчика сессий WinCache измените в файле php.ini настройку session.save_handler на wincache. По умолчанию, для хранения данных сессий используется временная директория Windows. Для изменения пути к сессионному файлу используйте настройку session.save_path.
Пример #1 Включение обработчика сессий WinCache
session.save_handler = wincache session.save_path = C:\inetpub\temp\session\
ОБРАТИТЕ ВНИМАНИЕ: wincache.rerouteini удалена в WinCache 1.3.7.0. Она была заменена автоматическим перенаправлением. Смотрите wincache.reroute_enabled.
Перенаправление функций WinCache (доступно с WinCache 1.2.0, удалено с WinCache 1.3.7.0) может использоваться для замены встроенных функций их эквивалентами, оптимизированными для работы с файловым кешем. Модуль WinCache включает оптимизированные под Windows реализации функций работы с файлами, что может повысить производительность PHP-приложений в случаях работы с файлами и сетевыми папками. Оптимизированные версии представлены для следующих функций:
Для настройки использования перенаправления в WinCache используется файл reroute.ini, который включён в установочный пакет. Скопируйте этот файл в ту же директорию, где находится php.ini. После этого добавьте в php.ini настройку wincache.rerouteini и укажите абсолютный или относительный путь к reroute.ini.
Пример #1 Включение перенаправления функций в WinCache
wincache.rerouteini = C:\PHP\reroute.ini
Замечание: Если перенаправление функций включено, то рекомендуется увеличить размер файлового кеша WinCache. Его размер настраивается в директиве wincache.fcachesize.
Файл reroute.ini содержит описание привязок встроенных функций PHP к их эквивалентам модуля WinCache. Каждая строка файла определяет привязку с использованием следующего синтаксиса:
<Имя функции PHP>:[<количество параметров функции>]=<имя функции wincache>
Пример файла приведён ниже. В этом примере вызов PHP-функции file_get_contents() подменяется вызовом функции wincache_file_get_contents() только если количество переданных параметров меньше или равно 2. Указание количества параметров полезно если подменяющая функция реализует обработку не всех исходных параметров.
Пример #2 Содержимое файла Reroute.ini
[FunctionRerouteList] file_exists=wincache_file_exists file_get_contents:2=wincache_file_get_contents readfile:2=wincache_readfile is_readable=wincache_is_readable is_writable=wincache_is_writable is_writeable=wincache_is_writable is_file=wincache_is_file is_dir=wincache_is_dir realpath=wincache_realpath filesize=wincache_filesize
Данный модуль не определяет каких-либо типов ресурсов.
Данный модуль не определяет никакие константы.
(PECL wincache >= 1.0.0)
wincache_fcache_fileinfo — Получает информацию о файлах, закешированных в файловом кеше
$summaryonly = false): array|falseПолучает информацию о содержимом файлового кеша и его использовании.
summaryonlyОпределяет, будет ли возвращаемый массив содержать информацию об отдельных записях кеша вместе со сводкой файлового кеша.
Массив метаданных о файловом кеше или false в случае возникновения ошибки.
Массив, возвращаемый этой функцией, содержит следующие элементы:
total_cache_uptime - общее время в секундах, в течение которого файловый кеш был активен
total_file_count - общее количество файлов, которые в данный момент находятся в файловом кеше
total_hit_count - количество раз, когда файлы обслуживались из файлового кеша
total_miss_count - количество раз, когда файлы не были найдены в файловом кеше
file_entries - массив, содержащий информацию обо всех закешированных файлах:
file_name - абсолютное имя закешированного файла
add_time - время в секундах с момента добавления файла в кеш
use_time - время в секундах с момента обращения к файлу в кеше
last_check - время в секундах с момента проверки файла на наличие модификаций
hit_count - количество раз, когда файл был обработан из кеша
file_size - размер кешируемого файла в байтах
Пример #1 Пример использования wincache_fcache_fileinfo()
<pre>
<?php
print_r(wincache_fcache_fileinfo());
?>
</pre>Результат выполнения данного примера:
Array
( [total_cache_uptime] => 3234
[total_file_count] => 5
[total_hit_count] => 0
[total_miss_count] => 1
[file_entries] => Array
(
[1] => Array
(
[file_name] => c:\inetpub\wwwroot\checkcache.php
[add_time] => 1
[use_time] => 0
[last_check] => 1
[hit_count] => 1
[file_size] => 2435
)
[2] => Array (...iterates for each cached file)
)
)
(PECL wincache >= 1.0.0)
wincache_fcache_meminfo — Получает информацию об использовании памяти файлового кеша
Получает информацию об использовании памяти файлового кеша.
У этой функции нет параметров.
Массив метаданных об использовании памяти файлового кеша или false в случае возникновения ошибки
Массив, возвращаемый этой функцией, содержит следующие элементы:
memory_total - объем памяти в байтах, выделенный для файлового кеша
memory_free - объем свободной памяти в байтах, доступной для файлового кеша
num_used_blks - количество блоков памяти, используемых файловым кешем
num_free_blks - количество свободных блоков памяти, доступных для файлового кеша
memory_overhead - объем памяти в байтах, используемый для внутренних структур файлового кеша
Пример #1 Пример использования wincache_fcache_meminfo()
<pre>
<?php
print_r(wincache_fcache_meminfo());
?>
</pre>Результат выполнения данного примера:
Array
(
[memory_total] => 134217728
[memory_free] => 131339120
[num_used_blks] => 361
[num_free_blks] => 3
[memory_overhead] => 5856
)
(PECL wincache >= 1.1.0)
wincache_lock — Получает эксклюзивную блокировку для данного ключа
$key, bool $isglobal = false): boolПолучает эксклюзивную блокировку для данного ключа. Выполнение текущего скрипта будет заблокировано до тех пор, пока блокировка не будет получена. После получения блокировки другие сценарии, которые пытаются запросить блокировку с помощью того же ключа, будут заблокированы до тех пор, пока текущий скрипт не снимет блокировку с помощью wincache_unlock().
Использование wincache_lock() и wincache_unlock() может вызвать взаимную блокировку при выполнении скриптов PHP в многопроцессорной среде, такой как FastCGI. Не используйте эти функции, если вы не уверены, что вам это нужно. Для большинства операций с пользовательским кешем эти функции использовать не обязательно.
keyИмя ключа в кеше для включения блокировки.
isglobalОпределяет, является ли область блокировки общесистемной или локальной. Локальные блокировки относятся к пулу приложений в случае IIS FastCGI или ко всем процессам PHP, которые имеют один и тот же идентификатор родительского процесса.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Пример использования wincache_lock()
<?php
$fp = fopen("/tmp/lock.txt", "r+");
if (wincache_lock(“lock_txt_lock”)) { // получить эксклюзивную блокировку
ftruncate($fp, 0); // обрезать файл
fwrite($fp, "Напишите что-нибудь здесь\n");
wincache_unlock(“lock_txt_lock”); // снять блокировку
} else {
echo "Не удалось получить блокировку!";
}
fclose($fp);
?>
(PECL wincache >= 1.0.0)
wincache_ocache_fileinfo — Получает информацию о файлах, закешированных в кеше опкодов
$summaryonly = false): array|falseПолучает информацию о содержимом кеша опкодов и его использовании.
Эта функция УДАЛЕНА в PHP 7.0.0.
summaryonlyОпределяет, будет ли возвращаемый массив содержать информацию об отдельных записях кеша вместе со сводкой кеша опкодов.
Массив метаданных о кеше опкодов или false в случае возникновения ошибки.
Массив, возвращаемый этой функцией, содержит следующие элементы:
total_cache_uptime - общее время в секундах, в течение которого кеш опкода был активен.
total_file_count - общее количество файлов, которые в настоящее время находятся в кеше опкодов.
total_hit_count - количество раз, когда скомпилированный опкод был использован из кеша.
total_miss_count - количество раз, когда скомпилированный опкод не был найден в кеше.
is_local_cache - true, если метаданные кеша предназначены для экземпляра локального кеша,
false, если метаданные предназначены для глобального кеша.
file_entries - массив, содержащий информацию обо всех закешированных файлах:
file_name - абсолютное имя закешированного файла.
add_time - время в секундах с момента добавления файла в кеш опкодов.
use_time - время в секундах с момента обращения к файлу в кеше опкодов.
last_check - время в секундах с момента проверки файла на наличие модификаций.
hit_count - количество раз, когда файл был использован из кеша.
function_count - количество функций в закешированном файле.
class_count - количество классов в закешированном файле.
Пример #1 Пример использования wincache_ocache_fileinfo()
<pre>
<?php
print_r(wincache_ocache_fileinfo());
?>
</pre>Результат выполнения данного примера:
Array
(
[total_cache_uptime] => 17357
[total_file_count] => 121
[total_hit_count] => 36562
[total_miss_count] => 201
[file_entries] => Array
(
[1] => Array
(
[file_name] => c:\inetpub\wwwroot\checkcache.php
[add_time] => 17356
[use_time] => 7
[last_check] => 10
[hit_count] => 454
[function_count] => 0
[class_count] => 1
)
[2] => Array (...iterates for each cached file)
)
)
(PECL wincache >= 1.0.0)
wincache_ocache_meminfo — Получает информацию об использовании кеш-памяти опкодов
Получает информацию об использовании кеш-памяти опкодов.
У этой функции нет параметров.
Массив метаданных об использовании кеш-памяти опкодов или false в случае возникновения ошибки.
Массив, возвращаемый этой функцией, содержит следующие элементы:
memory_total - объём памяти в байтах, выделенный для кеша опкодов.
memory_free - объём свободной памяти в байтах, доступной для кеша опкодов.
num_used_blks - количество блоков памяти, используемых кешем опкодов.
num_free_blks - количество свободных блоков памяти, доступных для кеша опкодов.
memory_overhead - объём памяти в байтах, используемый для внутренних структур кеша опкодов.
Эта функция УДАЛЕНА в PHP 7.0.0.
Пример #1 Пример использования wincache_ocache_meminfo()
<pre>
<?php
print_r(wincache_ocache_meminfo());
?>
</pre>Результат выполнения данного примера:
Array
(
[memory_total] => 134217728
[memory_free] => 112106972
[num_used_blks] => 15469
[num_free_blks] => 4
[memory_overhead] => 247600
)
(PECL wincache >= 1.0.0)
wincache_refresh_if_changed — Обновляет записи кеша для закешированных файлов
$files = NULL): boolОбновляет записи кеша для файлов, имена которых были переданы во входном аргументе. Если аргумент не указан, обновляются все записи в кеше.
filesМассив имён файлов, которые необходимо обновить. Могут использоваться абсолютные или относительные пути к файлам.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
WinCache выполняет регулярные проверки закешированных файлов, чтобы гарантировать, что если какой-либо файл был изменён, то соответствующая запись в кеше будет обновлена. По умолчанию эта проверка выполняется каждые 30 секунд. Если, например, PHP-скрипт обновляет другой PHP-скрипт, в котором хранятся параметры конфигурации приложения, то может случиться так, что после сохранения параметров конфигурации в файл приложение по-прежнему будет использовать старые параметры в течение некоторого времени, пока не будет обновлён кеш. В таких случаях может быть предпочтительнее обновить кеш сразу после изменения файла. В следующем примере показано, как это можно сделать.
Пример #1 Пример использования wincache_refresh_if_changed()
<?php
$filename = 'C:\inetpub\wwwroot\config.php';
$handle = fopen($filename, 'w+');
if ($handle === FALSE) die('Failed to open file '.$filename.' for writing');
fwrite($handle, '<?php $setting=something; ?>');
fclose($handle);
wincache_refresh_if_changed(array($filename));
?>
(PECL wincache >= 1.0.0)
wincache_rplist_fileinfo — Получает информацию о разрешении кеша пути к файлу разрешения
$summaryonly = false): array|falseПолучает информацию о закешированных сопоставлениях между относительными путями к файлам и соответствующими абсолютными путями к файлам.
summaryonly
Массив метаданных о кеше пути к файлу разрешения или false в случае возникновения ошибки.
Массив, возвращаемый этой функцией, содержит следующие элементы:
total_file_count - общее количество сопоставлений пути к файлу, хранящихся в кеше.
rplist_entries - массив, содержащий информацию обо всех путях закешированных файлов:
resolve_path - путь к файлу.
subkey_data - соответствующий абсолютный путь к файлу.
Пример #1 Пример использования wincache_rplist_fileinfo()
<pre>
<?php
print_r(wincache_rplist_fileinfo());
?>
</pre>Результат выполнения данного примера:
Array
(
[total_file_count] => 5
[rplist_entries] => Array
(
[1] => Array
(
[resolve_path] => checkcache.php
[subkey_data] => c:\inetpub\wwwroot|c:\inetpub\wwwroot\checkcache.php
)
[2] => Array (...iterates for each cached file)
)
)
(PECL wincache >= 1.0.0)
wincache_rplist_meminfo — Получает информацию об использовании памяти с помощью кеша пути к файлу разрешения
Получает информацию об использовании памяти с помощью кеша пути к файлу разрешения.
У этой функции нет параметров.
Массив метаданных, описывающий использование памяти с помощью кеша пути к файлу разрешения или false в случае возникновения ошибки.
Массив, возвращаемый этой функцией, содержит следующие элементы:
memory_total - объём памяти в байтах, выделенный для кеша пути к файлу разрешения.
memory_free - объём свободной памяти в байтах, доступной для кеша пути к файлу разрешения.
num_used_blks - количество блоков памяти, используемых кешем пути к файлу разрешения.
num_free_blks - количество свободных блоков памяти, доступных для кеша пути к файлу разрешения.
memory_overhead - объём памяти в байтах, используемый для внутренних структур кеширования пути к файлу разрешения.
Пример #1 Пример использования wincache_rplist_meminfo()
<pre>
<?php
print_r(wincache_rplist_meminfo());
?>
</pre>Результат выполнения данного примера:
Array
(
[memory_total] => 9437184
[memory_free] => 9416744
[num_used_blks] => 23
[num_free_blks] => 1
[memory_overhead] => 416
)
(PECL wincache >= 1.1.0)
wincache_scache_info — Получает информацию о файлах, закешированных в кеше сессии
$summaryonly = false): array|falseПолучает информацию о содержимом кеша сессии и его использовании.
summaryonlyОпределяет, будет ли возвращаемый массив содержать информацию об отдельных записях кеша вместе со сводкой кеша сессии.
Массив метаданных о кеше сессии или false в случае возникновения ошибки.
Массив, возвращаемый этой функцией, содержит следующие элементы:
total_cache_uptime - общее время в секундах, в течение которого кеш сессии был активен.
total_item_count - общее количество элементов, которые в настоящее время находятся в кеше сессии.
is_local_cache - true, если метаданные кеша предназначены для экземпляра локального кеша,
false, если метаданные предназначены для глобального кеша.
total_hit_count - количество раз, когда данные были обработаны из кеша.
total_miss_count - количество раз, когда данные не были найдены в кеше.
scache_entries - массив, содержащий информацию обо всех закешированных элементах:
key_name - имя ключа, который используется для хранения данных.
value_type - тип значения, хранимого ключом.
use_time - время в секундах с момента обращения к файлу в кеше опкодов.
last_check - время в секундах с момента проверки файла на наличие модификаций.
ttl_seconds - время, оставшееся для данных, чтобы оставаться в кеше, 0 означает бесконечность.
age_seconds - время, прошедшее с момента добавления данных в кеш.
hitcount - количество раз, когда данные были получены из кеша.
Пример #1 Пример использования wincache_scache_info()
<pre>
<?php
print_r(wincache_scache_info());
?>
</pre>Результат выполнения данного примера:
Array
(
[total_cache_uptime] => 17357
[total_file_count] => 121
[total_hit_count] => 36562
[total_miss_count] => 201
[scache_entries] => Array
(
[1] => Array
(
[file_name] => c:\inetpub\wwwroot\checkcache.php
[add_time] => 17356
[use_time] => 7
[last_check] => 10
[hit_count] => 454
[function_count] => 0
[class_count] => 1
)
[2] => Array (...iterates for each cached file)
)
)
(PECL wincache >= 1.1.0)
wincache_scache_meminfo — Получает информацию об использовании кеш-памяти сессии
Получает информацию об использовании памяти кешем сессии.
У этой функции нет параметров.
Массив метаданных об использовании кеш-памяти сессии или false в случае возникновения ошибки.
Массив, возвращаемый этой функцией, содержит следующие элементы:
memory_total - объём памяти в байтах, выделенный для кеш-памяти сессии.
memory_free - объём свободной памяти в байтах, доступной для кеш-памяти сессии.
num_used_blks - количество блоков памяти, используемых кешем сессии.
num_free_blks - количество свободных блоков памяти, доступных для кеша сессии.
memory_overhead - объём памяти в байтах, используемый для внутренних структур кеша сессии.
Пример #1 Пример использования wincache_scache_meminfo()
<pre>
<?php
print_r(wincache_scache_meminfo());
?>
</pre>Результат выполнения данного примера:
Array
(
[memory_total] => 5242880
[memory_free] => 5215056
[num_used_blks] => 6
[num_free_blks] => 3
[memory_overhead] => 176
)
(PECL wincache >= 1.1.0)
wincache_ucache_add — Добавляет переменную в пользовательский кеш, только если переменная ещё не существует в кеше
Добавляет переменную в пользовательский кеш, только если эта переменная ещё не существует в кеше. Добавленная переменная остаётся в пользовательском кеше, пока не истечёт срок её действия или она не будет удалена с помощью функций wincache_ucache_delete() или wincache_ucache_clear().
key
Сохраняет переменную с использованием этого имени key. Если переменная с таким же key
уже существует, завершится ошибкой и вернёт false. key чувствителен к регистру.
Чтобы переопределить значение, даже если key уже существует, используйте функцию wincache_ucache_set().
key также может принимать массив пар имя => значение, где имена будут использоваться в качестве ключей.
Это можно использовать для добавления нескольких значений в кеш за одну операцию, что позволяет избежать состояния гонки.
value
Значение переменной, которую необходимо сохранить. Value поддерживает все типы данных, кроме ресурсов,
таких как дескрипторы файлов.
Параметр игнорируется, если первым аргументом является массив. Общее руководство - передать null в качестве value
при использовании массива key.
Если value является объектом или массивом, содержащим объекты,
то объекты будут сериализованы. Подробнее о сериализации объектов смотрите в описании __sleep().
valuesАссоциативный массив ключей и значений.
ttl
Время, в течение которого переменная находится в кеше, в секундах. После того, как значение, указанное в ttl
будет передано, сохранённая переменная будет удалена из кеша.
Параметр принимает значение по умолчанию 0, что означает, что переменная останется в кеше,
пока она не будет явно удалена с помощью функций wincache_ucache_delete() или wincache_ucache_clear().
Если key является строкой, функция возвращает true в случае успешного выполнения и false в случае возникновения ошибки.
Если key является массивом, функция возвращает:
false;
Пример #1 Пример использования wincache_ucache_add() с key в виде строки
<?php
$bar = 'BAR';
var_dump(wincache_ucache_add('foo', $bar));
var_dump(wincache_ucache_add('foo', $bar));
var_dump(wincache_ucache_get('foo'));
?>Результат выполнения данного примера:
bool(true) bool(false) string(3) "BAR"
Пример #2 Пример использования wincache_ucache_add() с key в виде массива
<?php
$colors_array = array('green' => '5', 'Blue' => '6', 'yellow' => '7', 'cyan' => '8');
var_dump(wincache_ucache_add($colors_array));
var_dump(wincache_ucache_add($colors_array));
var_dump(wincache_ucache_get('Blue'));
?>Результат выполнения данного примера:
array(0) { }
array(4) {
["green"]=> int(-1)
["Blue"]=> int(-1)
["yellow"]=> int(-1)
["cyan"]=> int(-1)
}
string(1) "6"
(PECL wincache >= 1.1.0)
wincache_ucache_cas — Сравнивает переменную со старым значением и присваивает ей новое значение
$key, int $old_value, int $new_value): bool
Сравнивает переменную, связанную с key с old_value и,
если она совпадает, присваивает ей new_value.
key
key, который использовался для сохранения переменной в кеш.
key чувствителен к регистру.
old_value
Старое значение переменной, на которую указывает key в пользовательском кеше.
Значение должно быть типа long, иначе функция вернёт false.
new_value
Новое значение, которое будет присвоено указателю переменной key, если будет найдено совпадение.
Значение должно быть типа long, иначе функция вернёт false.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Пример использования wincache_ucache_cas()
<?php
wincache_ucache_set('counter', 2922);
var_dump(wincache_ucache_cas('counter', 2922, 1));
var_dump(wincache_ucache_get('counter'));
?>Результат выполнения данного примера:
bool(true) int(1)
(PECL wincache >= 1.1.0)
wincache_ucache_clear — Удаляет всё содержимое пользовательского кеша
Очищает/удаляет все значения, хранящиеся в пользовательском кеше.
У этой функции нет параметров.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Пример использования wincache_ucache_clear()
<?php
wincache_ucache_set('green', 1);
wincache_ucache_set('red', 2);
wincache_ucache_set('orange', 4);
wincache_ucache_set('blue', 8);
wincache_ucache_set('cyan', 16);
$array1 = array('green', 'red', 'orange', 'blue', 'cyan');
var_dump(wincache_ucache_get($array1));
var_dump(wincache_ucache_clear());
var_dump(wincache_ucache_get($array1));
?>Результат выполнения данного примера:
array(5) { ["green"]=> int(1)
["red"]=> int(2)
["orange"]=> int(4)
["blue"]=> int(8)
["cyan"]=> int(16) }
bool(true)
bool(false)
(PECL wincache >= 1.1.0)
wincache_ucache_dec — Уменьшает значение, связанное с ключом
Уменьшает значение, связанное с key на 1
или как указано в dec_by.
key
key, который использовался для сохранения переменной в кеш.
key чувствителен к регистру.
dec_by
Значение, на которое должна быть уменьшена переменная, связанная с key.
Если аргумент является числом с плавающей точкой, он будет усечён до ближайшего целого числа.
Переменная, связанная с key, должна иметь тип long,
иначе функция завершится ошибкой и вернёт false.
success
Будет установлено значение true в случае успешного выполнения и false в случае возникновения ошибки.
Возвращает уменьшенное значение в случае успешного выполнения и false в случае возникновения ошибки.
Пример #1 Пример использования wincache_ucache_dec()
<?php
wincache_ucache_set('counter', 1);
var_dump(wincache_ucache_dec('counter', 2923, $success));
var_dump($success);
?>Результат выполнения данного примера:
int(2922) bool(true)
(PECL wincache >= 1.1.0)
wincache_ucache_delete — Удаляет переменные из пользовательского кеша
Удаляет элементы из пользовательского кеша, на которые указывает параметр key.
key
Параметр key, который использовался для хранения переменной в кеше.
key чувствителен к регистру.
key может быть массивом ключей.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Если параметр key является массивом, функция возвращает false,
если не удаётся удалить каждый элемент массива из пользовательского кеша,
в противном случае возвращается массив, состоящий из всех удалённых ключей.
Пример #1 Пример использования wincache_ucache_delete() с key в виде строки
<?php
wincache_ucache_set('foo', 'bar');
var_dump(wincache_ucache_delete('foo'));
var_dump(wincache_ucache_exists('foo'));
?>Результат выполнения данного примера:
bool(true) bool(false)
Пример #2 Пример использования wincache_ucache_delete() с key в виде массива
<?php
$array1 = array('green' => '5', 'blue' => '6', 'yellow' => '7', 'cyan' => '8');
wincache_ucache_set($array1);
$array2 = array('green', 'blue', 'yellow', 'cyan');
var_dump(wincache_ucache_delete($array2));
?>Результат выполнения данного примера:
array(4) { [0]=> string(5) "green"
[1]=> string(4) "Blue"
[2]=> string(6) "yellow"
[3]=> string(4) "cyan" }
Пример #3 Пример использования wincache_ucache_delete() с key в виде массива, из которого нельзя удалить некоторые элементы
<?php
$array1 = array('green' => '5', 'blue' => '6', 'yellow' => '7', 'cyan' => '8');
wincache_ucache_set($array1);
$array2 = array('orange', 'red', 'yellow', 'cyan');
var_dump(wincache_ucache_delete($array2));
?>Результат выполнения данного примера:
array(2) { [0]=> string(6) "yellow"
[1]=> string(4) "cyan" }
(PECL wincache >= 1.1.0)
wincache_ucache_exists — Проверяет, существует ли переменная в пользовательском кеше
$key): bool
Проверяет, существует ли переменная key в пользовательском кеше или нет.
key
Параметр key, который использовался для хранения переменной в кеше.
key чувствителен к регистру.
Возвращает true, если переменная с key существует,
в противном случае возвращает false.
Пример #1 Пример использования wincache_ucache_exists()
<?php
if (!wincache_ucache_exists('green'))
wincache_ucache_set('green', 1);
var_dump(wincache_ucache_exists('green'));
?>Результат выполнения данного примера:
bool(true)
(PECL wincache >= 1.1.0)
wincache_ucache_get — Получает переменную, хранящуюся в пользовательском кеше
Получает переменную, хранящуюся в пользовательском кеше.
key
Параметр key, который использовался для хранения переменной в кеше.
key чувствителен к регистру. key может быть массивом ключей.
В этом случае возвращаемое значение будет массивом значений каждого элемента в массиве key.
Если возвращается объект или массив, содержащий объекты, то объекты будут десериализованы.
Подробнее о десериализации объектов смотрите __wakeup().
success
Будет установлено значение true в случае успешного выполнения или false в случае возникновения ошибки.
Если параметр key является строкой, функция возвращает значение переменной,
хранящейся с этим ключом.
Для параметра success будет установлено значение true в случае успешного выполнения
или false в случае возникновения ошибки.
Если параметр key - это массив, параметр success
всегда будет иметь значение true. Возвращённый массив (пары имя => значение) будет содержать только
те пары имя => значение, для которых операция получения в пользовательском кеше была успешной.
Если ни один из ключей в массиве ключей не находит совпадения в пользовательском кеше,
будет возвращён пустой массив.
Пример #1 wincache_ucache_get() с key в виде строки
<?php
wincache_ucache_add('color', 'blue');
var_dump(wincache_ucache_get('color', $success));
var_dump($success);
?>Результат выполнения данного примера:
string(4) "blue" bool(true)
Пример #2 wincache_ucache_get() с key в виде массива
<?php
$array1 = array('green' => '5', 'Blue' => '6', 'yellow' => '7', 'cyan' => '8');
wincache_ucache_set($array1);
$array2 = array('green', 'Blue', 'yellow', 'cyan');
var_dump(wincache_ucache_get($array2, $success));
var_dump($success);
?>Результат выполнения данного примера:
array(4) { ["green"]=> string(1) "5"
["Blue"]=> string(1) "6"
["yellow"]=> string(1) "7"
["cyan"]=> string(1) "8" }
bool(true)
(PECL wincache >= 1.1.0)
wincache_ucache_inc — Увеличивает значение, связанное с ключом
Увеличивает значение, связанное с key на 1
или как указано в inc_by.
key
key, который использовался для сохранения переменной в кеш.
key чувствителен к регистру.
inc_by
Значение, на которое должна быть увеличена переменная, связанная с key.
Если аргумент является числом с плавающей точкой, он будет усечён до ближайшего целого числа.
Переменная, связанная с key, должна иметь тип long,
иначе функция завершится ошибкой и вернёт false.
success
Будет установлено значение true в случае успешного выполнения и false в случае возникновения ошибки.
Возвращает увеличенное значение в случае успешного выполнения и false в случае возникновения ошибки.
Пример #1 Пример использования wincache_ucache_inc()
<?php
wincache_ucache_set('counter', 1);
var_dump(wincache_ucache_inc('counter', 2921, $success));
var_dump($success);
?>Результат выполнения данного примера:
int(2922) bool(true)
(PECL wincache >= 1.1.0)
wincache_ucache_info — Получает информацию о данных, хранящихся в пользовательском кеше
$summaryonly = false, string $key = NULL): array|falseПолучает информацию о данных, хранящихся в пользовательском кеше.
summaryonlyОпределяет, будет ли возвращаемый массив содержать информацию об отдельных записях кеша вместе со сводкой пользовательского кеша.
key
Ключ записи в пользовательском кеше. Если указано, то возвращаемый массив будет содержать информацию только об этой записи кеша.
Если не указано и для summaryonly установлено значение false,
тогда возвращаемый массив будет содержать информацию обо всех записях кеша.
Массив метаданных об использовании пользовательского кеша или false в случае возникновения ошибки
Массив, возвращаемый этой функцией, содержит следующие элементы:
total_cache_uptime - общее время в секундах, в течение которого пользовательский кеш был активен.
total_item_count - общее количество элементов, которые в данный момент находятся в пользовательском кеше.
is_local_cache - true - метаданные кеша предназначены для экземпляра локального кеша,
false, если метаданные предназначены для глобального кеша.
total_hit_count - количество раз, когда данные были получены из кеша.
total_miss_count - количество раз, когда данные не были найдены в кеше.
ucache_entries - массив, содержащий информацию обо всех кешированных элементах:
key_name - имя ключа, который используется для хранения данных.
value_type - тип значения, хранимого ключом.
use_time - время в секундах с момента обращения к файлу в кеше опкодов.
last_check - время в секундах с момента проверки файла на наличие модификаций.
is_session - указывает, являются ли данные переменной сессии.
ttl_seconds - время, оставшееся для данных, чтобы находиться в кеше, 0 означает бесконечность.
age_seconds - время, прошедшее с момента добавления данных в кеш.
hitcount - количество раз, когда данные были получены из кеша.
Пример #1 Пример использования wincache_ucache_info()
<?php
wincache_ucache_get('green');
wincache_ucache_set('green', 2922);
wincache_ucache_get('green');
wincache_ucache_get('green');
wincache_ucache_get('green');
print_r(wincache_ucache_info());
?>Результат выполнения данного примера:
Array
( ["total_cache_uptime"] => int(0)
["is_local_cache"] => bool(false)
["total_item_count"] => int(1)
["total_hit_count"] => int(3)
["total_miss_count"] => int(1)
["ucache_entries"] => Array(1)
( [1] => Array(6)
(
["key_name"] => string(5) "green"
["value_type"] => string(4) "long"
["is_session"] => int(0)
["ttl_seconds"] => int(0)
["age_seconds"] => int(0)
["hitcount"] => int(3)
)
)
)
(PECL wincache >= 1.1.0)
wincache_ucache_meminfo — Получает информацию об использовании памяти пользовательского кеша
Получает информацию об использовании памяти пользовательского кеша.
У этой функции нет параметров.
Массив метаданных об использовании памяти пользовательского кеша или false в случае возникновения ошибки
Массив, возвращаемый этой функцией, содержит следующие элементы:
memory_total - объем памяти в байтах, выделенный для пользовательского кеша
memory_free - объем свободной памяти в байтах, доступной для пользовательского кеша
num_used_blks - количество блоков памяти, используемых пользовательским кешем
num_free_blks - количество свободных блоков памяти, доступных для пользовательского кеша
memory_overhead - объем памяти в байтах, используемый для внутренних структур пользовательского кеша
Пример #1 Пример использования wincache_ucache_meminfo()
<pre>
<?php
print_r(wincache_ucache_meminfo());
?>
</pre>Результат выполнения данного примера:
Array
(
[memory_total] => 5242880
[memory_free] => 5215056
[num_used_blks] => 6
[num_free_blks] => 3
[memory_overhead] => 176
)
(PECL wincache >= 1.1.0)
wincache_ucache_set — Добавляет переменную в пользовательский кеш и перезаписывает переменную, если она уже существует в кеше
Добавляет переменную в пользовательский кеш. Заменяет переменную, если она уже существует в кеше. Добавленная или обновлённая переменная остаётся в пользовательском кеше, пока не истечёт срок её действия или она не будет удалена с помощью функций wincache_ucache_delete() или wincache_ucache_clear().
key
Сохраняет переменную с использованием этого имени key. Если переменная с таким же key
уже существует, функция перезапишет предыдущее значение новым. key чувствителен к регистру.
key также может принимать массив пар имя => значение,
где имена будут использоваться в качестве ключей.
Это можно использовать для добавления нескольких значений в кеш за одну операцию, что позволяет избежать состояния гонки.
value
Значение переменной, которую необходимо сохранить. Value поддерживает все типы данных, кроме ресурсов,
таких как дескрипторы файлов.
Параметр игнорируется, если первым аргументом является массив. Общее руководство - передать null в качестве value
при использовании массива key.
Если value является объектом или массивом, содержащим объекты,
то объекты будут сериализованы. Подробнее о сериализации объектов смотрите в описании __sleep().
valuesАссоциативный массив ключей и значений.
ttl
Время, в течение которого переменная находится в кеше, в секундах. После того, как значение, указанное в ttl
будет передано, сохранённая переменная будет удалена из кеша.
Параметр принимает значение по умолчанию 0, что означает, что переменная останется в кеше,
пока она не будет явно удалена с помощью функций wincache_ucache_delete() или wincache_ucache_clear().
Если key является строкой, функция возвращает true в случае успешного выполнения и false в случае возникновения ошибки.
Если key является массивом, функция возвращает:
false;
Пример #1 Пример использования wincache_ucache_set() с key в виде строки
<?php
$bar = 'BAR';
var_dump(wincache_ucache_set('foo', $bar));
var_dump(wincache_ucache_get('foo'));
$bar1 = 'BAR1';
var_dump(wincache_ucache_set('foo', $bar1));
var_dump(wincache_ucache_get('foo'));
?>Результат выполнения данного примера:
bool(true) string(3) "BAR" bool(true) string(3) "BAR1"
Пример #2 Пример использования wincache_ucache_set() с key в виде массива
<?php
$colors_array = array('green' => '5', 'Blue' => '6', 'yellow' => '7', 'cyan' => '8');
var_dump(wincache_ucache_set($colors_array));
var_dump(wincache_ucache_set($colors_array));
var_dump(wincache_ucache_get('Blue'));
?>Результат выполнения данного примера:
array(0) {}
array(0) {}
string(1) "6"
(PECL wincache >= 1.1.0)
wincache_unlock — Снимает эксклюзивную блокировку данного ключа
$key): boolСнимает исключительную блокировку, которая была получена для данного ключа с помощью wincache_lock(). Если какой-либо другой процесс был заблокирован в ожидании блокировки этого ключа, этот процесс сможет получить блокировку.
Использование wincache_lock() и wincache_unlock() может вызвать взаимную блокировку при выполнении скриптов PHP в многопроцессорной среде, такой как FastCGI. Не используйте эти функции, если вы не уверены, что вам это нужно. Для большинства операций с пользовательским кешем эти функции использовать не обязательно.
keyИмя ключа в кеше для снятия блокировки.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Пример #1 Пример использования wincache_unlock()
<?php
$fp = fopen("/tmp/lock.txt", "r+");
if (wincache_lock(“lock_txt_lock”)) { // получить эксклюзивную блокировку
ftruncate($fp, 0); // обрезать файл
fwrite($fp, "Напишите что-нибудь здесь\n");
wincache_unlock(“lock_txt_lock”); // снять блокировку
} else {
echo "Не удалось получить блокировку!";
}
fclose($fp);
?>
Для сборки модуля WinCache требуется:
Первые два пункта полностью покрываются статьёй руководства » сборка PHP под Windows.
Получение исходного кода WinCache описано в разделе Скачивание PECL-модулей.
Следующие шаги описывают, как компилировать и собирать WinCache под Windows OS:
Откройте консоль командной строки
Перейдите в папку с исходными кодами PHP
Выполните команду:
cscript.exe win32\build\buildconf.js
Выполните команду:
configure.bat --help
--enable-wincache.
Выполните команду:
configure.js [все опции для сборки PHP] --enable-wincache
--enable-wincache это единственная дополнительная опция,
которая требуется для правильной сборки модуля WinCache.
Эта опция соберёт WinCache и будет статически связывать его с PHP dll.
Чтобы создать модуль WinCache в качестве автономной библиотеки DLL, используйте параметр
--enable-wincache=shared.
Выполните команду:
nmake
Следующие шаги описывают процесс проверки того, что модуль был собран корректно:
Перейдите в папку, где находится скомпилированный PHP
Выполните команду:
php.exe -n -d extension=php_wincache.dll -re wincache
XHProf — это легковесный профайлер основанный на иерархии и инструментировании. В процессе сбора данных он отслеживает количество вызовов и инклюзивные метрики рёбер динамического графа вызовов программы. Эксклюзивные метрики, такие как затраченное время, время CPU и потребление памяти, рассчитываются в фазе репортинга/постпроцессинга. Профилирование функции может быть сломано вызывающими или вызываемыми функциями. XHProf отслеживает рекурсивные функции путём анализа циклов в графе вызовов в момент сбора данных и избегает зацикленности путём назначения уникальных имён на основе глубины для рекурсивных вызовов.
XHProf содержит простой HTML интерфейс (написанный на PHP). UI на основе браузера сильно облегчает просмотр результатов и пересылку их всем желающим. Также поддерживается графическое отображение графа вызовов.
Отчёты XHProf часто полезны для анализа структуры запускаемого кода. Иерархическая структура отчётов позволяет определить, к примеру, цепочку вызовов, приведшую к вызову конкретной функции.
XHProf поддерживает сравнение двух разных запусков ("diff") или агрегацию данных нескольких запусков. Сравнительные и агрегированные отчёты, также как одиночные, предоставляют как "плоские", так и "иерархические" взгляды на результаты профилирования.
Дополнительная документация доступна на сайте » facebook xhprof.
В целом не требуется, так как xhprof включает интерфейс, написанный на PHP. Он используется для сохранения и отображения результатов профилирования в удобном виде в браузере. Таким образом, включение встроенного в PHP веб-сервера позволит использовать xprof максимально продуктивно.
Также существует форк GUI интерфейса - » http://github.com/preinheimer/xhprof
Информация по установке этого модуля PECL может быть найдена в главе руководства Установка PECL модулей. Дополнительная информация, такая как новые версии, скачивание, исходные файлы, информация о разработчике и CHANGELOG, может быть найдена здесь: » https://pecl.php.net/package/xhprof
Поведение этих функций зависит от установок в php.ini.
| Имя | По умолчанию | Место изменения | Список изменений |
|---|---|---|---|
| xhprof.output_dir | "" | PHP_INI_ALL |
Краткое разъяснение конфигурационных директив.
xhprof.output_dir
string
Директория используемая реализацией интерфейса iXHProfRuns по умолчанию (класс XHProfRuns_Default) для сохранения результатов профилирования.
Данный модуль не определяет каких-либо типов ресурсов.
Перечисленные ниже константы определены данным модулем и могут быть доступны только в том случае, если PHP был собран с поддержкой этого модуля или же в том случае, если данный модуль был динамически загружен во время выполнения.
XHPROF_FLAGS_NO_BUILTINS
(int)
XHPROF_FLAGS_CPU
(int)
XHPROF_FLAGS_MEMORY
(int)
Пример #1 Примеры использования Xhprof, опционально с GUI
В этом примере профайлер запускается, останавливается и использует встроенный GUI интерфейс для сохранения и разбора результатов. Другими словами, исполнение кода модуля завершается на функции xhprof_disable().
<?php
xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);
for ($i = 0; $i <= 1000; $i++) {
$a = $i * $i;
}
$xhprof_data = xhprof_disable();
$XHPROF_ROOT = "/tools/xhprof/";
include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_lib.php";
include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_runs.php";
$xhprof_runs = new XHProfRuns_Default();
$run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_testing");
echo "http://localhost/xhprof/xhprof_html/index.php?run={$run_id}&source=xhprof_testing\n";
?>Результатом выполнения данного примера будет что-то подобное:
http://localhost/xhprof/xhprof_html/index.php?run=t11_4bdf44d21121f&source=xhprof_testing
(PECL xhprof >= 0.9.0)
xhprof_disable — Останавливает профилирование xhprof
Останавливает профилирование и возвращает собранные данные.
У этой функции нет параметров.
Массив с результатами профилирования.
Пример #1 Пример использования xhprof_disable()
<?php
xhprof_enable();
$foo = strlen("foo bar");
$xhprof_data = xhprof_disable();
print_r($xhprof_data);
?>Результатом выполнения данного примера будет что-то подобное:
Array
(
[main()==>strlen] => Array
(
[ct] => 1
[wt] => 279
)
[main()==>xhprof_disable] => Array
(
[ct] => 1
[wt] => 9
)
[main()] => Array
(
[ct] => 1
[wt] => 610
)
)
(PECL xhprof >= 0.9.0)
xhprof_enable — Запуск профилирования xhprof
$flags = 0, array $options = ?): voidЗапускает профилирование.
flags
Необязательные флаги для получения дополнительной
информации при профилировании. Подробности можно найти в
разделе Константы XHprof.
Например, XHPROF_FLAGS_MEMORY
включает профилирование памяти.
optionsМассив (array) необязательных опций, а конкретно опция 'ignored_functions' со списком функций, которые не нужно профилировать.
null
| Версия | Описание |
|---|---|
| PECL xhprof 0.9.2 |
Добавлен необязательный параметр options.
|
Пример #1 Пример использования xhprof_enable()
<?php
// 1. время исполнения + память + CPU; также игнорируем функции стандартной библиотеки
xhprof_enable(XHPROF_FLAGS_NO_BUILTINS | XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORY);
// 2. время исполнения; игнорируем при профилировании call_user_func*
xhprof_enable(
0,
array('ignored_functions' => array('call_user_func',
'call_user_func_array')));
// 3. время исполнения + память; игнорируем при профилировании call_user_func*
xhprof_enable(
XHPROF_FLAGS_MEMORY,
array('ignored_functions' => array('call_user_func',
'call_user_func_array')));
?>(PECL xhprof >= 0.9.0)
xhprof_sample_disable — Остановить сэмплирующие профилирование xhprof
Остановить сэмплирующие профилирование xhprof.
У этой функции нет параметров.
Массив данных, собранный профайлером.
Пример #1 Пример использования xhprof_sample_disable()
<?php
xhprof_sample_enable();
for ($i = 0; $i <= 10000; $i++) {
$a = strlen($i);
$b = $i * $a;
$c = rand();
}
$xhprof_data = xhprof_sample_disable();
print_r($xhprof_data);
?>Результатом выполнения данного примера будет что-то подобное:
Array
(
[1272935300.800000] => main()
[1272935300.900000] => main()
)
(PECL xhprof >= 0.9.0)
xhprof_sample_enable — Запуск сэмплирующего режима профилирования XHProf
Запуск сэмплирующего режима профилирования, который является облегчённой версией xhprof_enable(). Интервал семплирования составляет 0.1 секунды и при каждой итерации записывается стек вызовов. Данный режим предназначен для снижения накладных расходов при мониторинге производительности.
У этой функции нет параметров.
null
Yac (Yet Another cache) - это свободный от блокировок кеш пользовательских данных с общей памятью, который можно использовать для замены APC и локального кеширования в памяти.
Этот модуль » PECL не поставляется вместе с PHP.
Информация по установке этого модуля PECL может быть найдена в главе руководства Установка PECL модулей. Дополнительная информация, такая как новые версии, скачивание, исходные файлы, информация о разработчике и CHANGELOG, может быть найдена здесь: » https://pecl.php.net/package/yac.
Бинарные файлы Windows (файлы DLL) для этого модуля PECL доступны на сайте PECL.
Поведение этих функций зависит от установок в php.ini.
| Имя | По умолчанию | Место изменения | Список изменений |
|---|---|---|---|
| yac.compress_threshold | -1 | PHP_INI_SYSTEM | |
| yac.debug | 0 | PHP_INI_ALL | |
| yac.enable | 1 | PHP_INI_SYSTEM | |
| yac.enable_cli | 0 | PHP_INI_SYSTEM | |
| yac.keys_memory_size | 4M | PHP_INI_SYSTEM | |
| yac.serializer | php | PHP_INI_SYSTEM | |
| yac.values_memory_size | 64M | PHP_INI_SYSTEM |
Краткое разъяснение конфигурационных директив.
yac.compress_threshold
int
yac.debug
int
yac.enable
int
yac.enable_cli
int
yac.keys_memory_size
string
yac.serializer
string
yac.values_memory_size
string
Перечисленные ниже константы определены данным модулем и могут быть доступны только в том случае, если PHP был собран с поддержкой этого модуля или же в том случае, если данный модуль был динамически загружен во время выполнения.
YAC_VERSION
(string)
YAC_MAX_KEY_LEN
(int)
YAC_MAX_VALUE_RAW_LEN
(int)
YAC_MAX_RAW_COMPRESSED_LEN
(int)
YAC_SERIALIZER_PHP
(int)
YAC_SERIALIZER_JSON
(int)
YAC_SERIALIZER_IGBINARY
(int)
YAC_SERIALIZER_MSGPACK
(int)
YAC_SERIALIZER
(string)
(PECL yac >= 1.0.0)
(PECL yac >= 1.0.0)
Yac::add — Сохраняет в кеш
$key_vals): boolДобавляет элемент в кеш.
keysКлюч (string)
valueСмешанное значение. Могут быть сохранены все типы значений php, кроме resource
ttlВремя жизни
bool, true в случае успешного выполнения, false в случае возникновения ошибки
Замечание:
Yac::add() может завершиться с ошибкой, если не удалось получить блокировку cas, поэтому, если вам нужно, чтобы значение сохранялось должным образом, вы можете написать следующее:
Пример #1 Убедитесь, что элемент хранится
while(!$yac->set("key", "vale));
(PECL yac >= 1.0.0)
Yac::__construct — Конструктор класса
$prefix = "")Префикс используется для добавления к ключам, его можно использовать для предотвращения конфликтов между приложениями.
prefixПрефикс (string)
(PECL yac >= 1.0.0)
Yac::delete — Удаляет элементы из кеша
$keys, int $ttl = ?): boolУдаляет элементы из кеша
keysСтроковый ключ или массив из нескольких ключей, которые нужно удалить
ttlЕсли задана задержка, удаление отметит элементы как недопустимые в течение ttl секунд.
(PECL yac >= 1.0.0)
Yac::dump — Дамп кеша
numМаксимальное количество элементов, которые должны быть возвращены
Смешанное значение.
(PECL yac >= 1.0.0)
Yac::flush — Очищает кеш
Удаляет все кешированные значения
У этой функции нет параметров.
Логическое значение, всегда возвращает true
(PECL yac >= 1.0.0)
Yac::get — Извлекает значения из кеша
keyКлюч (string) или массив (array), состоящий из нескольких ключей
cas
Если не null, будет установлен регистр извлечённых элементов.
Смешанное значение в случае успешного выполнения, false в случае возникновения ошибки
(PECL yac >= 1.0.0)
Yac::__get — Геттер
keyКлюч (string)
Смешанное значение в случае успешного выполнения, null в случае возникновения ошибки
(PECL yac >= 1.0.0)
Yac::info — Состояние кеша
Получает статус кеш-системы
У этой функции нет параметров.
Вернуть массив, соответствующий: "memory_size", "slots_memory_size", "values_memory_size", "segment_size", "segment_num", "miss", "hits", "fails", "kicks", "recycles", "slots_size", "slots_used"
(PECL yac >= 1.0.0)
Yac::set — Сохраняет в кеш
Добавляет элемент в кеш, если ключ уже существует, заменяет его.
keysКлюч (string)
valueСмешанное значение. Могут быть сохранены все типы значений php, кроме resource
ttlВремя жизни
Собственное значение
(PECL yac >= 1.0.0)
Yac::__set — Сеттер
keysКлюч (string)
valueСмешанное значение. Могут быть сохранены все типы значений php, кроме resource
Всегда возвращает собственное значение
Для сборки этого модуля не требуются внешние библиотеки.
Этот модуль » PECL не поставляется вместе с PHP.
Информация по установке этого модуля PECL может быть найдена в главе руководства Установка PECL модулей. Дополнительная информация, такая как новые версии, скачивание, исходные файлы, информация о разработчике и CHANGELOG, может быть найдена здесь: » https://pecl.php.net/package/openal.
DLL для этого модуля PECL в данный момент недоступна. Смотрите также раздел сборка на Windows.
Данный модуль не определяет никакие директивы конфигурации в php.ini.
Этот модуль определяет четыре типа ресурсов: Open AL(Device) - возвращается openal_device_open(), Open AL(Context) - возвращается openal_context_create(), Open AL(Buffer) - возвращается openal_buffer_create(), и Open AL(Source) - возвращается openal_source_create().
Перечисленные ниже константы определены данным модулем и могут быть доступны только в том случае, если PHP был собран с поддержкой этого модуля или же в том случае, если данный модуль был динамически загружен во время выполнения.
ALC_FREQUENCY
(int)
ALC_REFRESH
(int)
ALC_SYNC
(int)
AL_FREQUENCY
(int)
AL_BITS
(int)
AL_CHANNELS
(int)
AL_SIZE
(int)
AL_BUFFER
(int)
AL_SOURCE_RELATIVE
(int)
AL_SOURCE_STATE
(int)
AL_PITCH
(int)
AL_GAIN
(int)
AL_MIN_GAIN
(int)
AL_MAX_GAIN
(int)
AL_MAX_DISTANCE
(int)
AL_ROLLOFF_FACTOR
(int)
AL_CONE_OUTER_GAIN
(int)
AL_CONE_INNER_ANGLE
(int)
AL_CONE_OUTER_ANGLE
(int)
AL_REFERENCE_DISTANCE
(int)
AL_POSITION
(int)
AL_VELOCITY
(int)
AL_DIRECTION
(int)
AL_ORIENTATION
(int)
AL_FORMAT_MONO8
(int)
AL_FORMAT_MONO16
(int)
AL_FORMAT_STEREO8
(int)
AL_FORMAT_STEREO16
(int)
AL_INITIAL
(int)
AL_PLAYING
(int)
AL_PAUSED
(int)
AL_STOPPED
(int)
AL_LOOPING
(int)
AL_TRUE
(int)
AL_FALSE
(int)
(PECL openal >= 0.1.0)
openal_buffer_create — Сгенерировать буфер OpenAL
У этой функции нет параметров.
Возвращает ресурс Open AL(Buffer) в случае
успешного выполнения или false в случае возникновения ошибки.
(PECL openal >= 0.1.0)
openal_buffer_data — Загрузка буфера с данными
$buffer,$format,$data,$freqbufferРесурс Open AL(Buffer) (созданный ранее с помощью openal_buffer_create()).
format
Формат data, представленный одной из констант:
AL_FORMAT_MONO8,
AL_FORMAT_MONO16,
AL_FORMAT_STEREO8 и
AL_FORMAT_STEREO16
data
Блок двоичных аудиоданных в указанном формате format
и с частотой freq.
freq
Частота data, заданная в герцах.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PECL openal >= 0.1.0)
openal_buffer_destroy — Уничтожает буфер OpenAL
$buffer): boolbufferРесурс Open AL(Buffer) (ранее созданный с помощью openal_buffer_create()).
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PECL openal >= 0.1.0)
openal_buffer_get — Получить свойство буфера OpenAL
$buffer, int $property): int|falsebufferРесурс Open AL(Buffer) (созданный ранее с помощью openal_buffer_create()).
property
Одно из свойств, заданное в виде константы:
AL_FREQUENCY,
AL_BITS,
AL_CHANNELS и
AL_SIZE.
Возвращает целочисленное значение, соответствующее запрошенному свойству property или false в случае возникновения ошибки.
(PECL openal >= 0.1.0)
openal_buffer_loadwav — Загрузить файл в формате wav в буфер
$buffer, string $wavfile): boolbufferРесурс Open AL(Buffer) (ранее созданный с помощью openal_buffer_create()).
wavfileПуть к файлу .wav в файловой системе local.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PECL openal >= 0.1.0)
openal_context_create — Создать контекст обработки звука
$device): resourcedeviceРесурс Open AL(Device) (созданный ранее с помощью openal_device_create()).
Возвращает ресурс Open AL(Context) в случае
успешного выполнения, false в случае возникновения ошибки.
(PECL openal >= 0.1.0)
openal_context_current — Сделать указанный контекст текущим
$context): boolcontextРесурс Open AL(Context) (созданный ранее с помощью openal_context_create()).
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PECL openal >= 0.1.0)
openal_context_destroy — Уничтожает контекст
$context): boolcontextРесурс Open AL(Context) (созданный ранее с помощью openal_context_create()).
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PECL openal >= 0.1.0)
openal_context_process — Обработать указанный контекст
$context): boolcontextРесурс Open AL(Context) (созданный ранее с помощью openal_context_create()).
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PECL openal >= 0.1.0)
openal_context_suspend — Приостановить указанный контекст
$context): boolcontextРесурс Open AL(Context) (созданный ранее с помощью openal_context_create()).
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PECL openal >= 0.1.0)
openal_device_close — Закрыть устройство OpenAL
$device): booldeviceРесурс Open AL(Device) (созданный ранее с помощью openal_device_open()), который нужно закрыть.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PECL openal >= 0.1.0)
openal_device_open — Инициализировать звуковой уровень OpenAL
$device_desc = ?): resourcedevice_desc
При необходимости открыть аудиоустройство, указав значение параметра device_desc.
Если device_desc не указан, будет использовано первое аудиоустройство.
Возвращает ресурс Open AL(Device) в случае успешного выполнения
или false в случае возникновения ошибки.
(PECL openal >= 0.1.0)
openal_listener_get — Получить свойство прослушивателя
property
Запрашиваемое свойство, представленное одной из констант:
AL_GAIN (float),
AL_POSITION (array(float,float,float)),
AL_VELOCITY (array(float,float,float)) и
AL_ORIENTATION (array(float,float,float)).
Возвращает число с плавающей точкой или массив чисел с плавающими точками (при необходимости) или false в случае возникновения ошибки.
(PECL openal >= 0.1.0)
openal_listener_set — Установка свойства прослушивателя
property
Устанавливаемое свойство, представленное одной из констант:
AL_GAIN (float),
AL_POSITION (array(float,float,float)),
AL_VELOCITY (array(float,float,float)) и
AL_ORIENTATION (array(float,float,float)).
settingЗначение для установки, либо число с плавающей точкой, либо массив с числами с плавающими точками.
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
(PECL openal >= 0.1.0)
openal_source_create — Сгенерировать источник ресурса
У этой функции нет параметров.
Возвращает ресурс Open AL(Source) в случае успешного выполнения
или false в случае возникновения ошибки.
(PECL openal >= 0.1.0)
openal_source_destroy — Уничтожение ресурса источника