Как я могу заставить php возвращать 500 при возникновении фатального исключения?

Неустранимые ошибки PHP возвращаются HTTP-клиенту как код состояния 200. Как сделать так, чтобы он возвращал код состояния 500 (внутренняя ошибка сервера)?


person Mike    schedule 12.10.2009    source источник
comment
тот факт, что php возвращает ошибку, не связанную с заголовком HTML, который вы получаете в браузере. Если вы запустите этот скрипт из командной строки, вы не получите код ошибки 200.   -  person Gabriel Sosa    schedule 12.10.2009
comment
См. Решение stackoverflow.com/questions/2331582/catch-php-fatal-error.   -  person cweiske    schedule 14.04.2011
comment
Мне нужно прямо противоположное. Я установил функцию выключения, которая с auto_prepend_file улавливает все фатальные ошибки. Однако я также хочу, чтобы status code 200 отправлялся при вызове этой функции. Но я продолжаю получать status code 500.   -  person Majid Fouladpour    schedule 30.06.2015


Ответы (10)


Это как раз та проблема, с которой я столкнулся вчера, и я нашел решение следующим образом:

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

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

function my_error_handler()
{
  $last_error = error_get_last();
  if ($last_error && $last_error['type']==E_ERROR)
      {
        header("HTTP/1.1 500 Internal Server Error");
        echo '...';//html for 500 page
      }
}
register_shutdown_function('my_error_handler');

Примечание: если вы хотите поймать пользовательский тип ошибки, который начинается с E_USER *, вы можете использовать функцию set_error_handler () для регистрации обработчика ошибок и запуска ошибки с помощью функции trigger_error, однако этот обработчик ошибок не может обрабатывать тип ошибки E_ERROR. см. объяснение на php.net об обработчике ошибок

person fuyi    schedule 13.01.2012
comment
Не забудьте также использовать ini_set("display_errors", "off"); в производственной среде, иначе сообщения о фатальных ошибках будут отправлены обратно клиенту. - person alexw; 06.03.2015
comment
Я также предлагаю проверить E_PARSE - он также доступен для улавливания, если функция выключения установлена ​​до того, как будет включен файл с ошибкой синтаксического анализа. - person Brilliand; 27.10.2015

Я использовал set_exception_handler для обработки неперехваченных исключений.

function handleException($ex) {
      error_log("Uncaught exception class=" . get_class($ex) . " message=" . $ex->getMessage() . " line=" . $ex->getLine());
      ob_end_clean(); # try to purge content sent so far
      header('HTTP/1.1 500 Internal Server Error');
      echo 'Internal error';
    }

set_exception_handler('handleException');
person Matti Haavikko    schedule 23.09.2010
comment
Вы можете сделать это, если хотите обрабатывать фатальные ошибки: stackoverflow.com/questions/277224/ - person John Hunt; 22.03.2013
comment
Используйте как set_error_handler, так и set_exception_handler. Первый - для фатальных ошибок старого типа, второй - для объектно-ориентированных исключений. - person Ron Inbar; 12.05.2014

Стандартная конфигурация PHP возвращает значение 500 при возникновении ошибки! Просто убедитесь, что ваш display_errors = off. Вы можете смоделировать это с помощью:

ini_set('display_errors', 0); 
noFunction();

По умолчанию директива display_errors отключена.

person lukyer    schedule 05.04.2016
comment
Это должно быть выше. На самом деле это правильный способ настроить сервер так, чтобы он возвращал 500 при фатальных ошибках. Если вам нужно увидеть сообщения об ошибках, вы должны использовать журнал ошибок. - person Dan H; 31.07.2018

Невозможно каким-либо образом обработать PHP E_ERROR согласно документации PHP: http://www.php.net/manual/en/function.set-error-handler.php

Также невозможно обработать E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING и большую часть E_STRICT по этой ссылке.

Вы МОЖЕТЕ предоставить обработчик для других ошибок, предупреждений и уведомлений, включая E_USER_ERROR, но на самом деле это не так полезно, как кажется, поскольку эта ошибка возникает только намеренно программистом с помощью trigger_error ().

И, конечно же, вы можете перехватить любое исключение (даже то, что генерируется встроенными функциями PHP).

Я согласен, что это проблема. Серверы НЕ должны возвращать 200 OK при сбое и сгорании кода приложения.

person Jonathan Hanson    schedule 24.01.2010
comment
отвечая на супер старый ответ здесь ... но с php 5.2 ... вы можете использовать error_get_last() внутри функции выключения .. если последняя ошибка была фатальной .. тада - person Brad Kent; 16.03.2018

Поскольку PHP> = 5.4

http_response_code(500);
echo json_encode( [ 'success' => false , 'message' => 'Crazy thing just happened!' ]);
exit();

