W3docs

set_error_handler()

Функция set_error_handler() в PHP позволяет регистрировать пользовательский обработчик ошибок вместо стандартного поведения.

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

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

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

set_error_handler() регистрирует обратный вызов, который PHP вызывает вместо встроенного обработчика ошибок при возникновении соответствующей (нефатальной) ошибки. Ваш обратный вызов решает, что происходит дальше — записать в лог, отобразить дружелюбное сообщение, выбросить исключение или просто проигнорировать.

Функция не останавливает возникновение ошибок — она лишь меняет способ их обработки. PHP по-прежнему учитывает error_reporting при решении о том, вызывать ли ваш обработчик вообще.

Синтаксис

set_error_handler(
    callable|null $callback,
    int $error_levels = E_ALL
): callable|false
ПараметрОписание
$callbackФункция, которую PHP вызывает при возникновении ошибки. Передайте null, чтобы восстановить встроенный обработчик PHP.
$error_levelsБитовая маска уровней ошибок, которые должен получать ваш обработчик (например, E_WARNING | E_NOTICE). По умолчанию E_ALL.

Возвращаемое значение: ранее зарегистрированный обработчик (callable) или null, если такого не было. Возвращает false только в случае недопустимого обратного вызова.

Сигнатура обратного вызова

PHP вызывает ваш обработчик с пятью аргументами. Чаще всего используются первые четыре:

function handler(
    int $errno,        // the error level constant, e.g. E_WARNING
    string $errstr,    // the error message
    string $errfile = "",   // file where the error occurred
    int $errline = 0        // line number
): bool {
    // ...
}

Если ваш обработчик возвращает false, PHP продолжает стандартную внутреннюю обработку ошибки. Возврат true (или отсутствие возврата) сигнализирует PHP, что ошибка полностью обработана, и подавляет поведение по умолчанию.

Какие ошибки можно перехватить

set_error_handler() перехватывает пользовательски перехватываемые уровни ошибок — предупреждения, уведомления, устаревший код и семейство E_USER_*, которые поднимаются с помощью trigger_error():

ПерехватываемыеНе перехватываемые (фатальные)
E_WARNING, E_NOTICE, E_DEPRECATEDE_ERROR
E_USER_ERROR, E_USER_WARNING, E_USER_NOTICEE_PARSE
E_RECOVERABLE_ERROR, E_STRICTE_CORE_ERROR, E_COMPILE_ERROR

Примечание: Фатальные ошибки, такие как E_ERROR и E_PARSE, обходят ваш обработчик и завершают скрипт. Чтобы перехватывать и их, используйте обработчик в сочетании с set_exception_handler() и функцией завершения. Неперехваченные исключения также не направляются сюда — для них есть отдельный обработчик.

Простой обработчик

Определите функцию с ожидаемой сигнатурой и зарегистрируйте её. Здесь вызов trigger_error() имитирует предупреждение, чтобы вы могли увидеть работу обработчика:

<?php

function customErrorHandler($errno, $errstr, $errfile, $errline)
{
    echo "Handled error [$errno]: $errstr in $errfile on line $errline\n";
    return true; // we consider the error fully handled
}

set_error_handler("customErrorHandler");

trigger_error("This is a test warning", E_USER_WARNING);

// Restore PHP's default error handling
restore_error_handler();

Вывод:

Handled error [512]: This is a test warning in ... on line 11

512 — числовое значение E_USER_WARNING. После вызова restore_error_handler() ошибки возвращаются к поведению PHP по умолчанию.

Преобразование ошибок в исключения

Распространённый паттерн в продакшне — преобразование предупреждений и уведомлений в исключения, чтобы они проходили через обычную логику try/catch. Это позволяет обрабатывать ошибки file_get_contents() (которая выдаёт только предупреждение) с помощью try/catch:

<?php

set_error_handler(function ($errno, $errstr, $errfile, $errline) {
    // Respect the @ operator and error_reporting settings.
    if (!(error_reporting() & $errno)) {
        return false;
    }
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});

try {
    $data = file_get_contents("/no/such/file");
} catch (ErrorException $e) {
    echo "Caught: " . $e->getMessage() . "\n";
}

Вывод:

Caught: file_get_contents(/no/such/file): Failed to open stream: No such file or directory

Логирование вместо отображения

Сопоставление константы уровня с читаемой меткой делает логи удобнее для просмотра. Используйте error_log() для записи в настроенный назначенный журнал:

<?php

set_error_handler(function ($errno, $errstr, $errfile, $errline) {
    $levels = [
        E_WARNING       => "WARNING",
        E_NOTICE        => "NOTICE",
        E_DEPRECATED    => "DEPRECATED",
        E_USER_WARNING  => "USER_WARNING",
    ];
    $label = $levels[$errno] ?? "UNKNOWN($errno)";

    $line = "[$label] $errstr in $errfile:$errline";
    error_log($line);   // goes to your log, not the page
    echo $line . "\n";  // shown here only to demonstrate the output
    return true;
});

trigger_error("Disk space low", E_USER_WARNING);

Вывод:

[USER_WARNING] Disk space low in ... :15

Подводные камни

  • Оператор @. Когда ошибка подавляется с помощью @, функция error_reporting() возвращает 0 внутри вашего обработчика. Проверяйте error_reporting() & $errno, если хотите учитывать @, как показано выше.
  • Фатальные ошибки по-прежнему ускользают. Независимо от второго аргумента, E_ERROR и ошибки синтаксиса никогда не передаются вашему обработчику.
  • Обработчик глобален. Зарегистрированный обработчик влияет на весь запрос. Библиотеки, устанавливающие собственный обработчик, могут перезаписать ваш, поэтому восстанавливайте обработчики после завершения работы.
  • Не используйте echo в продакшне. Отображение сырых сообщений раскрывает пути и помогает злоумышленникам — записывайте их в лог и показывайте пользователю обобщённую страницу.

Связанные функции

Заключение

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

Практика

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