【问题标题】:How to handle php notices, warnings and errors in REST api?如何处理 REST api 中的 php 通知、警告和错误?
【发布时间】:2015-04-30 05:51:16
【问题描述】:

在 REST API 中,200 响应表示操作成功。 PHP 默认情况下直接在响应正文中输出错误消息,而不更改响应代码。在 SPA 中,响应文本对用户不直接可见。因此,当应用程序无法按预期工作时,我会通过 FireBug 检查响应正文以检查可能的 PHP 异常(这会导致无效的 json 响应)。 有没有办法在所有 PHP 错误上发送特定的 HTTP 代码?

有没有办法根据任何 PHP 错误的存在来更改 HTTP 响应代码?或者,是否可以轻松获取错误文本并以 json 格式发送。 (处于开发阶段)

更新:异常捕获(try/catch/final)不是我想要的。

【问题讨论】:

  • 为什么不能使用error_reporting(0)?
  • 您必须捕获这些错误并在输出中发送这些错误响应。
  • @SanjayKumarNS 我需要报告错误。我只想为我的基于 Angular 的单页应用程序提供错误 http 响应。
  • 此链接可能对您有所帮助stackoverflow.com/questions/16374526/…
  • 您在我的回答尝试下方评论:“异常捕获(try/catch/final)不是我要寻找的。通知/警告不是异常。此外,通过程序添加 try/catch 也太过分了对于这个问题。";所以我删除了我的答案,但我建议你详细说明你的问题到底是什么:)

标签: php rest error-handling single-page-application


【解决方案1】:

例如,假设您只关心致命的运行时错误、致命的编译时错误和运行时警告。使用error_reporting() 函数将错误报告设置为所需的级别。

error_reporting( E_ERROR | E_COMPILE_ERROR | E_WARNING );

由于用户定义的错误处理程序(下文稍后)无法处理致命错误,因此仍会显示致命错误消息。为避免这种情况,请使用 ini_set() 函数并将 display_errors 设置为零。

ini_set( 'display_errors', 0 );

现在使用set_error_handler() 创建一个自定义错误处理程序,以完全绕过指定错误类型的 PHP 错误处理程序(不适用于致命错误)。

/* The following error types cannot be handled with a user defined function: 
 *  E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING
 * The standard PHP error handler is completely bypassed for the error types specified
 *  unless the callback function returns FALSE.
 */
function exception_error_handler( $severity, $message, $file, $line ) 
{
    if ( !( error_reporting() & $severity ) ) {
        // This error code is not included in error_reporting
        return;
    }

    // code for handling errors
}
set_error_handler( "exception_error_handler" );

可以在关机时使用register_shutdown_function() 处理致命错误。关闭处理程序在脚本完成后执行,或者被终止(这也适用于错误)。我们需要获取关于发生的最后一个错误的信息(error_get_last()),接下来是检查这是否是我们跟踪的错误类型(这里实际上不需要它,因为error_reporting 中没有指定的错误不会被触发,但过滤错误很有用),最后调用异常处理程序。

function fatal_error_shutdown() 
{
    $last_error = error_get_last();
    if ( error_reporting() & $last_error['type'] )
        call_user_func_array( 'exception_error_handler', $last_error );
}
register_shutdown_function( 'fatal_error_shutdown' );

现在您可以使用自定义异常处理程序来捕获未处理的异常(包括致命异常)并强制响应代码(使用header() 函数)。

