如何在REST api中处理php通知,警告和错误?

时间:2015-04-30 05:51:16

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

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

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

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

8 个答案:

答案 0 :(得分:10)

当然,您可以在PHP中更改HTTP状态:

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

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

答案 1 :(得分:10)

例如,假设您只关注致命的运行时错误,致命的编译时错误和运行时警告。使用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()),然后检查这是否是我们跟踪的错误类型(由于{ {1}}不会被触发,但过滤错误会很有用),最后调用异常处理程序。

error_reporting

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

答案 2 :(得分:6)

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

答案 3 :(得分:5)

使用框架或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。

答案 4 :(得分:3)

虽然您的问题的某些部分已在此处回答Returning http status codes with a rest api

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

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

答案 5 :(得分:3)

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

中使用的RockWall REST engine

答案 6 :(得分:3)

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 :(得分:1)

在Yii Framework中,非常有效地处理这些问题。

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

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

现在,为了显示目的,Yii的效率非常高。

在错误/异常/致命处理程序函数中,它可以向客户端抛出错误或显示格式错误。

如果要显示格式良好的话,Yii正在将路由转移到SystemController的错误操作。

您也可以使用How Yii Handling Errors

希望它有所帮助!!