CodeIgniter:尝试Catch在模型类中不起作用

Him*_*dav 12 php codeigniter

unique对列有一个约束.当这段代码运行时,我从框架中获取错误日志,但它不是我在Exception块中给出的.
如果存在唯一列,那么我想查询其主键并将其设置为$id并返回到页面.现在它正在停止db错误而不是进入Catch block.
这是我的代码:

try {
            $result = $this->db->insert('email', $new_email);
            if ($result)
            {
                $id = $this->db->insert_id();    
            } else {
                throw new Exception("$$$$$$$$$$$$$Log database error");
            }
        } catch (Exception $e) {
            log_message('error',$e->getMessage());
            return;
        }
Run Code Online (Sandbox Code Playgroud)

**Error Messages** 我从框架得到:

DEBUG - 2013-04-07 05:00:38 --> DB Transaction Failure
ERROR - 2013-04-07 05:00:38 --> Query error: Duplicate entry 
Run Code Online (Sandbox Code Playgroud)

我不知道它有什么问题.

Pat*_*lle 27

CI对异常没有很好的支持.你的数据库查询会调用一些名为show_error()的模糊的CI error_logging thingie.您需要做的是设置适当的异常处理.

基本上你可以遵循整个食谱.

现在所有数据库错误都会自动抛出异常.作为奖励,您可以在整个CI应用程序中进行良好的异常处理.

注册一个自定义错误处理程序,将PHP错误转换为异常,例如将它放在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");
Run Code Online (Sandbox Code Playgroud)

注册一个未捕获的异常处理程序,在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");
Run Code Online (Sandbox Code Playgroud)

设置终止处理程序:

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");
Run Code Online (Sandbox Code Playgroud)

设置一个自定义断言处理程序,将断言转换为异常,在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');
Run Code Online (Sandbox Code Playgroud)

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

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

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

希望这可以帮助.

您还需要拦截CI show_error方法.将它放在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 );
    }
}
Run Code Online (Sandbox Code Playgroud)

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

$db['default']['db_debug'] = TRUE;
Run Code Online (Sandbox Code Playgroud)

CI有一些(非常)弱点,例如异常处理,但这将在很大程度上纠正这一点.

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