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

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

 header("HTTP/1.1 500 Internal Server Error"); 

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

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 о обработчике ошибок

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

 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'); 

Невозможно обрабатывать 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, когда код приложения сбой и ожоги.

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

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

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

 try { ...badcode... throw new Exception('error'); } catch (Exception $e) { header("Status: 500 Server Error"); var_dump($e->getMessage()); } 

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

Никогда не забудьте установить 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) или http_response_code(500) .

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

рок-твердое тело-script.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"); 

скрипт-я-хочу-к-охранником-для-errors.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. Это кажется мне более элегантным, но я не могу найти способ его снять. Я попробовал флаг RewriteRule R, но это предотвращает выполнение php вообще, так что это бесполезно.

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

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

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