Подтвердить что ты не робот

Catch PHP Fatal Error

У меня есть сайт веб-сервиса, который поддерживается без проблем, поэтому другие веб-сайты/ajax script могут совершать звонок на сайт для получения/установки данных. Однако, всякий раз, когда сайт веб-службы каким-то образом возвращает фатальную ошибку PHP, возвращается HTTP-статус 200, а не 500. Есть ли способ исправить его, чтобы всякий раз, когда возникает фатальная ошибка, возвращается 500 вместо 200? Или, если это невозможно, как я могу изменить свой клиент для распознавания фатальной ошибки, возвращаемой веб-сервисом?

4b9b3361

Ответ 1

Одним из возможных способов было бы установить ответ по умолчанию на 500, если все выполняется успешно, установите ответ на 200:

http_response_code(500);
render_my_page();
http_response_code(200);

Ответ 2

PHP отправляет HTTP 500 по Неустранимая ошибка.
Позвольте мне привести комментарий в этот отчет об ошибке PHP (ошибка xdebug предотвращает это поведение):

Это происходит. Это требует, чтобы:

1) display_errors = off
2) К моменту возникновения ошибки заголовки не отправляются 3) В то время статус равен 200.

<?
    ini_set('display_errors', 0); 
    foobar();
    // This will return a http 500
?>

Вы можете уловить фатальные ошибки с помощью функции выключения и error_get_last:

register_shutdown_function(function() {
    $lastError = error_get_last();

    if (!empty($lastError) && $lastError['type'] == E_ERROR) {
        header('Status: 500 Internal Server Error');
        header('HTTP/1.0 500 Internal Server Error');
    }
});

Ответ 3

Создайте собственный обработчик ошибок (set_error_handler) и вызовите header("HTTP/1.0 500 Service not available");.

Изменить:

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

<?php
        $x = y();
?>

Приведенный выше код вернет код ошибки 500, если на экран ничего не отправлено.

Итак, если вы хотите, чтобы такая ошибка задавала правильный код, выполните свою собственную буферизацию:

<?php
        $buffer = 'blah';
        $x = y();  // will trigger 500 error
        echo $buffer;
?>

Ответ 4

function fatal_error_handler() {

  if (@is_array($e = @error_get_last())) {
    if (isset($e['type']) && $e['type']==1) {
      header("Status: 500 Internal Server Error");
      header("HTTP/1.0 500 Internal Server Error");
      }
    }

}
register_shutdown_function('fatal_error_handler');

Ответ 5

Я разработал способ поймать все типы ошибок в PHP (почти все)! Я не уверен в E_CORE_ERROR (я думаю, что это не сработает для этой ошибки)! Но для других фатальных ошибок (E_ERROR, E_PARSE, E_COMPILE...) отлично работает, используя только одну функцию обработчика ошибок! Там мое решение:

Поместите этот следующий код в свой основной файл (index.php):

<?php

define('E_FATAL',  E_ERROR | E_USER_ERROR | E_PARSE | E_CORE_ERROR | 
        E_COMPILE_ERROR | E_RECOVERABLE_ERROR);

define('ENV', 'dev');

//Custom error handling vars
define('DISPLAY_ERRORS', TRUE);
define('ERROR_REPORTING', E_ALL | E_STRICT);
define('LOG_ERRORS', TRUE);

register_shutdown_function('shut');

set_error_handler('handler');

//Function to catch no user error handler function errors...
function shut(){

    $error = error_get_last();

    if($error && ($error['type'] & E_FATAL)){
        handler($error['type'], $error['message'], $error['file'], $error['line']);
    }

}

function handler( $errno, $errstr, $errfile, $errline ) {

    switch ($errno){

        case E_ERROR: // 1 //
            $typestr = 'E_ERROR'; break;
        case E_WARNING: // 2 //
            $typestr = 'E_WARNING'; break;
        case E_PARSE: // 4 //
            $typestr = 'E_PARSE'; break;
        case E_NOTICE: // 8 //
            $typestr = 'E_NOTICE'; break;
        case E_CORE_ERROR: // 16 //
            $typestr = 'E_CORE_ERROR'; break;
        case E_CORE_WARNING: // 32 //
            $typestr = 'E_CORE_WARNING'; break;
        case E_COMPILE_ERROR: // 64 //
            $typestr = 'E_COMPILE_ERROR'; break;
        case E_CORE_WARNING: // 128 //
            $typestr = 'E_COMPILE_WARNING'; break;
        case E_USER_ERROR: // 256 //
            $typestr = 'E_USER_ERROR'; break;
        case E_USER_WARNING: // 512 //
            $typestr = 'E_USER_WARNING'; break;
        case E_USER_NOTICE: // 1024 //
            $typestr = 'E_USER_NOTICE'; break;
        case E_STRICT: // 2048 //
            $typestr = 'E_STRICT'; break;
        case E_RECOVERABLE_ERROR: // 4096 //
            $typestr = 'E_RECOVERABLE_ERROR'; break;
        case E_DEPRECATED: // 8192 //
            $typestr = 'E_DEPRECATED'; break;
        case E_USER_DEPRECATED: // 16384 //
            $typestr = 'E_USER_DEPRECATED'; break;

    }

    $message = '<b>'.$typestr.': </b>'.$errstr.' in <b>'.$errfile.'</b> on line <b>'.$errline.'</b><br/>';

    if(($errno & E_FATAL) && ENV === 'production'){

        header('Location: 500.html');
        header('Status: 500 Internal Server Error');

    }

    if(!($errno & ERROR_REPORTING))
        return;

    if(DISPLAY_ERRORS)
        printf('%s', $message);

    //Logging error on php file error log...
    if(LOG_ERRORS)
        error_log(strip_tags($message), 0);

}

ob_start();

@include 'content.php';

ob_end_flush();

?>

Надеюсь, это поможет многим людям!

Ответ 6

Я бы подумал, что вы хотите поймать и исправить все Fatal-ошибки перед развертыванием приложения, так как многие из них являются ошибками кода, отсутствующие включают в себя несуществующие объекты, которые являются ошибками разработки. Даже ошибки из-за памяти могут быть сведены к минимуму с помощью методов кодирования, которые являются экономными в памяти (один из самых больших выигрышей - использование небуферизованных запросов и обработка данных и выдача выходных данных, когда возвращается результат, вместо того, чтобы метать огромные массивы).