W3docs

ignore_user_abort()

Функция PHP ignore_user_abort(): описание, синтаксис, параметры, возвращаемое значение и практические примеры использования.

Функция PHP ignore_user_abort() управляет тем, продолжает ли скрипт выполняться после отключения клиента (браузера пользователя). На этой странице описано, что делает функция, её сигнатура и возвращаемое значение, как она взаимодействует с connection_aborted(), типичные ошибки и полный пример фонового задания.

Что делает ignore_user_abort()

Когда пользователь закрывает вкладку браузера, нажимает «Стоп» или переходит на другую страницу, соединение с сервером разрывается. По умолчанию PHP не останавливает скрипт немедленно — он замечает разорванное соединение лишь в следующий раз, когда пытается отправить вывод в браузер, и только тогда завершает скрипт. Функция ignore_user_abort() меняет это поведение: при её включении PHP продолжает выполнять скрипт до конца, даже если никто больше не прослушивает.

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

«Прерывание клиента» — это событие на транспортном уровне: PHP обнаруживает его только при попытке записи в уже закрытое соединение. Именно поэтому момент обнаружения кажется косвенным — см. раздел Почему прерывание обнаруживается поздно ниже.

Синтаксис

ignore_user_abort(?bool $enable = null): int
  • $enable — передайте true, чтобы игнорировать отключения клиента, или false, чтобы вернуть поведение по умолчанию (прерывание при отключении). Если аргумент не указан, текущее значение остаётся без изменений и просто возвращается.
  • Возвращаемое значениепредыдущее значение настройки в виде целого числа (1 = прерывания игнорировались, 0 = не игнорировались). Это позволяет сохранить и восстановить состояние.
<?php
$previous = ignore_user_abort(true);   // turn it on, remember old value
// ... critical work ...
ignore_user_abort($previous);          // restore whatever it was before

Ту же настройку можно задать глобально в php.ini с помощью директивы ignore_user_abort; вызов функции переопределяет её для текущего запроса.

Базовое использование

Вызовите функцию один раз в начале кода, который нужно защитить:

<?php
// Keep running even if the user disconnects.
ignore_user_abort(true);

// Critical code that must not be interrupted.
saveOrderToDatabase();
chargePayment();
sendConfirmationEmail();

// Optional: go back to the default behaviour.
ignore_user_abort(false);

Обратите внимание: ignore_user_abort() сохраняет скрипт активным, но не снимает ограничение max_execution_time. Долго выполняющаяся задача всё равно может быть прервана по таймауту, поэтому при необходимости используйте её совместно с set_time_limit().

Обнаружение прерывания с помощью connection_aborted()

Игнорировать прерывание не значит не реагировать на него. Функция connection_aborted() возвращает 1, как только клиент отключился, и 0 в остальных случаях — её можно проверять внутри цикла и решать, продолжать ли выполнение, очистить ли ресурсы и выйти.

Одна тонкость: PHP обновляет статус соединения только при попытке отправить вывод и сброске буфера. Чтобы обнаружить прерывание в середине цикла, обычно выводят что-нибудь с помощью echo и вызывают flush() — это вынуждает PHP заметить закрытый сокет.

<?php
ignore_user_abort(true);

for ($i = 0; $i < 10; $i++) {
    // Push some output so PHP checks the connection state.
    echo "Step $i\n";
    flush();

    // connection_aborted() returns 1 after the client disconnects.
    if (connection_aborted()) {
        // The user left — stop early and clean up if we want to.
        break;
    }

    doExpensiveStep($i);
}

ignore_user_abort(false);

Здесь connection_aborted() позволяет скрипту самостоятельно принять решение: завершиться тихо, записать в лог факт отключения пользователя или прервать выполнение досрочно. Связанная функция: connection_status() возвращает все три состояния (нормальное, прерванное, таймаут) в виде битовой маски.

Практический пример фонового задания

Распространённый паттерн — отправить ответ, закрыть соединение, чтобы браузер перестал ждать, и продолжить тяжёлую работу в фоне. ignore_user_abort(true) — это то, что делает возможной «продолжающуюся» часть.

<?php
// 1. Keep running after the browser is released.
ignore_user_abort(true);
set_time_limit(0); // no execution-time cap for the background work

// 2. Send the response and flush the output buffers.
ob_start();
echo "Thanks! Your request is being processed.";
$size = ob_get_length();
header("Content-Length: $size");
header("Connection: close");
ob_end_flush();
flush();

if (function_exists('fastcgi_finish_request')) {
    fastcgi_finish_request(); // PHP-FPM: detach from the client now
}

// 3. The user's browser is already done. This runs regardless.
processLargeReport();

Браузер получает быстрый ответ и перестаёт ждать, пока сервер завершает медленную задачу. Без ignore_user_abort(true) фоновая работа была бы прервана, как только PHP обнаружил закрытое соединение.

Почему прерывание обнаруживается поздно

PHP буферизирует вывод. Пока буфер не сброшен клиенту, PHP не обращается к сокету и поэтому не узнаёт, что он закрыт. Вот почему скрипты, которые ничего не выводят (или чей вывод остаётся в буфере), могут выполняться до конца после отключения, так и не получив connection_aborted() === 1. Если требуется своевременное обнаружение прерывания, периодически выводите небольшой «heartbeat» и вызывайте flush(), как в цикле выше. Вспомогательные функции буферизации вывода ob_flush() и ob_end_flush() дают более тонкий контроль над тем, когда данные покидают буфер.

Типичные ошибки

  • Не переопределяет ограничение по времени. Для длительных заданий используйте set_time_limit(0) (или достаточно большое значение) вместе с ней.
  • Для обнаружения нужны вывод и flush. connection_aborted() не переключится в 1 само по себе, если скрипт ничего не пишет клиенту.
  • Неуправляемый скрипт сложнее остановить. При игнорировании прерываний ошибочный бесконечный цикл продолжает потреблять ресурсы, поскольку пользователь больше не может его отменить. Всегда устанавливайте разумные ограничения.
  • На CLI-скрипты не влияет. В командной строке нет клиентского соединения, поэтому функция является пустой операцией — используйте её только в веб-контексте (при обработке запросов).

Заключение

ignore_user_abort() позволяет PHP-скрипту продолжать выполнение после отключения клиента, что необходимо для безопасного завершения критических или фоновых операций. Используйте её совместно с connection_aborted() для обнаружения отключений, flush() для принудительного обнаружения и set_time_limit() для защиты от прерывания в середине задачи — и вы получите надёжный паттерн для работы, которую нельзя оставлять незавершённой.

Практика

Практика
Что делает функция ignore_user_abort() в PHP?
Что делает функция ignore_user_abort() в PHP?
Was this page helpful?