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

Дерево руководства
Глава 125 · От первого результата к полному официальному справочнику
Miscellaneous: полный справочник разных функций PHP
Все 37 узлов официальной ветки: 31 функция и шесть структурных страниц — от первой понятной задачи до полного договора, ошибок, версий, SAPI и платформы.
Разные функции PHP: почему они собраны вместе и с чего начать
Miscellaneous — официальный раздел для функций, которым не подошла другая категория. Это не один API: здесь рядом находятся управление завершением сценария, паузы, двоичные данные, подсветка исходника, состояние HTTP-соединения и Windows-консоль. Поэтому начинать надо с задачи, а не читать список как последовательный урок.
| Если нужно | Откройте | Что получите |
|---|---|---|
| Остановить CLI/HTTP-сценарий | exit | Строковое сообщение либо целый код; границы shutdown/finally. |
| Сделать короткую паузу | sleep, usleep, time_nanosleep | Явные единицы, результат и платформенные границы. |
| Собрать/разобрать бинарный протокол | pack / unpack | Байты, формат, длину и порядок endian. |
| Понять уход HTTP-клиента | connection_aborted / connection_status | Наблюдаемое состояние после реальной записи, а не магическую отмену. |
| Сгенерировать идентификатор | uniqid | Границы time-based ID и безопасная альтернатива для секретов. |
| Работать с Windows-консолью | sapi_windows_cp_get | Отдельный Windows-only маршрут с реальными проверками. |
| Вызвать Python, Node.js или другую программу | exec, system, shell_exec, passthru и proc_open | Раздельные stdout/stderr/exit code, безопасный argv и лимиты процесса. |
Установка и доступность: Core, Standard, SAPI и операционная система
Для основных функций отдельная установка не нужна: они входят в PHP. Но наличие имени ещё не означает одинаковое поведение везде. SAPI — способ запуска PHP: CLI, встроенный сервер, FPM, Apache-модуль и другие. Функции соединения имеют смысл в HTTP-SAPI, sys_getloadavg отсутствует в Windows, а sapi_windows_* существуют только в Windows-сборке.
| Группа | Где проверять | Честная граница |
|---|---|---|
| Core/Standard | function_exists + версия PHP | Семантика могла меняться; смотрите changelog карточки. |
| connection_* / ignore_user_abort | Изолированный localhost HTTP | CLI показывает тип, но не эмулирует уход браузера. |
| sapi_windows_* | Отдельный Windows-процесс/консоль | На Linux/macOS функции отсутствуют; это не ошибка переносимого кода. |
| sys_getloadavg | Unix-хост и function_exists | Windows-результат нельзя подделывать числом. |
| get_browser | Настроенный browscap | Без внешней базы возможностей функция выдаёт предупреждение/false. |
Проверка синтаксиса не доказывает работу HTTP, консоли или внешнего browscap. В примерах явно указано, что было реально выполнено, что проверено только на Windows и что остаётся контекстным фрагментом.
Runtime-настройки: что меняет поведение функций
Официальная ветка задаёт следующие INI-настройки. INI_SYSTEM обычно задаётся администратором сервера; менять её посреди запроса нельзя. Цвета подсветки формируют HTML и не делают просмотр исходника безопасным.
| Настройка | Default | Уровень | Влияние и практическая проверка |
|---|---|---|---|
| ignore_user_abort | "0" | INI_ALL | Продолжать ли после обнаруженного disconnect. Функция ignore_user_abort читает/меняет режим для текущего выполнения. |
| highlight.string | "#DD0000" | INI_ALL | Цвет строк в HTML, который создают highlight_file/highlight_string. |
| highlight.comment | "#FF8000" | INI_ALL | Цвет комментариев. |
| highlight.keyword | "#007700" | INI_ALL | Цвет ключевых слов. |
| highlight.default | "#0000BB" | INI_ALL | Цвет обычного текста PHP-кода. |
| highlight.html | "#000000" | INI_ALL | Цвет HTML вне PHP-тегов. |
| highlight.bg | — | только в описании страницы | Упоминается ниже официальной таблицы, но отсутствует в её современном перечне options; не проектируйте переносимый код вокруг этой строки. |
| browscap | NULL | INI_SYSTEM | Путь к browser capabilities file для get_browser. База внешняя, требует обновления и доверенной поставки. |
Сначала читайте эффективное значение через ini_get и фиксируйте конфигурацию рядом с окружением. Не полагайтесь на php.ini локальной машины как на доказательство настройки production FPM.
Предопределённые константы: состояния соединения и смещение payload
Три CONNECTION_* значения кодируют состояние соединения. NORMAL равен нулю, ABORTED и TIMEOUT — независимые биты; поэтому комбинированное состояние читают побитовой операцией &, а не одним равенством.
| Константа | Когда существует | Смысл |
|---|---|---|
| CONNECTION_NORMAL | Всегда в расширении | Нормальное состояние; значение 0. |
| CONNECTION_ABORTED | Всегда в расширении | Бит 1: клиентский разрыв был обнаружен. |
| CONNECTION_TIMEOUT | Всегда в расширении | Бит 2: достигнут тайм-аут соединения/сценария. |
| __COMPILER_HALT_OFFSET__ | Только в файле, где вызван __halt_compiler() | Байтовое смещение первого байта после остановки компилятора. |
Константа halt имеет смысл вместе с __halt_compiler; в другом файле проверяйте defined и не угадывайте offset по длине строки. Практический декодер маски показан в connection_status.
Вызов другого языка: где заканчивается Miscellaneous
Глобальные exec(), system(), shell_exec() и passthru() легко принять за «разные функции». В официальном PHP Manual это отдельная ветка System Program Execution. Здесь мы ставим явную границу, чтобы читатель не спутал eval() с запуском отдельной программы, а глобальную exec() — с PDO::exec() или curl_exec().
| Инструмент | Что получает PHP | Когда выбирать |
|---|---|---|
exec() | Массив строк stdout, последнюю строку и отдельный exit code. | Короткий текстовый отчёт, где важно отличить текст от кода завершения. |
system() | Сразу печатает stdout; return содержит только последнюю строку. | Доверенный построчный CLI-отчёт; в HTTP нужно учитывать все уровни буферизации. |
shell_exec() | Весь stdout одной строкой, но без отдельного exit code. | Только когда нет бизнес-решения по успеху: null не различает пустой успех и ряд ошибок. |
passthru() | Печатает сырые bytes; результат не возвращается строкой. | Доверенный бинарный вывод; до HTTP-тела задают Content-Type, а для атомарного ответа сначала проверяют весь результат. |
proc_open() | Отдельные stdin/stdout/stderr, argv, cwd, environment и resource процесса. | Интеграция с Python/Node/C, где нужны JSON, диагностика, deadline и проверка схемы. |
Полный путь данных разобран в практической главе о PHP, Python и Node.js: PHP формирует проверенный JSON, запускает фиксированный worker, читает stdout/stderr, проверяет exit code, декодирует JSON и проверяет типы до публикации результата.
Полный справочник Miscellaneous: 31 функция по задачам
Это полный официальный список текущей ветки book.misc. Каждый пункт ведёт к одному каноническому якорю; прежние карточки constant/define/defined и функций времени не дублируются.
Управление выполнением и HTTP
Время, ожидание и нагрузка
Двоичные строки и контейнер в файле
Константы и динамическое имя
Capabilities и исходный код
Windows SAPI
sapi_windows_cp_getsapi_windows_cp_setsapi_windows_cp_is_utf8sapi_windows_cp_convsapi_windows_set_ctrl_handlersapi_windows_generate_ctrl_eventsapi_windows_vt100_support
Идентификаторы
Changelog официального раздела: изменения, которые меняют код
| Версия | Функция | Изменение |
|---|---|---|
| 8.5.0 | hrtime | macOS использует CLOCK_UPTIME_RAW вместо mach_absolute_time. |
| 8.4.0 | exit | Стал proper function: обычные типы/strict_types, named argument и variable function. |
| 8.4.0 | exit | Параметрless exit в shutdown/destructor сбрасывает прежний exit code в 0. |
| 8.4.0 | highlight_string | Возврат уточнён с string|bool до string|true. |
| 8.3.0 | highlight_file / highlight_string | Изменился генерируемый HTML. |
| 8.1.0 | define | Значение может быть объектом. |
| 8.0.0 | constant | Неизвестное имя теперь бросает Error вместо E_WARNING + null. |
| 8.0.0 | define | case_insensitive=true вызывает E_WARNING; false ещё принимается. |
| 8.0.0 | ignore_user_abort | enable стал nullable. |
| 8.0.0 | pack | Больше не возвращает false при ошибке. |
| 8.0.0 | sapi_windows_vt100_support | enable стал nullable. |
| 8.0.0 | sleep | Отрицательные seconds бросают ValueError вместо warning + false. |
| 7.3.0 | define | case_insensitive deprecated перед удалением поддержки. |
| 7.2.0 | pack / unpack | Float/double получили явный big/little endian. |
| 7.1.1 / 7.0.15 | pack | Добавлены e/E/g/G для byte order float/double. |
| 7.1.0 | unpack | Добавлен необязательный offset. |
Таблица воспроизводит все строки официальной страницы changelog.misc по зафиксированному снимку. Подробное следствие и рабочий пример находятся в соответствующей карточке.
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
connection_abortedПроверить, обнаружил ли текущий SAPI отключение клиента.
PHP 4+ · standard
connection_aborted(): intПроверить, обнаружил ли текущий SAPI отключение клиента.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Код формирует очередную порцию
- SAPI пытается отправить её через буферы/сервер
- Разрыв становится наблюдаемым
- connection_aborted возвращает 1
Первый запуск и развитие задачи
<?php
$status = connection_status();
echo $status === CONNECTION_NORMAL ? "normal\n" : "other\n";
echo connection_aborted() === 0 ? "connected\n" : "aborted\n";
Ожидаемый результат
normal
connected
CLI-процесс не обслуживает браузерное соединение, поэтому это только минимальная проверка типов и исходного состояния. Настоящий disconnect проверяется отдельным локальным HTTP-опытом.
<?php
// endpoint.php — только для отдельного localhost-теста.
ignore_user_abort(true);
while (ob_get_level() > 0) { ob_end_flush(); }
header('Content-Type: text/plain');
for ($part = 1; $part <= 200; $part++) {
echo str_repeat('x', 65536);
flush();
if (connection_aborted()) {
file_put_contents(__DIR__ . '/observed.txt',
connection_status() . "\n", LOCK_EX);
break;
}
usleep(10000);
}
Запускайте файл отдельным php -S на 127.0.0.1, подключайте локальный сокет, прочитайте начало ответа и закройте клиент. Проверенная harness-процедура хранится в evidence/misc-connection-http-test.py. Буферы, веб-сервер и прокси влияют на момент обнаружения; это фрагмент, а не обещание боевого SAPI.
Не стройте бесконечный цикл ожидания disconnect. Работа должна иметь собственный deadline, отмену и идемпотентность; долгие задания выносите из HTTP в очередь.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| Параметры | Нет. |
| Возврат | 1 после обнаруженного отключения, иначе 0. Это int, хотя условие if принимает его как boolean. |
| Момент обнаружения | Обычно после попытки реально отправить данные; echo без доставки через буферы не гарантирует обновление состояния. |
Ошибки и границы. Функция сообщает состояние соединения, а не причину остановки процесса. Тайм-аут, исключение и завершение воркера требуют отдельных сигналов.
Версии и платформа. Реальное обнаружение зависит от SAPI, веб-сервера, reverse proxy, буферов и момента записи.
Рядом: connection_status, ignore_user_abort.
connection_statusПолучить битовую маску состояния текущего клиентского соединения.
PHP 4+ · standard
connection_status(): intПолучить битовую маску состояния текущего клиентского соединения.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Получить status
- Проверить бит ABORTED
- Проверить бит TIMEOUT
- Собрать решение по обоим признакам
Первый запуск и развитие задачи
<?php
function connectionLabels(int $status): array
{
$labels = [];
if (($status & CONNECTION_ABORTED) !== 0) { $labels[] = 'aborted'; }
if (($status & CONNECTION_TIMEOUT) !== 0) { $labels[] = 'timeout'; }
return $labels === [] ? ['normal'] : $labels;
}
foreach ([CONNECTION_NORMAL, CONNECTION_ABORTED,
CONNECTION_ABORTED | CONNECTION_TIMEOUT] as $status) {
echo implode('+', connectionLabels($status)), "\n";
}
Ожидаемый результат
normal
aborted
aborted+timeout
CONNECTION_NORMAL равен нулю, а остальные состояния — биты. Проверка status === CONNECTION_ABORTED потеряла бы второй признак в комбинированном состоянии.
<?php
// endpoint.php — только для отдельного localhost-теста.
ignore_user_abort(true);
while (ob_get_level() > 0) { ob_end_flush(); }
header('Content-Type: text/plain');
for ($part = 1; $part <= 200; $part++) {
echo str_repeat('x', 65536);
flush();
if (connection_aborted()) {
file_put_contents(__DIR__ . '/observed.txt',
connection_status() . "\n", LOCK_EX);
break;
}
usleep(10000);
}
Запускайте файл отдельным php -S на 127.0.0.1, подключайте локальный сокет, прочитайте начало ответа и закройте клиент. Проверенная harness-процедура хранится в evidence/misc-connection-http-test.py. Буферы, веб-сервер и прокси влияют на момент обнаружения; это фрагмент, а не обещание боевого SAPI.
Эта маска не заменяет журнал задания: сохраняйте собственные статусы «принято», «обработано», «повторить». CONNECTION_TIMEOUT относится к состоянию PHP-соединения, а не к HTTP-тайм-ауту внешнего API.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| Параметры | Нет. |
| Возврат | Битовая маска из CONNECTION_NORMAL (0), CONNECTION_ABORTED и CONNECTION_TIMEOUT. |
| Проверка | Для ненулевых флагов используйте ($status & FLAG) !== 0; равенство подходит лишь когда точно исключены комбинации. |
Ошибки и границы. Ноль означает нормальное состояние, поэтому условие if ($status) не различает конкретные ненормальные причины.
Версии и платформа. Доступные биты заданы константами текущего PHP; наблюдение разрыва зависит от SAPI.
Рядом: connection_aborted, ignore_user_abort.
exitНемедленно прекратить текущий PHP-сценарий с сообщением или кодом CLI.
PHP 4+; proper function semantics — PHP 8.4+ · standard
exit(string|int $status = 0): neverНемедленно прекратить текущий PHP-сценарий с сообщением или кодом CLI.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Проверить условие остановки
- Сформировать сообщение либо целый код
- exit начинает завершение
- Shutdown/destructors; обычное продолжение отсутствует
Первый запуск и развитие задачи
<?php
$process = proc_open([PHP_BINARY, '-n', __DIR__ . '/child.php'],
[0 => ['file', 'NUL', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']],
$pipes, __DIR__);
if (!is_resource($process)) { throw new RuntimeException('child'); }
$stdout = stream_get_contents($pipes[1]); fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]); fclose($pipes[2]);
$status = proc_close($process);
echo 'stdout=', $stdout, "\nstatus=", $status, "\nstderr=", $stderr;
Ожидаемый результат
stdout=maintenance
status=0
stderr=Дочерний CLI завершился сам. Строка — сообщение в stdout; это не ненулевой код ошибки. Для CLI-автоматизации чаще пишут диагностику в STDERR и передают целый код.
<?php
$process = proc_open([PHP_BINARY, '-n', __DIR__ . '/child.php'],
[0 => ['file', 'NUL', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']],
$pipes, __DIR__);
if (!is_resource($process)) { throw new RuntimeException('child'); }
$stdout = stream_get_contents($pipes[1]); fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]); fclose($pipes[2]);
$status = proc_close($process);
echo $stdout, 'status=', $status, "\n", 'stderr=', $stderr;
Ожидаемый результат
before
shutdown
status=4
stderr=exit(status: 4) — именованный аргумент, доступный с PHP 8.4. Shutdown-функция выполняется, строка finally отсутствует: exit не проходит через этот блок.
В библиотечном методе часто удобнее выбросить исключение и позволить верхней границе сформировать HTTP/CLI-ответ. После header("Location: ...") сценарий сам не прекращается; если продолжение опасно, завершите его явно на границе контроллера.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| status: string | Печатается перед остановкой; код процесса — 0. |
| status: int | Код процесса. Используйте 0…254; 255 зарезервирован PHP. |
| Возврат never | Успешный вызов не возвращается к следующей строке. |
| Завершение | Shutdown-функции и деструкторы запускаются, но finally не выполняется. Нельзя отключить или затенить namespaced-функцией. |
Ошибки и границы. С PHP 8.4 применяются обычные правила типов и strict_types; массив/ресурс вызывают TypeError. До 8.4 они приводились к строке. Параметрless exit в shutdown/destructor с 8.4 сбрасывает прежний код на 0.
Версии и платформа. С PHP 8.4 доступны именованный аргумент и variable function. Синтаксис exit; без скобок сохраняется как специальная форма.
Рядом: die.
dieИспользовать точный псевдоним exit; отдельной семантики у die нет.
PHP 4+; alias of exit, proper function semantics — PHP 8.4+ · standard
die(string|int $status = 0): neverИспользовать точный псевдоним exit; отдельной семантики у die нет.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Код встречает die
- Читает его как exit
- Применяет тот же договор status
- Завершает сценарий
Первый запуск и развитие задачи
<?php
$process = proc_open([PHP_BINARY, '-n', __DIR__ . '/child.php'],
[0 => ['file', 'NUL', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']],
$pipes, __DIR__);
if (!is_resource($process)) { throw new RuntimeException('child'); }
$out = stream_get_contents($pipes[1]); fclose($pipes[1]);
$err = stream_get_contents($pipes[2]); fclose($pipes[2]);
$code = proc_close($process);
echo $out, "|", $code, "|", $err;
Ожидаемый результат
denied|0|Переменная $stop содержит имя alias. Строковый status печатается, поэтому код процесса остаётся 0.
<?php
$process = proc_open([PHP_BINARY, '-n', __DIR__ . '/child.php'],
[0 => ['file', 'NUL', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']],
$pipes, __DIR__);
if (!is_resource($process)) { throw new RuntimeException('child'); }
$out = stream_get_contents($pipes[1]); fclose($pipes[1]);
$err = stream_get_contents($pipes[2]); fclose($pipes[2]);
$code = proc_close($process);
echo 'empty=', $out === '' ? 'yes' : 'no', "\ncode=", $code, "\n";
Ожидаемый результат
empty=yes
code=3
die(3) ничего не печатает и завершает только дочерний процесс с кодом 3. Родитель может принять решение по коду.
Не выбирайте между die и exit по выдуманной производительности. В проекте полезнее один согласованный стиль и явная политика: где завершает CLI, а где библиотека возвращает/выбрасывает ошибку.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| Статус | Те же string/int и правила кода 0…254, что у exit. |
| Возврат | never: выполнение не продолжается. |
| Alias | Сигнатура, типы, shutdown/destructor/finally и изменения PHP 8.4 полностью принадлежат exit. |
Ошибки и границы. Все ошибки типов и ограничения exit применяются без изменений.
Версии и платформа. Официальная страница — alias-ссылка на exit; самостоятельный контракт не расходится с ней.
Рядом: exit.
evalВыполнить строку как PHP-код — опасная граница и почти всегда сигнал выбрать более ясную модель.
PHP 4+ · standard
eval(string $code): mixedВыполнить строку как PHP-код — опасная граница и почти всегда сигнал выбрать более ясную модель.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Строка входит в eval
- Компилятор PHP разбирает её в текущей области
- Код получает права процесса
- return/изменённые переменные выходят наружу
Первый запуск и развитие задачи
<?php
function totalWithInternalRule(int $price): int
{
$result = eval('return $price * 2;');
if (!is_int($result)) { throw new RuntimeException('rule'); }
return $result;
}
echo totalWithInternalRule(75), "\n";
Ожидаемый результат
150
Строка кода записана разработчиком и не приходит от пользователя. return завершает только eval и отдаёт 150 в $result. Пример показывает механику, а не рекомендацию строить правила строками.
<?php
try {
eval('return 1 + ;');
} catch (ParseError $error) {
echo "invalid internal code\n";
}
$rules = [
'double' => static fn (int $value): int => $value * 2,
'vat20' => static fn (int $value): int => intdiv($value * 120, 100),
];
echo $rules['vat20'](500), "\n";
Ожидаемый результат
invalid internal code
600
ParseError перехватывается с PHP 7. Таблица известных callable решает обычную задачу выбора правила без исполнения произвольного текста и допускает статический анализ.
| Реальная потребность | Более ясная альтернатива |
|---|---|
| Выбрать одно из известных правил | Массив callable / match / Strategy. |
| Шаблон страницы | Подключаемый доверенный шаблон или шаблонизатор с ограниченным языком. |
| Формула пользователя | Парсер формул с белым списком операций и лимитами, не PHP-код. |
| Конфигурация | JSON/YAML/массив со схемой и проверкой типов. |
Нельзя «надёжно очистить» произвольный PHP-текст регулярным выражением. Изоляция требует отдельного процесса/контейнера, минимальных прав, лимитов и всё равно не превращает eval в безопасный пользовательский язык.
eval() выполняет PHP-текст внутри текущего PHP-процесса; он не запускает Python, Node.js или C-программу. Для этой задачи используйте отдельный справочник запуска программ и цельный пример обмена JSON с Python/Node.js.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| code | PHP-код без начального/конечного тега; инструкции завершаются ;. Можно выйти в HTML-режим тегами, но это ещё сильнее усложняет границу. |
| Область | Видит и может менять переменные места вызова. Объявленные функции/классы создаются в глобальном namespace, как в отдельном include-файле. |
| Возврат | null, если внутри нет return; иначе значение return. ParseError при синтаксической ошибке с PHP 7. |
| Синтаксис | Это language construct: variable function и named arguments не применяются. Фатальная ошибка внутри завершает весь сценарий. |
Ошибки и границы. Никогда не соединяйте eval с полем формы, URL, записью БД, загруженным файлом или ответом API. set_error_handler не ловит ParseError; используйте catch (ParseError).
Версии и платформа. С PHP 7 синтаксическая ошибка выбрасывает ParseError; раньше eval возвращал false. Поведение области и глобальных объявлений принципиально важно.
ignore_user_abortРешить, должен ли PHP продолжать после обнаруженного отключения клиента.
PHP 4+ · standard
ignore_user_abort(?bool $enable = null): intРешить, должен ли PHP продолжать после обнаруженного отключения клиента.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Сохранить прежний режим
- Включить продолжение только для ограниченного участка
- Проверять собственный deadline/идемпотентность
- Восстановить прежний режим
Первый запуск и развитие задачи
<?php
$before = ignore_user_abort();
$returned = ignore_user_abort(true);
echo $returned === $before ? "previous returned\n" : "mismatch\n";
echo ignore_user_abort() === 1 ? "enabled\n" : "disabled\n";
ignore_user_abort((bool) $before);
echo ignore_user_abort() === $before ? "restored\n" : "not restored\n";
Ожидаемый результат
previous returned
enabled
restored
Вызов с аргументом возвращает предыдущее состояние, а не новое. После опыта исходная настройка восстановлена.
<?php
// endpoint.php — только для отдельного localhost-теста.
ignore_user_abort(true);
while (ob_get_level() > 0) { ob_end_flush(); }
header('Content-Type: text/plain');
for ($part = 1; $part <= 200; $part++) {
echo str_repeat('x', 65536);
flush();
if (connection_aborted()) {
file_put_contents(__DIR__ . '/observed.txt',
connection_status() . "\n", LOCK_EX);
break;
}
usleep(10000);
}
Запускайте файл отдельным php -S на 127.0.0.1, подключайте локальный сокет, прочитайте начало ответа и закройте клиент. Проверенная harness-процедура хранится в evidence/misc-connection-http-test.py. Буферы, веб-сервер и прокси влияют на момент обнаружения; это фрагмент, а не обещание боевого SAPI.
Продолжение после разрыва не подтверждает доставку ответа и не защищает от kill, timeout, сбоя хоста или исключения. Для заказа сначала фиксируйте транзакционное состояние, а тяжёлую работу отдавайте очереди.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| enable=true/false | Изменяет одноимённую INI-настройку для текущего выполнения. |
| enable=null/нет аргумента | Только читает прежнее/текущее состояние. Nullable с PHP 8. |
| Возврат | Предыдущее состояние как int 0/1. |
| CLI | Если TTY исчезнет, запись может завершить сценарий, если игнорирование выключено. |
Ошибки и границы. PHP замечает разрыв при попытке отправки, а буферы могут отложить этот момент. Не используйте настройку для бесконечного фонового цикла.
Версии и платформа. Параметр nullable с PHP 8. Поведение зависит от SAPI и буферизации.
Рядом: connection_aborted, connection_status.
sys_getloadavgПолучить среднюю системную нагрузку за 1, 5 и 15 минут там, где ОС это поддерживает.
PHP 5.1.3+; unavailable on Windows · standard
sys_getloadavg(): array|falseПолучить среднюю системную нагрузку за 1, 5 и 15 минут там, где ОС это поддерживает.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Проверить доступность
- Получить ровно три окна
- Сопоставить с CPU/воркерами и собственной политикой
- Отложить необязательное задание либо продолжить
Первый запуск и развитие задачи
<?php
if (!function_exists('sys_getloadavg')) {
echo "not available on this Windows runtime\n";
} else {
$load = sys_getloadavg();
echo is_array($load) && count($load) === 3 ? "three samples\n" : "unavailable\n";
}
Ожидаемый результат
not available on this Windows runtime
PHP 8.5.11 для Windows не определяет функцию. function_exists проверяет реальную сборку; это честный платформенный результат, а не имитация Unix.
<?php
if (!function_exists('sys_getloadavg')) {
throw new RuntimeException('Нужна Unix-платформа с sys_getloadavg');
}
$load = sys_getloadavg();
if (!is_array($load) || count($load) !== 3) {
throw new RuntimeException('Метрика недоступна');
}
[$one, $five, $fifteen] = $load;
printf("1m=%.2f 5m=%.2f 15m=%.2f\n", $one, $five, $fifteen);
$workers = 4;
echo $one > $workers * 2 ? "defer optional job\n" : "capacity policy allows check\n";
Вывод зависит от Unix-хоста, поэтому это проверенный синтаксически контекстный пример. Load average — длина runnable/uninterruptible очереди по правилам ОС, не процент CPU. Порог 2×workers — лишь явная политика примера.
Для production-наблюдения собирайте также CPU, память, latency, очередь и ошибки. Один load average не диагностирует причину и не должен автоматически выключать обязательную обработку.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| Параметры | Нет. |
| Возврат | Три sample в порядке 1/5/15 минут; false при отказе. |
| Windows | Функция не реализована. Проверяйте function_exists или используйте платформенный мониторинг. |
| Смысл | Не процент загрузки и не число запросов PHP. Интерпретация зависит от ОС и количества CPU/воркеров. |
Ошибки и границы. false и отсутствие функции — разные состояния. Не индексируйте результат до проверки.
Версии и платформа. Изолированная Windows-проверка зафиксировала отсутствие в PHP 8.5.11; Unix-значения намеренно не подделываются.
Рядом: hrtime.
time_sleep_untilЗаблокировать текущий процесс до абсолютной Unix-отметки времени.
PHP 5.1+ · standard
time_sleep_until(float $timestamp): boolЗаблокировать текущий процесс до абсолютной Unix-отметки времени.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Рассчитать wakeAt по проверенным данным
- Убедиться, что срок в будущем и ожидание короткое
- time_sleep_until блокирует процесс
- После true перепроверить деловое условие
Первый запуск и развитие задачи
<?php
$wakeAt = microtime(true) + 0.02;
$ok = time_sleep_until($wakeAt);
var_dump($ok);
var_dump(microtime(true) >= $wakeAt);
Ожидаемый результат
bool(true)
bool(true)
Пауза около 20 мс ограничена учебным запуском. microtime(true) даёт дробную Unix-отметку; повторное значение после возврата не меньше цели.
<?php
$warnings = 0;
set_error_handler(static function (int $level) use (&$warnings): bool {
if ($level === E_WARNING) { $warnings++; return true; }
return false;
});
try {
$ok = time_sleep_until(microtime(true) - 1);
} finally {
restore_error_handler();
}
var_dump($ok);
echo 'warnings=', $warnings, "\n";
Ожидаемый результат
bool(false)
warnings=1
Предупреждение обработано только ради наблюдаемого опыта; рабочий код проверяет, что deadline ещё в будущем, и не подавляет другие ошибки.
Для задания на завтра используйте планировщик/очередь с available_at: sleeping-процесс удерживает воркер и может потеряться при перезапуске. Изменение системных wall-clock часов влияет на абсолютные сроки; для timeout участка выбирайте hrtime.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| timestamp | Unix timestamp с дробной частью; для точного относительного интервала сначала сформулируйте, нужны ли wall-clock или monotonic часы. |
| Возврат | true при достижении срока, false при отказе. |
| Прошлая отметка | E_WARNING и false. |
| Сигналы | Официальная заметка: доставляются после пробуждения. |
Ошибки и границы. Не держите открытые транзакции и пользовательские сессии во время ожидания. Предупреждение прошлой даты нужно предотвращать, а не скрывать @.
Версии и платформа. Функция принимает float; time() округляет до целой секунды и может создавать впечатление «проснулся на секунду раньше», если сравнивать разные единицы.
Рядом: sleep, usleep, time_nanosleep, hrtime.
__halt_compilerОстановить компиляцию текущего файла и оставить после конструкции необрабатываемые байты данных.
PHP 5.1+ · standard
__halt_compiler(): voidОстановить компиляцию текущего файла и оставить после конструкции необрабатываемые байты данных.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- PHP компилирует загрузчик
- __halt_compiler фиксирует offset
- Оставшиеся bytes не компилируются
- Загрузчик читает хвост из __FILE__ по offset
Первый запуск и развитие задачи
<?php
$source = file_get_contents(__FILE__);
$payload = substr($source, __COMPILER_HALT_OFFSET__);
echo trim($payload), "\n";
__halt_compiler();
MANUAL-PAYLOAD
Ожидаемый результат
MANUAL-PAYLOAD
__COMPILER_HALT_OFFSET__ — byte-позиция первого байта после конструкции. Компилятор не разбирает MANUAL-PAYLOAD как PHP; код до конструкции читает этот хвост как данные.
<?php
$handle = fopen(__FILE__, 'rb');
if ($handle === false || fseek($handle, __COMPILER_HALT_OFFSET__) !== 0) {
throw new RuntimeException('payload');
}
$json = ltrim((string) stream_get_contents($handle));
fclose($handle);
$manifest = json_decode($json, true, flags: JSON_THROW_ON_ERROR);
echo $manifest['package'], ':', $manifest['files'], "\n";
__halt_compiler();
{"package":"demo","files":3}
Ожидаемый результат
demo:3
JSON остаётся обычными данными и проходит json_decode. В реальном single-file package дополнительно проверяют подпись/хеш, размер и схему; сам offset не доказывает целостность.
Практическое применение — PHAR/single-file installer. Для обычного приложения отдельный ресурсный файл обычно проще обновлять, подписывать и проверять. Не используйте конструкцию как замену системе контроля версий для «выключенного» кода.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| Параметры/возврат | Нет параметров; void. Компиляция кода после конструкции прекращается. |
| __COMPILER_HALT_OFFSET__ | Константа появляется только в файле с этой конструкцией и содержит byte-offset начала хвоста. |
| Область | Разрешена только на самом внешнем уровне файла; нельзя вызвать из функции/метода. |
| Граница | Это compiler construct, не обычная Reflection-функция. Код после неё не проверяется как PHP. |
Ошибки и границы. Неверное расположение даёт compile error. Любой парсер хвоста обязан ограничивать размер и проверять формат; приложенные bytes не становятся доверенными автоматически.
Версии и платформа. Offset измеряется в bytes текущего файла. Перенос строк/кодировка перед конструкцией изменяют число.
Рядом: php_strip_whitespace.
packСобрать бинарную строку по точной схеме протокола или формата файла.
PHP 4+; endian float/double codes — PHP 7.0.15/7.1.1+ · standard
pack(string $format, mixed ...$values): stringСобрать бинарную строку по точной схеме протокола или формата файла.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Прочитать спецификацию формата
- Выбрать размер и endian для каждого поля
- pack потребляет values по format
- Проверить длину/hex и отправить либо сохранить bytes
Первый запуск и развитие задачи
<?php
$binary = pack('NnC', 0x10203040, 0x5060, 0x70);
echo bin2hex($binary), "\n";
echo strlen($binary), " bytes\n";
Ожидаемый результат
10203040506070
7 bytes
N всегда пишет 32-bit big-endian, n — 16-bit big-endian, C — один byte. Поэтому результат не зависит от native endian этой машины.
<?php
$record = pack('Z8N', 'IMG', 640);
echo bin2hex($record), "\n";
echo strlen($record), "\n";
Ожидаемый результат
494d47000000000000000280
12
Z8 занимает восемь bytes: IMG, NUL-терминатор и дополнение. N добавляет четыре bytes 00000280. Это бинарная запись, а не UTF-8-текстовый CSV.
| Код | Что именно записывает/читает |
|---|---|
| a / A / Z | Строка с NUL-дополнением / SPACE-дополнением / NUL-terminated; A при unpack убирает конечные ASCII whitespace и NUL, a сохраняет NUL, Z убирает NUL-хвост. |
| h / H | Шестнадцатеричные полубайты: младший nibble первым / старший nibble первым. Повтор задаёт число символов из одного аргумента. |
| c / C | Знаковый / беззнаковый byte. |
| s / S | 16-bit signed/unsigned в машинном byte order. |
| n / v | 16-bit unsigned: big-endian / little-endian. |
| i / I | Signed/unsigned integer машинного размера и byte order. |
| l / L | 32-bit signed/unsigned в машинном byte order. |
| N / V | 32-bit unsigned: big-endian / little-endian. |
| q / Q | 64-bit signed/unsigned в машинном byte order; недоступны на 32-bit сборках. |
| J / P | 64-bit unsigned: big-endian / little-endian; недоступны на 32-bit сборках. |
| f / g / G | Float: машинное представление / little-endian / big-endian. |
| d / e / E | Double: машинное представление / little-endian / big-endian. |
| x / X / @ | Вставить NUL / отступить на byte назад / дополнить NUL до абсолютной позиции. |
Для сетевого протокола выбирайте N/n/J или V/v/P по его спецификации. Коды i/I/l/L/S зависят от машины и плохо подходят для обмена между языками без явного договора. Бинарная строка может содержать NUL: не обрабатывайте её текстовыми функциями, ожидающими кодировку.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| format | Последовательность кодов и необязательных repeat. Для a/A/h/H repeat — число символов одного аргумента; для @ — абсолютная позиция; для остальных — число потребляемых значений. * повторяет до конца входных values. |
| values | Значения в порядке схемы. Количество, диапазоны и смысл обязан проверить код протокола. |
| Возврат | Бинарная PHP-string. С PHP 8 pack больше не возвращает false при отказе. |
| Signed/unsigned | При pack различие кодов не меняет bytes; оно влияет на unpack. PHP int остаётся signed и машинного размера. |
Ошибки и границы. Неверная схема, лишние/недостающие values, выход за диапазон и float→int могут дать предупреждение/ValueError либо неподходящие bytes. На 32-bit нет q/Q/J/P; большие unsigned значения могут потерять точность ещё до pack.
Версии и платформа. PHP 7.2 документировал endian float/double; с PHP 8 возврат только string. Никогда не полагайтесь на native order без требования формата.
Рядом: unpack.
uniqidСоздать time-based строковую метку для низкой цены конфликта, но не секрет и не гарантию уникальности.
PHP 4+ · standard
uniqid(string $prefix = "", bool $more_entropy = false): stringСоздать time-based строковую метку для низкой цены конфликта, но не секрет и не гарантию уникальности.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Нужна только временная подпись лога/превью → uniqid допустим
- Нужна уникальность БД → UNIQUE + обработка конфликта/UUID
- Нужна непредсказуемость → random_bytes/Randomizer Secure
- Не смешивать эти свойства
Первый запуск и развитие задачи
<?php
$id = uniqid('job-');
var_dump(str_starts_with($id, 'job-'));
var_dump(strlen($id) === strlen('job-') + 13);
var_dump((bool) preg_match('/^job-[0-9a-f]+$/D', $id));
Ожидаемый результат
bool(true)
bool(true)
bool(true)
Конкретное время-зависимое значение намеренно не фиксируется. Проверка формы не превращает ID в гарантированно уникальный или секретный.
<?php
$label = uniqid('preview-', true);
$token = bin2hex(random_bytes(16));
var_dump(str_starts_with($label, 'preview-'));
var_dump(strlen($label) === strlen('preview-') + 23);
var_dump(strlen($token) === 32 && ctype_xdigit($token));
Ожидаемый результат
bool(true)
bool(true)
bool(true)
more_entropy удлиняет time-based label, но Manual всё равно не гарантирует uniqueness/unguessability. Для reset-ссылки используется random_bytes; в БД также ставят UNIQUE и обрабатывают редкий конфликт.
Идентификатор заказа лучше выдаёт база/доменная схема; парольный reset, CSRF и API-key требуют CSPRNG. Изменение системных часов и параллельные узлы увеличивают риск совпадения. prefix из внешнего ввода не делает безопасное имя файла.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| prefix | Добавляется дословно. Может различать узлы, но не координирует их часы и не санитизирует путь/HTML/SQL. |
| more_entropy=false | Пустой prefix → 13 characters. Основа — текущее время с microsecond precision. |
| more_entropy=true | Пустой prefix → 23 characters; добавляется значение внутреннего генератора, повышая вероятность различия, но не создавая CSPRNG-токен. |
| Возврат | Строка; Manual дважды предупреждает, что uniqueness не гарантирована. |
Ошибки и границы. Не используйте uniqid для аутентификации, доступа, подписи, nonce или имен, где угадывание раскрывает файл. more_entropy не исправляет эту границу.
Версии и платформа. Под Cygwin more_entropy должен быть true. Длина относится к ASCII characters/bytes текущего формата, но не является обещанием будущнего бизнес-ID.
unpackРазобрать бинарную строку по известной схеме в ассоциативный массив.
PHP 4+; offset — PHP 7.1+ · standard
unpack(string $format, string $string, int $offset = 0): array|falseРазобрать бинарную строку по известной схеме в ассоциативный массив.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Проверить magic/version/length
- Выбрать explicit endian schema
- unpack читает от offset
- Проверить false, ключи и предметные диапазоны
Первый запуск и развитие задачи
<?php
$binary = hex2bin('10203040506070');
if ($binary === false) { throw new RuntimeException('hex'); }
$header = unpack('Nrequest/nflags/Cversion', $binary);
if ($header === false) { throw new RuntimeException('header'); }
echo $header['request'], "\n";
echo dechex($header['flags']), "\n";
echo dechex($header['version']), "\n";
Ожидаемый результат
270544960
5060
70
Имена request/flags/version становятся ключами массива. N/n/C читают 4/2/1 bytes с тем же endian-договором, что pack.
<?php
$frame = "AA" . pack('n2', 300, 400);
$size = unpack('nwidth/nheight', $frame, 2);
if ($size === false) { throw new RuntimeException('frame'); }
echo $size['width'], 'x', $size['height'], "\n";
Ожидаемый результат
300x400
Offset 2 отсчитывается в bytes и пропускает ASCII-префикс AA. Имена обязательны для двух разных полей: иначе numeric key может быть перезаписан следующим кодом.
| Код | Что именно записывает/читает |
|---|---|
| a / A / Z | Строка с NUL-дополнением / SPACE-дополнением / NUL-terminated; A при unpack убирает конечные ASCII whitespace и NUL, a сохраняет NUL, Z убирает NUL-хвост. |
| h / H | Шестнадцатеричные полубайты: младший nibble первым / старший nibble первым. Повтор задаёт число символов из одного аргумента. |
| c / C | Знаковый / беззнаковый byte. |
| s / S | 16-bit signed/unsigned в машинном byte order. |
| n / v | 16-bit unsigned: big-endian / little-endian. |
| i / I | Signed/unsigned integer машинного размера и byte order. |
| l / L | 32-bit signed/unsigned в машинном byte order. |
| N / V | 32-bit unsigned: big-endian / little-endian. |
| q / Q | 64-bit signed/unsigned в машинном byte order; недоступны на 32-bit сборках. |
| J / P | 64-bit unsigned: big-endian / little-endian; недоступны на 32-bit сборках. |
| f / g / G | Float: машинное представление / little-endian / big-endian. |
| d / e / E | Double: машинное представление / little-endian / big-endian. |
| x / X / @ | Вставить NUL / отступить на byte назад / дополнить NUL до абсолютной позиции. |
Безымянные поля получают numeric keys с 1, но нумерация начинается заново для каждого format-code: следующий код может перезаписать данные. Поэтому в рабочем протоколе именуйте каждое поле. Unpack не проверяет CRC, magic, допустимый enum или общую длину сообщения — это делает код формата.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| format | Коды pack плюс имена полей; поля разделяются /. При repeat ключи получают числовые суффиксы. a/A/Z по-разному сохраняют/убирают конечные NUL/ASCII whitespace. |
| string | Бинарные bytes. До разбора проверьте минимальную/точную длину и версию протокола. |
| offset | Byte-offset начала разбора, доступен с PHP 7.1. |
| Возврат | Ассоциативный массив или false. Большой unsigned может стать отрицательным из-за signed PHP int. |
Ошибки и границы. Короткий/повреждённый буфер, неверный format и offset требуют явной обработки false/диагностики. Не распаковывайте произвольный огромный input без лимита размера.
Версии и платформа. Endian float/double коды доступны в современном PHP; native-order коды остаются платформенными.
Рядом: pack.
get_browserСопоставить строку User-Agent с записью внешней базы browscap.ini.
PHP 4+ · standard
get_browser(?string $user_agent = null, bool $return_array = false): object|array|falseСопоставить строку User-Agent с записью внешней базы browscap.ini.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Получить строку заголовка или лога
- Загрузить настроенную версию browscap
- Найти лучшее правило
- Вернуть заявленные capabilities или false
Первый запуск и развитие задачи
<?php
$command = [PHP_BINARY, '-n', '-d', 'browscap=' . __DIR__ . '/browscap.ini',
__DIR__ . '/worker.php'];
$process = proc_open($command,
[0 => ['file', 'NUL', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']],
$pipes, __DIR__);
if (!is_resource($process)) { throw new RuntimeException('worker'); }
$out = stream_get_contents($pipes[1]); fclose($pipes[1]);
$err = stream_get_contents($pipes[2]); fclose($pipes[2]);
$code = proc_close($process);
echo $out, 'exit=', $code, "\n", 'stderr=', $err;
Ожидаемый результат
ManualBrowser|1.0|cookies=yes
exit=0
stderr=Тестовый browscap передан только дочернему CLI на старте. База специально содержит один User-Agent и не претендует на актуальный каталог браузеров.
<?php
$command = [PHP_BINARY, '-n', __DIR__ . '/worker.php'];
$process = proc_open($command,
[0 => ['file', 'NUL', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']],
$pipes, __DIR__);
if (!is_resource($process)) { throw new RuntimeException('worker'); }
$out = stream_get_contents($pipes[1]); fclose($pipes[1]);
$err = stream_get_contents($pipes[2]); fclose($pipes[2]);
$code = proc_close($process);
echo $out, 'exit=', $code, "\n", 'stderr=', $err;
Ожидаемый результат
warning
bool(false)
exit=0
stderr=Дочерний PHP запущен с -n, поэтому browscap не настроен. Пользовательский error handler превращает ожидаемое предупреждение в наблюдаемый текст только для опыта.
Не принимайте решение о доступе, цене или безопасности по User-Agent. Поле cookies означает возможность браузера по базе, а не фактическое согласие/включение пользователя; это проверяется реальной cookie. Для интерфейса надёжнее feature detection и progressive enhancement.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| user_agent | Явная строка либо null: тогда используется HTTP User-Agent текущего запроса. Это заявка клиента, а не доказанная модель устройства. |
| return_array=false | Объект свойств; true — массив. Конкретные ключи зависят от browscap-базы. |
| Возврат false | Информация не получена, в частности browscap не настроен. |
| Конфигурация | browscap — INI_SYSTEM-путь к внешнему файлу; база не поставляется с PHP и требует обновлений. |
Ошибки и границы. Устаревшая/неверная база даёт Default Browser или ошибочную классификацию. Нельзя принимать произвольный путь к browscap во время запроса: setting читается на системном уровне.
Версии и платформа. Работа зависит от конкретного INI выбранного SAPI. Composer-пакет не автоматически настраивает встроенную функцию.
highlight_fileПолучить HTML-подсветку PHP-исходника из файла для закрытой документации.
PHP 4+; generated HTML changed in PHP 8.3 · standard
highlight_file(string $filename, bool $return = false): string|boolПолучить HTML-подсветку PHP-исходника из файла для закрытой документации.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Сервер читает весь разрешённый файл
- Lexer разбивает PHP-токены
- Генерируется HTML с inline-цветами
- Закрытая страница выводит/возвращает результат
Первый запуск и развитие задачи
<?php
$html = highlight_file(__DIR__ . '/sample.php', true);
if (!is_string($html)) { throw new RuntimeException('highlight'); }
$plain = html_entity_decode(strip_tags($html), ENT_QUOTES | ENT_HTML5, 'UTF-8');
var_dump(str_contains($plain, '$message'));
var_dump(str_contains($plain, 'DEMO-NOT-A-SECRET'));
Ожидаемый результат
bool(true)
bool(true)
Функция читает и форматирует исходник, но не выполняет echo из sample.php. Текст-заглушка специально показывает главный риск: любые реальные секреты в исходнике тоже будут раскрыты.
<?php
$warnings = 0;
set_error_handler(static function (int $level) use (&$warnings): bool {
if ($level === E_WARNING) { $warnings++; return true; }
return false;
});
try { $result = highlight_file(__DIR__ . '/absent.php', true); }
finally { restore_error_handler(); }
var_dump($result);
echo 'warnings=', $warnings, "\n";
Ожидаемый результат
bool(false)
warnings=2
PHP 8.5.11 выдаёт отдельные предупреждения открытия файла и highlight_file. Код проверяет false, а не связывает бизнес-логику с числом диагностик. Путь фиксирован автором; разрешённые документы перечисляют явно и не показывают пользователю системные пути.
Не превращайте filename из query-параметра в публичный просмотрщик: пользователь сможет запросить конфигурацию, ключи и исходники. Для документации лучше хранить отдельную проверенную копию примера или репозиторный snippet без секретов.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| filename | Путь к читаемому PHP-файлу. Функция раскрывает его исходный текст. |
| return=false | HTML сразу печатается; возврат true/false. |
| return=true | HTML возвращается строкой; при отказе false. Внутри используется output buffering, поэтому нельзя вызывать в ob_start callback. |
| Оформление | Цвета берутся из highlight.string/comment/keyword/default/html. Генерируемая разметка изменилась в PHP 8.3 и может меняться снова. |
Ошибки и границы. Отсутствие/права дают warning и false. open_basedir и реальные права файла применяются, но не заменяют allowlist.
Версии и платформа. Не привязывайте CSS/тест к точной внутренней разметке. return=true несовместим с ob_start callback.
Рядом: highlight_string, show_source, php_strip_whitespace.
highlight_stringСформировать HTML-подсветку доверенной строки PHP-кода без её выполнения.
PHP 4+; HTML changed 8.3; return type refined 8.4 · standard
highlight_string(string $string, bool $return = false): string|trueСформировать HTML-подсветку доверенной строки PHP-кода без её выполнения.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Получить доверенный пример
- Lexer разбирает токены без выполнения
- Генерируется HTML
- Вернуть строку либо вывести
Первый запуск и развитие задачи
<?php
$source = '<?php $total = 2 + 3; echo $total;';
$html = highlight_string($source, true);
$plain = html_entity_decode(strip_tags($html), ENT_QUOTES | ENT_HTML5, 'UTF-8');
var_dump(is_string($html));
var_dump(str_contains($plain, '$total'));
var_dump(str_contains($plain, '2 + 3'));
Ожидаемый результат
bool(true)
bool(true)
bool(true)
Исходная строка включает открывающий PHP-тег, как требует Manual. Подсветка не запускает вычисление 2+3.
<?php
$ran = false;
ob_start();
$ok = highlight_string('<?php $ran = true;', false);
$html = ob_get_clean();
var_dump($ok);
var_dump(is_string($html) && $html !== '');
var_dump($ran);
Ожидаемый результат
bool(true)
bool(true)
bool(false)
Output buffer использован вокруг обычного вызова, а не как callback. Переменная ran остаётся false: PHP-текст только подсвечен.
Функция не делает недоверенный текст безопасным бизнес-кодом: она лишь показывает его. Если результат вставляется в большую HTML-страницу, учитывайте, что это уже сгенерированная HTML-разметка, а исходный пример храните отдельно.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| string | PHP-код, включая открывающий тег |
| return=false | HTML печатается, возвращается true. |
| return=true | HTML возвращается string. |
| Разметка | Зависит от highlight.* и версии; изменилась в 8.3. Возврат уточнён с string|bool до string|true в 8.4. |
Ошибки и границы. Не вызывайте return=true внутри callback ob_start: функция сама использует внутреннюю буферизацию.
Версии и платформа. Тестируйте наличие смысла/токенов, а не точные span/style, если обновляете PHP.
Рядом: highlight_file, show_source.
php_strip_whitespaceУдалить комментарии и лишние пробелы из PHP-файла, сохранив токены кода.
PHP 5+ · standard
php_strip_whitespace(string $filename): stringУдалить комментарии и лишние пробелы из PHP-файла, сохранив токены кода.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Прочитать доверенный файл
- Tokenizer сохраняет нужные разделители токенов
- Убрать комментарии/лишний whitespace
- Проверить непустой результат и поведение
Первый запуск и развитие задачи
<?php
$stripped = php_strip_whitespace(__DIR__ . '/source.php');
var_dump($stripped !== '');
var_dump(!str_contains($stripped, 'teaching comment'));
file_put_contents(__DIR__ . '/stripped.php', $stripped);
$process = proc_open([PHP_BINARY, '-n', __DIR__ . '/stripped.php'],
[0 => ['file', 'NUL', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']],
$pipes, __DIR__);
if (!is_resource($process)) { throw new RuntimeException('worker'); }
$out = stream_get_contents($pipes[1]); fclose($pipes[1]);
$err = stream_get_contents($pipes[2]); fclose($pipes[2]);
$code = proc_close($process);
echo $out, 'exit=', $code, "\n", 'stderr=', $err;
Ожидаемый результат
bool(true)
bool(true)
compact
exit=0
stderr=Исполняется только авторский локальный fixture. Комментарий исчез, поведение осталось. Это демонстрация, не production-minifier и не защита исходника.
<?php
$warnings = 0;
set_error_handler(static function (int $level) use (&$warnings): bool {
if ($level === E_WARNING) { $warnings++; return true; }
return false;
});
try { $code = php_strip_whitespace(__DIR__ . '/absent.php'); }
finally { restore_error_handler(); }
var_dump($code === '');
echo 'warnings=', $warnings, "\n";
Ожидаемый результат
bool(true)
warnings=1
Пустая строка — официальный сигнал failure, поэтому её нельзя принимать за полезный компактный файл.
Не используйте функцию как обфускатор или безопасный публичный просмотр: строки, имена и секреты остаются. Комментарии могут содержать лицензии/документацию; удалять их из распространяемого файла можно только по принятой политике.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| filename | Путь к читаемому PHP-исходнику. |
| Возврат | Компактный исходник; пустая строка при failure. |
| INI | Разбор учитывает short_open_tag текущего окружения. |
| CLI-аналог | php -w file.php. |
Ошибки и границы. Пустой результат означает отказ чтения/разбора. Запись результата проверяется отдельно; не перезаписывайте единственную копию исходника.
Версии и платформа. Результат зависит от short_open_tag и синтаксиса версии PHP.
Рядом: highlight_file, __halt_compiler.
show_sourceИспользовать псевдоним highlight_file; отдельной возможности у show_source нет.
PHP 4+ · standard
show_source(string $filename, bool $return = false): string|boolИспользовать псевдоним highlight_file; отдельной возможности у show_source нет.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- show_source получает path/return
- Выполняется highlight_file
- Получается та же HTML-разметка
- Применяется та же security allowlist
Первый запуск и развитие задачи
<?php
$alias = show_source(__DIR__ . '/sample.php', true);
$target = highlight_file(__DIR__ . '/sample.php', true);
var_dump(is_string($alias));
var_dump($alias === $target);
Ожидаемый результат
bool(true)
bool(true)
Оба имени возвращают одну и ту же разметку. Новый код обычно выбирает более понятное имя highlight_file.
<?php
ob_start();
$ok = show_source(__DIR__ . '/sample.php', false);
$html = ob_get_clean();
var_dump($ok);
var_dump(is_string($html) && $html !== '');
Ожидаемый результат
bool(true)
bool(true)
show_source печатает подсветку и возвращает true. Те же риски раскрытия пути/секретов относятся к нему без изменений.
Не создавайте два разных внутренних стандарта документации для alias и target. В интерфейсе показывайте один канонический термин, а alias сохраняйте для чтения старого кода.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| Alias | Все параметры, возвраты, warnings, INI-цвета, буферизация и риски принадлежат highlight_file. |
| filename | Путь к раскрываемому исходнику. |
| return | false печатает и возвращает bool; true возвращает string либо false. |
Ошибки и границы. Полностью совпадают с highlight_file, включая warning/false и запрет return=true внутри ob_start callback.
Версии и платформа. Официальная страница определяет show_source только как alias highlight_file.
Рядом: highlight_file, highlight_string.
sapi_windows_cp_convПреобразовать bytes одной Windows-codepage в другую.
Windows SAPI, PHP 7.1+ · standard
sapi_windows_cp_conv(int|string $in_codepage, int|string $out_codepage, string $subject): ?stringПреобразовать bytes одной Windows-codepage в другую.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Знать фактическую входную codepage
- Декодировать bytes в Unicode
- Закодировать в out_codepage
- Проверить string, сохранить метаданные кодировки
Первый запуск и развитие задачи
<?php
$legacy = sapi_windows_cp_conv(65001, 1251, 'Привет');
if (!is_string($legacy)) { throw new RuntimeException('to 1251'); }
$restored = sapi_windows_cp_conv(1251, 65001, $legacy);
var_dump(bin2hex($legacy) === 'cff0e8e2e5f2');
var_dump($restored === 'Привет');
Ожидаемый результат
bool(true)
bool(true)
Кодовые страницы заданы явно: 65001 — UTF-8, 1251 — Cyrillic Windows. Это преобразование текста, а не исправление неизвестной кодировки угадыванием.
<?php
$warnings = 0;
set_error_handler(static function (int $level) use (&$warnings): bool {
if ($level === E_WARNING) { $warnings++; return true; }
return false;
});
try { $converted = sapi_windows_cp_conv(65001, 1251, "\xFF"); }
finally { restore_error_handler(); }
var_dump($converted);
echo 'warnings=', $warnings, "\n";
Ожидаемый результат
NULL
warnings=1
0xFF не является самостоятельным UTF-8-символом. null нельзя превращать в пустой текст: это ошибка входных bytes.
Для переносимого приложения часто удобнее iconv/mbstring с явными именами кодировок. Не применяйте преобразование повторно к уже UTF-8 данным и не «лечите» mojibake случайным перебором codepage.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| in_codepage | Числовой ID или имя фактической кодировки входных bytes. |
| out_codepage | ID/имя требуемой выходной кодировки. |
| subject | Бинарная PHP-string, которую нужно интерпретировать именно как in_codepage. |
| Возврат | Преобразованная строка либо null. Неверная codepage/последовательность выдаёт E_WARNING. |
Ошибки и границы. E_WARNING + null нужно обрабатывать вместе. Успешное преобразование не проверяет предметно допустимые символы.
Версии и платформа. Изолированно выполнено на Windows PHP 8.5.11; функции нет на Unix.
sapi_windows_cp_getПрочитать текущую process, системную ANSI или OEM codepage Windows.
Windows SAPI, PHP 7.1+ · standard
sapi_windows_cp_get(string $kind = ""): intПрочитать текущую process, системную ANSI или OEM codepage Windows.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Выбрать process/ansi/oem
- Вызвать функцию
- Получить ID
- Передать ID преобразованию либо диагностике
Первый запуск и развитие задачи
<?php
$process = sapi_windows_cp_get();
$ansi = sapi_windows_cp_get('ansi');
$oem = sapi_windows_cp_get('oem');
$fallback = sapi_windows_cp_get('anything-else');
var_dump($process > 0 && $ansi > 0 && $oem > 0);
var_dump($fallback === $process);
var_dump(sapi_windows_cp_is_utf8() === ($process === 65001));
Ожидаемый результат
bool(true)
bool(true)
bool(true)
Конкретные ANSI/OEM числа зависят от Windows-настроек, поэтому проверяется договор. Любой kind кроме ansi/oem относится к текущей process codepage.
<?php
$before = sapi_windows_cp_get();
try {
var_dump(sapi_windows_cp_set(65001));
var_dump(sapi_windows_cp_get() === 65001);
var_dump(sapi_windows_cp_is_utf8());
} finally {
sapi_windows_cp_set($before);
}
var_dump(sapi_windows_cp_get() === $before);
Ожидаемый результат
bool(true)
bool(true)
bool(true)
bool(true)
Изменение действует только в отдельном учебном PHP-процессе. finally возвращает прежнее значение даже при исключении.
ANSI, OEM и process могут различаться. Значение не описывает кодировку произвольного файла/HTTP-тела: её задаёт источник данных.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| kind="ansi" | Системная ANSI codepage. |
| kind="oem" | Системная OEM codepage. |
| Другой/пустой kind | Текущая codepage PHP-процесса. |
| Возврат | Числовой identifier codepage. |
Ошибки и границы. Не подставляйте полученное process-значение вместо документированной кодировки протокола.
Версии и платформа. Изолированно выполнено на Windows; конкретные числа зависят от хоста.
Рядом: sapi_windows_cp_set, sapi_windows_cp_conv, sapi_windows_cp_is_utf8.
sapi_windows_cp_is_utf8Проверить, совместима ли текущая process codepage с UTF-8.
Windows SAPI, PHP 7.1+ · standard
sapi_windows_cp_is_utf8(): boolПроверить, совместима ли текущая process codepage с UTF-8.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Прочитать текущую codepage
- Спросить UTF-8 compatibility
- Выбрать вывод/конверсию
- Не делать вывод о неизвестном входном файле
Первый запуск и развитие задачи
<?php
$process = sapi_windows_cp_get();
$ansi = sapi_windows_cp_get('ansi');
$oem = sapi_windows_cp_get('oem');
$fallback = sapi_windows_cp_get('anything-else');
var_dump($process > 0 && $ansi > 0 && $oem > 0);
var_dump($fallback === $process);
var_dump(sapi_windows_cp_is_utf8() === ($process === 65001));
Ожидаемый результат
bool(true)
bool(true)
bool(true)
Конкретные ANSI/OEM числа зависят от Windows-настроек, поэтому проверяется договор. Любой kind кроме ansi/oem относится к текущей process codepage.
<?php
$before = sapi_windows_cp_get();
try {
var_dump(sapi_windows_cp_set(1251));
var_dump(sapi_windows_cp_get() === 1251);
var_dump(sapi_windows_cp_is_utf8());
} finally {
sapi_windows_cp_set($before);
}
var_dump(sapi_windows_cp_get() === $before);
Ожидаемый результат
bool(true)
bool(true)
bool(false)
bool(true)
1251 — корректная текстовая codepage, но она не UTF-8-compatible по договору функции. Код не меняет системную локаль Windows.
Проверка полезна для CLI-консоли, но HTTP/БД/файл имеют собственный договор кодировки. Один global-флаг процесса не заменяет проверку каждого boundary.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| Параметры | Нет. |
| Возврат | true для UTF-8-compatible process codepage, иначе false. |
| Область | Текущий PHP-процесс Windows; не содержимое конкретного файла. |
Ошибки и границы. false не означает повреждённый текст; это характеристика current process codepage.
Версии и платформа. Изолированно выполнено на Windows; отсутствует на Unix.
Рядом: sapi_windows_cp_get, sapi_windows_cp_set, sapi_windows_cp_conv.
sapi_windows_cp_setИзменить codepage текущего PHP-процесса Windows.
Windows SAPI, PHP 7.1+ · standard
sapi_windows_cp_set(int $codepage): boolИзменить codepage текущего PHP-процесса Windows.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Сохранить current codepage
- Установить нужный ID и проверить bool
- Выполнить ограниченный участок
- В finally вернуть прежний ID
Первый запуск и развитие задачи
<?php
$before = sapi_windows_cp_get();
try {
var_dump(sapi_windows_cp_set(65001));
var_dump(sapi_windows_cp_get() === 65001);
var_dump(sapi_windows_cp_is_utf8());
} finally {
sapi_windows_cp_set($before);
}
var_dump(sapi_windows_cp_get() === $before);
Ожидаемый результат
bool(true)
bool(true)
bool(true)
bool(true)
Изменение действует только в отдельном учебном PHP-процессе. finally возвращает прежнее значение даже при исключении.
<?php
$before = sapi_windows_cp_get();
try {
var_dump(sapi_windows_cp_set(1251));
var_dump(sapi_windows_cp_get() === 1251);
var_dump(sapi_windows_cp_is_utf8());
} finally {
sapi_windows_cp_set($before);
}
var_dump(sapi_windows_cp_get() === $before);
Ожидаемый результат
bool(true)
bool(true)
bool(false)
bool(true)
1251 — корректная текстовая codepage, но она не UTF-8-compatible по договору функции. Код не меняет системную локаль Windows.
Глобальное состояние усложняет библиотечный код: меняйте его на узкой границе CLI и всегда восстанавливайте. Для конкретной строки предпочтительнее явный cp_conv/iconv, не зависящий от текущего процесса.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| codepage | Числовой identifier, например 65001 UTF-8 или 1251 Cyrillic Windows. |
| Возврат | true при успехе, false при отказе. |
| Область | Текущий процесс; это не изменение системной локали, файла или уже созданной строки. |
Ошибки и границы. Проверяйте false и восстанавливайте прежнее состояние. Параллельные/чужие компоненты могут ожидать другую codepage.
Версии и платформа. Изолированно выполнено в отдельном Windows PHP 8.5.11 процессе.
Рядом: sapi_windows_cp_get, sapi_windows_cp_is_utf8, sapi_windows_cp_conv.
sapi_windows_generate_ctrl_eventОтправить CTRL+C/CTRL+BREAK процессу той же Windows console process group.
Windows SAPI, PHP 7.4+ · standard
sapi_windows_generate_ctrl_event(int $event, int $pid = 0): boolОтправить CTRL+C/CTRL+BREAK процессу той же Windows console process group.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Создать отдельную process group
- Child регистрирует handler и сообщает ready
- Parent отправляет CTRL_BREAK target group
- Child подтверждает событие и завершает cleanup
Первый запуск и развитие задачи
<?php
@unlink(__DIR__ . '/ready.txt');
@unlink(__DIR__ . '/observed.txt');
$process = proc_open([PHP_BINARY, '-n', __DIR__ . '/worker.php'],
[0 => ['file', 'NUL', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']],
$pipes, __DIR__, null, ['create_process_group' => true]);
if (!is_resource($process)) { throw new RuntimeException('worker'); }
$deadline = microtime(true) + 2;
while (!is_file(__DIR__ . '/ready.txt') && microtime(true) < $deadline) { usleep(10000); }
$state = proc_get_status($process);
$sent = is_file(__DIR__ . '/ready.txt')
&& sapi_windows_generate_ctrl_event(PHP_WINDOWS_EVENT_CTRL_BREAK, $state['pid']);
$deadline = microtime(true) + 2;
while (!is_file(__DIR__ . '/observed.txt') && microtime(true) < $deadline) { usleep(10000); }
$observed = is_file(__DIR__ . '/observed.txt') ? trim(file_get_contents(__DIR__ . '/observed.txt')) : '';
$stdout = stream_get_contents($pipes[1]); fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]); fclose($pipes[2]);
$code = proc_close($process);
echo $sent ? "sent\n" : "not sent\n";
echo $observed === (string) PHP_WINDOWS_EVENT_CTRL_BREAK ? "break observed\n" : "not observed\n";
echo 'exit=', $code, " stdout=", $stdout, ' stderr=', $stderr;
Ожидаемый результат
sent
break observed
exit=0 stdout= stderr=Child создан с новой process group и сам зарегистрировал handler. Событие направлено только его PID/group; текущий процесс не получает сигнал.
<?php
$sent = sapi_windows_generate_ctrl_event(
PHP_WINDOWS_EVENT_CTRL_BREAK, 2147483647
);
var_dump($sent);
Ожидаемый результат
bool(false)
Большой PID выбран как отсутствующая учебная process group. false обрабатывается как недоставленное управление, а не как подтверждение остановки.
Не используйте pid=0 без полного понимания группы: можно затронуть родителя/соседей. Для production supervisor после сигнала ждёт подтверждение, применяет deadline и только затем escalation.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| event | PHP_WINDOWS_EVENT_CTRL_C или PHP_WINDOWS_EVENT_CTRL_BREAK. |
| pid | ID target process group; 0 означает все процессы текущей group. |
| Возврат | true, если API принял отправку, false при отказе; это ещё не подтверждение реакции/завершения child. |
| Предпосылка | Процесс должен быть в совместимой console group; обычный произвольный PID не гарантирует доставку. |
Ошибки и границы. true говорит об отправке события API, а не о том, что handler успешно сохранил данные. PID может переиспользоваться; связывайте его с созданным вами процессом.
Версии и платформа. Фактический test executed only against isolated child process group on Windows PHP 8.5.11.
Рядом: sapi_windows_set_ctrl_handler.
sapi_windows_set_ctrl_handlerУстановить или удалить обработчик CTRL+C/CTRL+BREAK в Windows CLI.
Windows SAPI, PHP 7.4+ · standard
sapi_windows_set_ctrl_handler(?callable $handler, bool $add = true): boolУстановить или удалить обработчик CTRL+C/CTRL+BREAK в Windows CLI.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Главный поток регистрирует handler
- Windows доставляет event
- Handler только отмечает отмену/начинает ограниченный cleanup
- Главный цикл завершает работу и удаляет handler
Первый запуск и развитие задачи
<?php
$handler = static function (int $event): void {
echo 'event=', $event, "\n";
};
var_dump(sapi_windows_set_ctrl_handler($handler, true));
var_dump(sapi_windows_set_ctrl_handler($handler, false));
Ожидаемый результат
bool(true)
bool(true)
Событие не отправляется; опыт проверяет регистрацию и симметричное удаление того же callable в главном потоке.
<?php
@unlink(__DIR__ . '/ready.txt');
@unlink(__DIR__ . '/observed.txt');
$process = proc_open([PHP_BINARY, '-n', __DIR__ . '/worker.php'],
[0 => ['file', 'NUL', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']],
$pipes, __DIR__, null, ['create_process_group' => true]);
if (!is_resource($process)) { throw new RuntimeException('worker'); }
$deadline = microtime(true) + 2;
while (!is_file(__DIR__ . '/ready.txt') && microtime(true) < $deadline) { usleep(10000); }
$state = proc_get_status($process);
$sent = is_file(__DIR__ . '/ready.txt')
&& sapi_windows_generate_ctrl_event(PHP_WINDOWS_EVENT_CTRL_BREAK, $state['pid']);
$deadline = microtime(true) + 2;
while (!is_file(__DIR__ . '/observed.txt') && microtime(true) < $deadline) { usleep(10000); }
$observed = is_file(__DIR__ . '/observed.txt') ? trim(file_get_contents(__DIR__ . '/observed.txt')) : '';
$stdout = stream_get_contents($pipes[1]); fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]); fclose($pipes[2]);
$code = proc_close($process);
echo $sent ? "sent\n" : "not sent\n";
echo $observed === (string) PHP_WINDOWS_EVENT_CTRL_BREAK ? "break observed\n" : "not observed\n";
echo 'exit=', $code, " stdout=", $stdout, ' stderr=', $stderr;
Ожидаемый результат
sent
break observed
exit=0 stdout= stderr=Child создан с новой process group и сам зарегистрировал handler. Событие направлено только его PID/group; текущий процесс не получает сигнал.
<?php
var_dump(sapi_windows_set_ctrl_handler(null, true));
var_dump(sapi_windows_set_ctrl_handler(null, false));
Ожидаемый результат
bool(true)
bool(true)
null заставляет процесс игнорировать CTRL+C, но не CTRL+BREAK. Учебный процесс сразу удаляет настройку; это не рекомендация игнорировать штатную остановку воркера.
Handler должен быть коротким и повторно безопасным. Не начинайте в нём новую долгую интеграцию; зафиксируйте флаг отмены и позвольте основному циклу закрыть ресурсы.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| handler | callable(int $event): void. null игнорирует CTRL+C, но не CTRL+BREAK. |
| add=true/false | Добавить либо удалить обработчик. Для удаления сохраняйте тот же callable. |
| Возврат | true при изменении, false при отказе. |
| Thread | В многопоточном окружении возможно только из main thread. |
Ошибки и границы. Удаление другого callable не гарантирует снятие нужного handler. null не игнорирует CTRL+BREAK. Сигнальное событие не заменяет deadline процесса.
Версии и платформа. Тест add/remove и isolated CTRL_BREAK выполнены на Windows PHP 8.5.11.
Рядом: sapi_windows_generate_ctrl_event.
sapi_windows_vt100_supportПроверить или переключить VT100 control sequences у Windows console stream.
Windows SAPI, PHP 7.2+; nullable enable — PHP 8+ · standard
sapi_windows_vt100_support(resource $stream, ?bool $enable = null): boolПроверить или переключить VT100 control sequences у Windows console stream.
Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.
Что произойдёт при вызове
- Определить реальный output stream
- Спросить VT100 support
- При true добавить escape-sequence
- При false вывести обычный текст
Первый запуск и развитие задачи
<?php
$stream = fopen(__DIR__ . '/output.txt', 'wb');
if ($stream === false) { throw new RuntimeException('file'); }
var_dump(sapi_windows_vt100_support($stream));
var_dump(sapi_windows_vt100_support($stream, true));
fclose($stream);
Ожидаемый результат
bool(false)
bool(false)
Перенаправленный файл не получает ENABLE_VIRTUAL_TERMINAL_PROCESSING. Поэтому цветовые escape-последовательности в лог лучше не записывать.
<?php
$stream = fopen('php://temp', 'w+');
fclose($stream);
try {
sapi_windows_vt100_support($stream);
} catch (TypeError $error) {
echo "closed stream rejected\n";
}
Ожидаемый результат
closed stream rejected
Переменная больше не содержит открытый stream resource. Это ошибка типа, а не ответ «VT100 выключен».
<?php
$green = "\033[32m";
$reset = "\033[0m";
$interactive = defined('STDOUT')
&& sapi_windows_vt100_support(STDOUT);
echo $interactive ? $green . 'OK' . $reset . PHP_EOL : "OK\n";
Результат зависит от настоящей консоли/редиректа, поэтому пример проверяется синтаксически. Даже при false сообщение остаётся читаемым без цвета.
При старте PHP уже пытается включить VT100 для STDOUT/STDERR. Приложение не должно считать ANSI-цвет частью бизнес-данных; журнал/JSON всегда остаётся plain.
Полный договор вызова
| Часть вызова | Полный договор |
|---|---|
| stream | Открытый stream, связанный с Windows console output buffer. Redirected file/pipe обычно не поддерживает режим. |
| enable=null | Только спрашивает текущее состояние. Nullable с PHP 8. |
| enable=true/false | Пытается включить/выключить ENABLE_VIRTUAL_TERMINAL_PROCESSING. |
| Возврат | При query — текущее состояние; при set — success/failure. Windows 10 API может отсутствовать на старой ОС. |
Ошибки и границы. Закрытый/non-resource stream даёт TypeError. false у файла — нормальное отсутствие console feature, не авария.
Версии и платформа. Функция использует Windows 10 console API и отсутствует на Unix.
Источники и обсуждения
- Miscellaneous Functions
- Installing/Configuring
- Runtime Configuration
- Predefined Constants
- Misc. Functions
- Changelog
- connection_aborted
- connection_status
- constant
- define
- defined
- die
- eval
- exit
- get_browser
- __halt_compiler
- highlight_file
- highlight_string
- hrtime
- ignore_user_abort
- pack
- php_strip_whitespace
- sapi_windows_cp_conv
- sapi_windows_cp_get
- sapi_windows_cp_is_utf8
- sapi_windows_cp_set
- sapi_windows_generate_ctrl_event
- sapi_windows_set_ctrl_handler
- sapi_windows_vt100_support
- show_source
- sleep
- sys_getloadavg
- time_nanosleep
- time_sleep_until
- uniqid
- unpack
- usleep
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


