Остановка выполнения в PHP: от die до обработки соединений

Раздел: Программирование -> Остановка скрипта

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

Основное эффективное решение: die()

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

<?php
if (!$db_connection) {
    die('Ошибка подключения к базе данных');
}
// дальнейший код
?>

Php прервать скрипт (прерывание php скрипта)

Пояснение: если условие истинно, скрипт остановится, на экран выведется сообщение. Функция die() является псевдонимом exit() и работает идентично.

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

Решение: использовать exit() без аргументов или с кодом возврата, а также комбинировать с register_shutdown_function().

Цель: быстрая остановка при критических ошибках в простых скриптах.

Как прервать скрипт с кодом возврата?

Функция exit() может принимать целочисленный код (от 0 до 254), который будет передан вызывающему процессу. Ноль обычно означает успешное завершение, ненулевые значения - ошибки.

<?php
if (empty($data)) {
    exit(1);
}
?>

Проблема: код 255 зарезервирован PHP, его использовать нельзя. Также код не может быть строкой - только число.

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

Цель: взаимодействие с консолью, cron, Docker, CI/CD.

Как прервать выполнение только внутри функции?

Оператор return завершает выполнение текущей функции и возвращает значение. Весь скрипт при этом продолжает работу.

<?php
function checkAccess($user) {
    if (!$user['active']) {
        return false; // выход из функции
    }
    // дальнейшие операции
    return true;
}

$result = checkAccess($currentUser);
if ($result === false) {
    echo 'Доступ запрещён';
}
?>

Проблема: если return используется в глобальном коде (не внутри функции), он завершает только текущий файл, а не весь скрипт (например, при подключении include).

Решение: для полной остановки используйте die() или exit().

Цель: досрочный выход из функции при определённых условиях.

Как прервать скрипт при исключении?

Выбрасывание исключения с помощью throw передаёт управление ближайшему блоку catch. Если исключение не перехвачено, возникает фатальная ошибка и скрипт прерывается.

<?php
try {
    $value = 1 / 0; // деление на ноль
} catch (DivisionByZeroError $e) {
    throw new \RuntimeException('Попытка деления на ноль', 0, $e);
}
// код после try-catch не выполнится, если исключение не обработано
?>

Проблема: необработанное исключение приводит к некрасивому выводу ошибки и может раскрыть чувствительные данные.

Решение: всегда перехватывать исключения на верхнем уровне или установить глобальный обработчик через set_exception_handler().

Цель: централизованная обработка ошибок и прерывание при невозможности восстановления.

Как установить лимит времени выполнения?

Функция set_time_limit() устанавливает максимальное время выполнения скрипта в секундах. По истечении времени скрипт прерывается с фатальной ошибкой. Ноль - без ограничения.

<?php
set_time_limit(30); // 30 секунд
while (true) {
    // долгая операция
}
?>

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

Решение: комбинировать с shutdown-функцией для освобождения ресурсов.

Цель: предотвращение бесконечных циклов и деградации сервера.

Как продолжить выполнение после отключения клиента?

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

<?php
ignore_user_abort(true);
// длительная обработка
file_put_contents('log.txt', 'Выполнение завершено');
?>

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

Решение: использовать очереди задач (RabbitMQ, Gearman) для фоновых операций.

Цель: фоновое выполнение задач (отправка писем, генерация отчётов).

Как выполнить код перед завершением?

Функция register_shutdown_function() регистрирует callback, который будет вызван после полного завершения скрипта (включая die/exit). Это подходит для очистки ресурсов, записи логов.

<?php
register_shutdown_function(function () {
    echo 'Завершение работы';
});
exit();
?>

Проблема: shutdown-функция не выполняется при фатальных ошибках (например, нехватка памяти) и вызове некоторых встроенных функций.

Решение: дополнительно использовать деструкторы классов или try-catch.

Цель: гарантированная очистка перед остановкой.

Расширенные примеры и нестандартные сценарии

1. Комбинация shutdown-функции и die для логирования

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

Пример
<?php
register_shutdown_function(function () {
    file_put_contents('shutdown.log', date('Y-m-d H:i:s') . " - Выполнение завершено\n", FILE_APPEND);
});

echo 'Скрипт запущен';
// симуляция критической ошибки
if (rand(0, 1)) {
    die('Принудительная остановка');
}
echo 'Это не будет выполнено';
?>
Вывод: "Скрипт запущен" (возможно) и сообщение от die. В файл shutdown.log будет добавлена строка с временем.

3. Прерывание с очисткой через деструктор класса

Деструктор вызывается при освобождении объекта, в том числе при завершении скрипта. Это позволяет освободить ресурсы (например, закрыть файлы).

Пример
<?php
class ResourceHandler {
    public function __destruct() {
        echo 'Ресурс освобождён' . PHP_EOL;
    }
}

$handler = new ResourceHandler();
exit('Завершение');
// деструктор будет вызван
?>
Вывод: "Ресурс освобождён" затем "Завершение" (порядок может зависеть от буферизации).

4. Возврат JSON-ответа с помощью exit

При разработке API часто нужно прервать скрипт после отправки структурированного ответа.

Пример
<?php
header('Content-Type: application/json');
$response = ['status' => 'error', 'message' => 'Некорректные данные'];
exit(json_encode($response));
?>
Вывод (в браузере): {"status":"error","message":"Некорректные данные"}

5. Принудительный тайм-аут с помощью set_time_limit и обработка через shutdown

Установим короткий лимит, затем запустим бесконечный цикл. PHP прервёт выполнение, а shutdown-функция выполнит лог.

Пример
<?php
set_time_limit(2);
register_shutdown_function(function () {
    $error = error_get_last();
    if ($error !== null) {
        file_put_contents('timeout.log', 'Ошибка: ' . $error['message'] . PHP_EOL, FILE_APPEND);
    }
});

while (true) {
    // вечный цикл
}
?>
Через 2 секунды скрипт выдаст фатальную ошибку "Maximum execution time exceeded". В файл timeout.log запишется соответствующее сообщение.

6. Прерывание при разрыве соединения с проверкой connection_status

Можно периодически проверять статус соединения и останавливать скрипт, если клиент отключился.

Пример
<?php
ignore_user_abort(true);
for ($i = 0; $i < 100; $i++) {
    // имитация работы
    usleep(100000);
    if (connection_status() !== CONNECTION_NORMAL) {
        file_put_contents('abort.log', 'Соединение потеряно на итерации ' . $i . PHP_EOL, FILE_APPEND);
        exit;
    }
}
?>
Если клиент закрыл соединение, скрипт запишет лог и завершится.

7. Использование exit с ob_flush для немедленной отправки данных

Иногда требуется отправить частичный вывод клиенту до прерывания скрипта.

Пример
<?php
ob_start();
echo 'Начало обработки...';
ob_flush();
flush();
sleep(2);
echo 'Готово';
exit;
?>
Сначала отобразится "Начало обработки...", через 2 секунды - "Готово" (если буферизация не отключена).

Прерывание PHP скрипта - comments

En
Php прервать скрипт (php)