Пожалуйста, установите httpCode перед echo.

person vanduc1102    schedule 16.06.2020

Вы можете использовать обработку ошибок php

http://www.w3schools.com/php/php_error.asp

person Xinus    schedule 12.10.2009
comment
Хороший ответ - это больше, чем просто ссылки на другие страницы. Например, вы могли бы вскоре сослаться на эту страницу. Что происходит, когда целевой сайт не работает или они перемещают этот контент? Кроме того, w3schools - не очень хороший источник. - person Olli; 08.04.2012

Вам нужно будет поймать возникшую ошибку, используя try / catch, а затем использовать это блок catch для отправки header () с ошибкой 500.

try {
    ...badcode...
    throw new Exception('error');

} catch (Exception $e) {

    header("Status: 500 Server Error");
    var_dump($e->getMessage());
}

Если фатальное исключение не окружено блоками try {} catch, вы должны зарегистрировать глобальный обработчик и использовать register_shutdown_function() для проверки наличия ошибки в конце скрипта.

person Xeoncross    schedule 12.10.2009
comment
Это будет перехватывать исключения, но не отлавливать фатальные ошибки PHP, которые обрабатываются вне области исключений. - person Alan Storm; 12.10.2009
comment
Насколько мне известно, фатальные / синтаксические ошибки не могут быть зафиксированы ни обработкой ошибок, ни обработкой исключений. - person ChrisR; 12.10.2009
comment
@ChrisRamakers: Я читал кое-что об использовании обработчиков вывода для обнаружения фатальных ошибок PHP. - person Alix Axel; 24.01.2010
comment
зависит, синтаксические ошибки запускаются во время компиляции, поэтому логика, которая обрабатывает вывод или простую обработку исключений, никогда не возникает, потому что страница просто не выполняется, потому что я не мог быть скомпилирован. Но опять же, я не абсолютный эксперт, поэтому я могу не знать обработчиков вывода, о которых вы говорите. - person ChrisR; 27.01.2010
comment
Фактически, вы используете register_shutdown_function() для обнаружения ошибок E_FATAL. - person Xeoncross; 18.08.2010

Никогда не забывайте устанавливать header("HTTP/1.1 200 OK", true, 200); в качестве последней строки любого пути выполнения:

//first things first:
header("HTTP/1.1 500 Internal Server Error", true, 500);


//Application code, includes, requires, etc. [...]


//somewhere something happens
//die();
throw new Exception("Uncaught exception!");


//last things last, only reached if code execution was not stopped by uncaught exception or some fatal error
header("HTTP/1.1 200 OK", true, 200);

В PHP 5.4 вы можете заменить указанную выше функцию header на гораздо лучшую http_response_code(200) < / a> или http_response_code(500).

person Tiberiu-Ionuț Stan    schedule 01.08.2012
comment
Это не работает, если между первым и последним вызовом header() создается какой-либо вывод, потому что тогда заголовок уже будет отправлен. Рабочие страницы могут доставляться со статусом 500. Такой подход слишком рискованный. - person Peter; 07.02.2014
comment
Используйте буферизацию вывода и вывод после заголовка. Что очевидно. Если буферизация вывода каким-либо образом не работает, это не рабочая страница, это страница с ошибками. - person Tiberiu-Ionuț Stan; 07.02.2014

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

рок-твердый-скрипт.php:

// minimize changes to this script to keep it rock-solid
http_response_code(500); // PHP >= 5.4
require_once("script-i-want-to-guard-for-errors.php");

скрипт-я-хочу-охранять-для-ошибок.php:

// do all the processsing
// don't produce any output
// you might want to use output buffering

http_response_code(200); // PHP >= 5.4

// here you can produce the output

Направьте ваш звонок на rock-solid-script.php, и вы готовы к работе.

Я бы предпочел установить код состояния по умолчанию 500 в .htaccess. Мне это кажется более элегантным, но я не могу найти способ справиться с этим. Я пробовал использовать R-флаг RewriteRule, но он полностью предотвращает выполнение php, так что бесполезно.

person Remco Nijhuis    schedule 22.02.2013

person    schedule
comment
Просто глупо, что вам придется вручную указывать версию HTTP, чтобы выдать код состояния. - person Drew Sears; 13.06.2012
comment
@DrewSears Я не думаю, что вам нужно; вы можете просто использовать поле заголовка Status, как в CGI. Но нужно сказать, что для программистов PHP, незнакомых с CGI, синтаксис HTTP / 1.1 легче читать, потому что он имитирует ответ HTTP. - person Chris Jester-Young; 15.06.2012
comment
Начиная с PHP ›= 5.4 есть функция http_response_code([int $responseCode]). - person Lars Nyström; 28.07.2016