Наша группа в Telegram для обмена идеями, проектами, мыслями, людьми в сфере ИТ г.Ростова-на-Дону: @it_rostov

Перехват fatal error или Перехват неперехватываемых ошибок


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

// мы будем сами обрабатывать ВСЕ ошибки
error_reporting(E_ALL);

// определенная пользователем функция обработки ошибок
function userErrorHandler ($errno, $errmsg, $filename, $linenum, $vars) {
    // дата и время для записи об ошибке
    $dt = date("Y-m-d H:i:s (T)");

    // определение ассоциативного массива строк ошибок
    // на самом деле следует рассматривать только элементы 2,8,256,512 и 1024
    $errortype = array (
                1   =>  "Ошибка",
                2   =>  "Предупреждение",
                4   =>  "Ошибка синтаксического анализа",
                8   =>  "Замечание",
                16  =>  "Ошибка ядра",
                32  =>  "Предупреждение ядра",
                64  =>  "Ошибка компиляции",
                128 =>  "Предупреждение компиляции",
                256 =>  "Ошибка пользователя",
                512 =>  "Предупреждение пользователя",
                1024=>  "Замечание пользователя"
                );
    // набор ошибок, для которого будут сохраняться значения переменных
    $user_errors = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE);

    $err  = $dt." ".$errortype[$errno]." № ".$errno."\n";
    $err .= $errmsg."\n";
    $err .= "Вызов из ".$filename." строка № ".$linenum."\n";

    ob_end_clean();
    ob_start();
    print_r($vars);
    $v = "Переменные:".ob_get_contents()."\n";
    ob_end_clean();
    ob_start("error_callback");

    // сохранить протокол ошибок и отправить его мылом
    mail('error@htmlweb.ru', 'PHP error report', $err.$v, "Content-Type: text/plain; charset=windows-1251" ) or die("Ошибка при отправке сообщения об ошибке");
    error_log($err."\n", 3, dirname(__FILE__) . "/log/error.log") or die("Ошибка записи сообщения об ошибке в файл");
}

function error_callback($buffer) {
    // если на экран будет выведено сообщение о фатальной ошибке, мы его сможем обработать
    if (preg_match("/<b>error</b>.*/",$buffer,$regs)) {
       $regs[0] = date("Y-m-d H:i:s (T)")."\n".preg_replace("/<[/]?b(r /)?>/","",$regs[0])."\n";
       mail('error@htmlweb.ru', 'PHP error report', $regs[0], "Content-Type: text/plain; charset=windows-1251" ) or die("Ошибка при отправке сообщения об ошибке");
       error_log($regs[0], 3, dirname(__FILE__) . "/log/error.log") or die("Ошибка записи сообщения об ошибке в файл");
       return "Ошибка, выполнение прервано";
    }
    else
       return $buffer;
}

// Перехват вывода на экран
ob_start("error_callback");

// Перехват обработки ошибок
$old_error_handler = set_error_handler("userErrorHandler");

Перехват fatal error в PHP

Следующий пример позволяет назначить функцию-обработчик завершения любого PHP скрипта. Этот обработчик получит управление и при возникновении fatal error.

// Определяем новую функцию-обработчик fatal error.
function myShutdownHandler() {
  if (@is_array($e = @error_get_last())) {
    $code = isset($e['type']) ? $e['type'] : 0;
    $msg = isset($e['message']) ? $e['message'] : '';
    $file = isset($e['file']) ? $e['file'] : '';
    $line = isset($e['line']) ? $e['line'] : '';
    if($code>0)userErrorHandler($code,$msg,$file,$line,'');

  }
}
register_shutdown_function('myShutdownHandler');

// вызываем ошибку:
$x = null;
$x->method();

userErrorHandler - процедура обработки ошибкок, описанная выше.