代码之家  ›  专栏  ›  技术社区  ›  Jeffrey04 George

捕获PHP致命错误

  •  14
  • Jeffrey04 George  · 技术社区  · 14 年前

    我有一个启用了RESTful的Web服务站点,因此其他网站/Ajax脚本可以调用该站点来获取/设置数据。但是,每当Web服务站点以某种方式返回PHP致命错误时,返回的HTTP状态是200而不是500。是否有一种方法可以修复它,以便每当发生致命错误时,返回500而不是200?或者,如果不可能,如何更改客户机以识别WebService返回的致命错误?

    6 回复  |  直到 10 年前
        1
  •  13
  •   PowerKiKi webjawns.com    10 年前

    一种可能的方法是将默认响应设置为500,如果所有操作都成功执行,则将响应设置为200:

    http_response_code(500);
    render_my_page();
    http_response_code(200);
    
        2
  •  31
  •   Benjamin Cremer    13 年前

    PHP 在发生致命错误时发送HTTP 500。
    让我引用一个评论 this PHP bug-report (xdebug错误阻止此行为):

    确实发生了。它要求:

    1)显示错误=关闭
    2)错误发生时尚未发送邮件头
    3)当时状态为200。

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

    您可以使用 shutdown function 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
  •  3
  •   Matthew    14 年前

    创建自定义错误处理程序( set_error_handler 和呼叫 header("HTTP/1.0 500 Service not available"); .

    编辑:

    根据我回答的第一条评论,您不能捕获真正的致命错误。但是,如果输出缓冲被禁用并且错误不显示在屏幕上,PHP将默认为在致命错误上设置500个错误代码。

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

    因此,如果您希望此类错误设置正确的代码,请自行进行缓冲:

    <?php
            $buffer = 'blah';
            $x = y();  // will trigger 500 error
            echo $buffer;
    ?>
    
        4
  •  3
  •   Prof    13 年前
    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
  •  2
  •   Lucas Batistussi    10 年前

    我开发了一种方法来捕获PHP中的所有错误类型(几乎全部)!我不知道E-core-u错误(我认为它不会适用于那个错误)!但是,对于其他致命错误(e_错误、e_解析、e_编译…)只使用一个错误处理函数就可以正常工作!我的解决方案是:

    将以下代码放到主文件(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
  •  -5
  •   staticsan    14 年前

    我认为您应该在部署应用程序之前捕获并修复所有致命错误,因为其中许多错误都是代码错误、缺少include、不存在的对象,这些都是开发错误。即使是内存不足的错误也可以通过节省内存的编码技术来最小化(最大的胜利之一是使用未缓冲的查询和处理数据,并在返回结果集时发出输出,而不是丢弃大型数组)。