Alex Rivera | Logout

Catch PHP Fatal Error

Asked 2010-02-25T04:11:44.627
21

I have a web service site that is restful enabled, so other websites/ajax script can make a call to the site to get/set data. However, whenever the web service site somehow returns a PHP fatal error, the HTTP status that is returned is 200 instead of 500. Is there a way to fix it so that whenever a fatal error occurs, returns 500 instead of 200? Or, if it is not possible, how can I change my client to recognize the fatal error returned by the webservice?

Edit
Report

4 Answers

29

PHP does send a HTTP 500 on a Fatal error.
Let me cite a comment in this PHP bug-report (a xdebug bug prevents this behavior):

It does happen. It requires that:

1) display_errors = off
2) No headers have been sent yet by the time the error happens
3) Status is 200 at that time.

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

You can catch fatal errors with a shutdown function and 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');
    }
});
answered 2011-11-28T12:10:21.013
14

One possible way would be to set the default response to 500, if everything executes successfully set the response to 200:

http_response_code(500);
render_my_page();
http_response_code(200);
answered 2010-02-25T04:24:04.160
2

I developed a way to catch all error types in PHP (almost all)! I have no sure about E_CORE_ERROR ( I think it will not work for that error)! But, for other fatal errors (E_ERROR, E_PARSE, E_COMPILE...) works fine using only one error handler function! There's my solution:

Put this following code on your main file (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 //
            $typest
answered 2012-05-11T04:40:25.790
-4

I would think that you'd want to catch and fix all Fatal errors before deploying the application, since many of them are code errors, missing includes, non-existent objects, which are all development errors. Even out-of-memory errors can be minimized against with coding techniques that are memory frugal (one of the biggest wins is using unbuffered queries and processing the data and emitting output as the resultset is returned, instead of throwing around huge arrays).

answered 2010-02-25T05:24:35.467

Your Answer