【讨论】:

    【解决方案2】:

    当然你可以在 PHP 中改变 HTTP 状态:

    <?php 
       header("HTTP/1.1 502 Bad Gateway");
    ?> 
    

    您可以更改消息和代码,但您必须小心standard codes

    【讨论】:

    • 答案没有解决问题,我想知道它是如何获得这样的选票的。
    【解决方案3】:

    set_error_handler 函数是我错过的。我想出了以下代码。欢迎任何更好的答案。

    function jsonErrorHandler()
    {
       if (error_reporting()) {
    
            http_response_code(500);
            header('Content-Type: application/json; charset=utf-8');
            $response = array_combine(['errno', 'errstr', 'errfile', 'errline', 'errcontext'], func_get_args());
            die(json_encode($response));
    
      }
    }
    
    set_error_handler('jsonErrorHandler');
    

    【讨论】:

      【解决方案4】:

      使用框架或an error handler library

      根据您选择的框架,您可以自定义错误处理程序如何呈现错误。我链接的错误处理程序显然默认支持将错误序列化为 JSON,您应该查看它的文档。

      有了一个框架,这是 Laravel 4 的 example

      App::error(function(Exception $exception, $code) {
          Log::error($exception);
          return Response::json(["code" => $code, "message" => $exception->getMessage()], $code);
      });
      

      请注意,如果您依赖全局错误处理程序,通常其他地方会出现问题 - 您不应依赖它来处理错误;而是在适当的地方使用 try/catch。

      【讨论】:

      • 来自您的链接页面:“这会将 401 和 404 的所有错误转换为自定义 json 错误,而不是 Whoops 堆栈跟踪。”正如我在问题中解释的那样,响应代码是 200,并且通知在响应正文上。
      • @PHPst 框架使所有异常默认抛出堆栈跟踪和 500 错误。
      【解决方案5】:

      虽然您的部分问题在这里得到了回答 Returning http status codes with a rest api

      我建议不要为许多警告、错误和通知发送不同的 http 代码。 500(http 代码 500)内部服务器错误应该会发生,并且您不需要向 API 使用者公开错误的细节。当然,您可以记录所有错误/通知/警告以调试和修复您的应用程序。

      此外,还取决于您的应用程序逻辑,需要向用户报告哪些错误,如数据验证、业务逻辑等。

      【讨论】:

      • 谢谢,但答案没有解决问题。我寻求一种自动方法来更改 PHP 错误/通知未捕获错误的 http 响应标头。
      【解决方案6】:

      HTTP 状态码在 HTTP 响应的标头中发送,这意味着只要 PHP 没有向客户端发送任何字节,您就可以随时更改它。如果已经这样做了,您很可能会收到 Cannot modify header information - headers already sent 错误。

      PHP有几个函数可以改变状态码,我推荐http_response_code(),因为它更容易使用:你只需要发送HTTP状态码,它会为你写完整的头部。

      为了捕捉错误,我建议设置一个error handler

      function log_error($errno, $errstr, $errfile = '', $errline = 0, $errcontext = array())
      {
          // Save the error to the error log.
          // You may want to add more information than $errstr in the log, so feel free to change this line.
          error_log($errstr);
      
          // If headers haven't been sent, you can set a new one.
          if (!headers_sent())
          {
              // 500 is the most generic error when the error comes from your application.
              http_response_code(500);
      
              // Checking if you're in debug mode allows you to show you errors while developping, and hiding them for users.
              // Change this line by your own checks.
              if (IS_DEBUG)
              {
                  // Send the correct Content-Type header.
                  header('Content-Type: application/json; charset=utf-8');
      
                  // Sending information about the error.
                  echo json_encode(array(
                      'error' => $errstr // Once again, you may want to add more information.
                  ));
      
                  // Exiting since we do not want the script to continue.
                  exit;
              }
              else
              {
                  // Do whatever you want here, it will be shown to your users if you're not in debug mode.
                  // But do not forget to exit.
                  exit;
              }
          }
      }
      
      // Setting your function as an error handler.
      set_error_handler('error_handler');
      

      由于 PHP 中的错误处理程序不处理异常,我还建议设置一个exception handler

      您的应用程序在运行时遇到的每个 PHP 错误(例如,不包括解析错误)现在都将发送 500 Internal Server Error 响应,如果您愿意,还可以提供有关错误的详细信息。

      【讨论】:

        【解决方案7】:

        您可以使用register_shutdown_function()error_get_last() PHP 函数来捕获任何错误并返回有效响应。 There is a working example 使用在RockWall REST engine

        【讨论】:

          【解决方案8】:

          在 Yii 框架中,非常有效地处理此类问题。

          他们使用 PHP 的 set_exception_handler('exceptionHandlerFunction')set_error_handler('errorHandlerFunction') 函数分别处理所有类型的异常和错误(警告、通知)。

          关于致命错误,register_shutdown_function('fatalHandlerFunction')

          现在,出于展示目的,Yii 的工作效率很高。

          在错误/异常/致命处理函数中,是否向客户端抛出错误或显示格式正确的错误取决于配置。

          如果想要显示格式正确,Yii 正在将路由转移到 SystemController 的错误动作。

          您也可以使用How Yii Handling Errors

          希望对你有帮助!!

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-06-13
            • 1970-01-01
            • 2012-09-09
            • 1970-01-01
            • 1970-01-01
            • 2019-03-30
            • 1970-01-01
            相关资源
            最近更新 更多