Catch PHP Fatal Error

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

Solutions Collecting From Web of "Catch PHP Fatal Error"

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

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

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

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

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

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

Вы можете уловить фатальные ошибки с помощью функции shutdown и 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'); } }); 

Создайте собственный обработчик ошибок ( set_error_handler ) и header("HTTP/1.0 500 Service not available"); вызова 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; ?> 
 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'); 

Я разработал способ поймать все типы ошибок в 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(); ?> 

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

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