在 PHP/CodeIgniter 中捕获意外终止 [英] Capturing unexpected termination in PHP / CodeIgniter

查看:21
本文介绍了在 PHP/CodeIgniter 中捕获意外终止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 CodeIgniter 来托管 RESTful API,并且我想捕获任何未返回预期状态代码的 API 响应.这可能最容易用一个例子来解释.一般来说,我的代码是这样的:

函数 post_comment(){$comment = $_POST['comment'];$result = do_something_with_comment($comment);如果($result === true){return_json_response(200, 'OK!');}别的{return_json_response(400, '发生了可怕的事情......');}}

返回 200 或 400 是完全有效的.我的问题是:如何在 do_something_with_comment() 出现致命错误时捕获错误,或者如果我在 do_something_with_comment() 内部留下打印调试.在前一种情况下,我永远不会到达 return_json_response().在后一种情况下,我会到达它,但屏幕调试会破坏 JSON 响应.

有没有办法围绕它创建一个通用包装器来捕获任何意外的输出或终止?

解决方案

一般来说,您可以:

尽可能使用异常/异常处理

注册一个将 PHP 错误转换为异常的自定义错误处理程序,例如将其放在 config/config.php 的顶部

function my_error_handler($errno, $errstr, $errfile, $errline){如果 (!(error_reporting() & $errno)){//此错误代码不包含在 error_reporting 中返回;}log_message('error', "$errstr @$errfile::$errline($errno)");throw new ErrorException( $errstr, $errno, 0, $errfile, $errline );}set_error_handler("my_error_handler");

注册一个未捕获的异常处理程序,在你的 config/config.php 中放入类似的内容

function my_exception_handler($exception){echo '

';print_r($exception);echo '</pre>';header("HTTP/1.0 500 内部服务器错误");}set_exception_handler("my_exception_handler");

编辑

设置终止处理程序:

function my_fatal_handler(){$errfile = "未知文件";$errstr = "致命错误";$errno = E_CORE_ERROR;$错误线= 0;$error = error_get_last();如果 ( $error !== NULL ){echo '

';打印_r($错误);echo '</pre>';header("HTTP/1.0 500 内部服务器错误");}}register_shutdown_function("my_fatal_handler");

设置一个自定义断言处理程序,将断言转换为异常,在您的 config/config.php 中放入类似的内容:

function my_assert_handler($file, $line, $code){log_message('debug', "断言失败@$file::$line($code)");throw new Exception("断言失败@$file::$line($code)");}断言选项(ASSERT_ACTIVE,1);assert_options(ASSERT_WARNING, 0);断言选项(ASSERT_BAIL,0);断言选项(ASSERT_QUIET_EVAL,0);assert_options(ASSERT_CALLBACK, 'my_assert_handler');

然后,这就是你的答案,在你的控制器中使用这样的包装器

公共函数controller_method(){尝试{//正常流量}catch( 异常 $e ){log_message( 'error', $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine() );//出错时}}

您可以根据自己的喜好调整和自定义整个内容!

希望这会有所帮助.

编辑

您还需要拦截 CI show_error 方法.把它放在 application/core/MY_exceptions.php:

class MY_Exceptions 扩展 CI_Exceptions{函数 show_error($heading, $message, $template = 'error_general', $status_code = 500){log_message('debug', print_r($message, TRUE));throw new Exception(is_array($message) ? $message[1] : $message, $status_code );}}

并在 application/config/database.php 中将此设置保留为 FALSE,以便将数据库错误转换为异常.

$db['default']['db_debug'] = TRUE;

CI 有一些(非常)弱点,例如异常处理,但这将大有帮助.

I'm using CodeIgniter to host a RESTful API and I'd like to capture any API response that does not return an expected status code. This is probably most easily explained with an example. In general, my code looks like this:

function post_comment()
{
     $comment = $_POST['comment'];
     $result = do_something_with_comment($comment);

     if ($result === true)
     {
         return_json_response(200, 'OK!');
     }
     else
     {
         return_json_response(400, 'Something terrible happened...');
     }
}

Returning either a 200 or 400 is perfectly valid. My problem is: how to capture errors when do_something_with_comment() has a fatal error, or if I leave a print debug inside of do_something_with_comment(). In the former case, I'll never reach return_json_response(). In the latter case, I'll reach it, but the screen debug will corrupt the JSON response.

Is there any way to create a generic wrapper around this to capture any unexpected output or termination?

解决方案

In general you could:

Use exception /exception handling as much as possible

Register a custom errorhandler that transforms PHP errors into exceptions, for instance put this in top of your config/config.php

function my_error_handler($errno, $errstr, $errfile, $errline)
{
    if (!(error_reporting() & $errno))
    {
        // This error code is not included in error_reporting
        return;
    }
    log_message('error', "$errstr @$errfile::$errline($errno)" );
    throw new ErrorException( $errstr, $errno, 0, $errfile, $errline );
}
set_error_handler("my_error_handler");

Register an uncaught exception handler, put something like this in your config/config.php

function my_exception_handler($exception)
{
    echo '<pre>';
    print_r($exception);
    echo '</pre>';
    header( "HTTP/1.0 500 Internal Server Error" );
}
set_exception_handler("my_exception_handler");

EDIT

Set a termination handler:

function my_fatal_handler()
{
    $errfile = "unknown file";
    $errstr  = "Fatal error";
    $errno   = E_CORE_ERROR;
    $errline = 0;
    $error = error_get_last();
    if ( $error !== NULL )
    {
        echo '<pre>';
        print_r($error);
        echo '</pre>';
        header( "HTTP/1.0 500 Internal Server Error" );
    }
}
register_shutdown_function("my_fatal_handler");

Set a custom assert handler that converts asserts into exceptions, put something like this in your config/config.php:

function my_assert_handler($file, $line, $code)
{
    log_message('debug', "assertion failed @$file::$line($code)" );
    throw new Exception( "assertion failed @$file::$line($code)" );
}
assert_options(ASSERT_ACTIVE,     1);
assert_options(ASSERT_WARNING,    0);
assert_options(ASSERT_BAIL,       0);
assert_options(ASSERT_QUIET_EVAL, 0);
assert_options(ASSERT_CALLBACK, 'my_assert_handler');

Then, and this is your answer, use wrappers like this in your controllers

public function controller_method( )
{
    try
    {
        // normal flow
    }
    catch( Exception $e )
    {
        log_message( 'error', $e->getMessage( ) . ' in ' . $e->getFile() . ':' . $e->getLine() );
        // on error
    }
}

You can tune and customize the whole thing to your likings!

Hope this helps.

EDIT

You will also need to intercept the CI show_error method. Place this in application/core/MY_exceptions.php:

class MY_Exceptions extends CI_Exceptions
{
    function show_error($heading, $message, $template = 'error_general', $status_code = 500)
    {
        log_message( 'debug', print_r( $message, TRUE ) );
        throw new Exception(is_array($message) ? $message[1] : $message, $status_code );
    }
}

And leave in application/config/database.php this setting on FALSE to have database errors converted into exceptions.

$db['default']['db_debug'] = TRUE;

CI has a few (very) weak points, such as exception-handling but this will go a long way correcting that.

这篇关于在 PHP/CodeIgniter 中捕获意外终止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