且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

CodeIgniter:Try Catch在模型类中不工作

更新时间:2023-02-06 11:44:22

CI没有对异常的良好支持。你的DB查询将调用一些名为show_error()的一些模糊的CI error_logging东西。你需要做的是设置正确的异常处理。

CI has no good support for exceptions. You DB queries will call some vague CI error_logging thingie called show_error(). What you need to do is setup proper exception handling.

基本上你可以按照整个配方。

Basically you can follow the entire recipe.

现在所有的数据库错误都会自动抛出异常。作为一个奖励,你在整个CI应用程序中有良好的异常处理。

Now all your database errors will automatically throw exceptions. And as a bonus you have good exception handling in your entire CI application.

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

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

注册未捕获的异常处理程序,在config / config.php

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

设置终止处理程序:

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

设置一个自定义断言处理程序,将断言转换为异常,在config / config中加入这样的代码。 php:

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

在控制器中使用这样的包装器

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
    }
}

希望这会有帮助。

您还需要拦截CI show_error方法。将此放在application / core / MY_exceptions.php:

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

然后在application / config / database.php设置为FALSE以将数据库错误转换为异常。

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

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

CI有一些(非常)弱点,例如异常处理, 。

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

如果要使用事务,请确保对异常进行回滚。与此NEVER(如在EVER中)相关,使用持久性连接作为打开事务和其他会话特定的DB状态将被其他会话拾取/继续。

If you are going to use transactions, make sure you do rollbacks on exceptions. Related to this NEVER (as in EVER) use persistant connections as open transactions and other session specific DB state will be picked up / continued by other sessions.