Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php CodeIgniter:Try Catch在模型类中不起作用_Php_Codeigniter - Fatal编程技术网

Php CodeIgniter:Try Catch在模型类中不起作用

Php CodeIgniter:Try Catch在模型类中不起作用,php,codeigniter,Php,Codeigniter,我对列的属性有一个唯一的约束。当这段代码运行时,我从框架中得到错误日志,但它不是我在异常块中给出的 如果存在唯一列,则我希望查询其主键并将其设置为$id,然后返回页面。现在,它在db错误时停止,而不是进入捕获块 这是我的代码: try { $result = $this->db->insert('email', $new_email); if ($result) { $id = $

我对列的属性有一个
唯一的
约束。当这段代码运行时,我从框架中得到错误日志,但它不是我在异常块中给出的
如果存在唯一列,则我希望查询其主键并将其设置为
$id
,然后返回页面。现在,它在db错误时停止,而不是进入
捕获块

这是我的代码:

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;
        }
**错误消息**
我从框架中获得:

DEBUG - 2013-04-07 05:00:38 --> DB Transaction Failure
ERROR - 2013-04-07 05:00:38 --> Query error: Duplicate entry 

我不知道它出了什么问题。

如果打开数据库调试,数据库中的错误将被路由到Exceptions核心类,然后调用
exit()
,这意味着如果
有条件,脚本将永远不会到达您的

打开
application/config/database.php
并尝试将
db_debug
设置为false。无论如何,这对于生产网站来说是一个好主意,因为您不希望任何SQL查询问题发布有关数据库结构的信息


另外,在双引号内使用
$
时要小心,因为它会被解析为一个变量(甚至是一行中的一堆变量——它实际上是一个变量…)。

如果将结果设置在
try
块之外会怎么样?或三元运算符:

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

正如@jcorry所说,如果不知道
$result
的实际值是什么,很难知道。

CI对异常没有很好的支持。DB查询将调用一些模糊的CI错误记录内容,称为show\u error()。您需要做的是设置正确的异常处理

基本上你可以按照整个食谱来做

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

注册一个将PHP错误转换为异常的自定义errorhandler,例如,将其放在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");
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");
注册一个未捕获的异常处理程序,在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");
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");
在控制器中使用这样的包装器

$db['default']['db_debug'] = TRUE;
您可以根据自己的喜好调整和定制整个内容

希望这有帮助

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

/*
 * ------------------------------------------------------
 *  Define a custom error handler so we can log PHP errors
 * ------------------------------------------------------
 */
    set_error_handler('_error_handler');
    set_exception_handler('_exception_handler');
    register_shutdown_function('_shutdown_handler');
并在application/config/database.php中将此设置保留为FALSE,以便将数据库错误转换为异常

    restore_error_handler();
    restore_exception_handler();
CI有一些(非常)弱点,例如异常处理,但这将大大改善这一点


如果要使用事务,请确保对异常执行回滚。与此相关的是,从不(像以前一样)将持久性连接用作打开的事务,其他会话将拾取/继续其他会话特定的DB状态

如果查看CodeIgniter的代码,您将看到它在bot system/core和ci_system/core文件夹中的CodeIgniter.php中设置了自己的错误处理

    //Disable CodeIgniter error handling so we can use try catch blocks
    $errorHandlers = array();
    do {
        $errorHandler = set_error_handler(function() {}); //Get the current handler
        array_push($errorHandlers, $errorHandler); //Store the handler so that it can be restored if necessary
        for ($i = 0; $i < 2; $i++) { //We have to reset twice to get to the previous handler since we added a dummy handler
            restore_error_handler();
        }
    }
    while (!is_null($errorHandler)); //Is null when there are no handlers
    $exceptionHandlers = array(); //Do the same with exceptions
    do {
        $exceptionHandler = set_exception_handler(function() {});
        array_push($exceptionHandlers, $exceptionHandler);
        for ($i = 0; $i < 2; $i++) {
            restore_exception_handler();
        }
    }
    while (!is_null($exceptionHandler));

    try {
        //Your code goes here
    }
    catch (Error $e) {
        //Handle error
    }
    catch (Exception $e) {
        //Handle exception
    }

    //Restore all error handlers
    foreach ($errorHandlers as $errorHandler) {
        if (isset($errorHandler)) {
            set_error_handler($errorHandler);
        }
    }
    foreach ($exceptionHandlers as $exceptionHandler) {
        if (isset($exceptionHandler)) {
            set_exception_handler($exceptionHandler);
        }
    }
前两个函数处理错误处理。为了让您的try..catch块工作,您只需关闭此功能

使用和函数,我们可以将这些错误处理函数重置为默认值

$db['default']['db_debug'] = FALSE;
或者。。。如果要保留错误处理程序以在以后还原它们

//禁用CodeIgniter错误处理,以便我们可以使用try-catch块
$errorHandlers=array();
做{
$errorHandler=set_error_handler(function(){});//获取当前处理程序
array_push($errorHandlers,$errorHandler);//存储处理程序,以便在必要时可以还原它
对于($i=0;$i<2;$i++){//我们必须重置两次才能访问上一个处理程序,因为我们添加了一个虚拟处理程序
还原错误处理程序();
}
}
而(!is_null($errorHandler))//如果没有处理程序,则为null
$exceptionHandlers=array()//对例外情况也要这样做
做{
$exceptionHandler=设置异常处理程序(函数(){});
数组_push($exceptionHandler,$exceptionHandler);
对于($i=0;$i<2;$i++){
还原异常处理程序();
}
}
而(!is_null($exceptionHandler));
试一试{
//你的密码在这里
}
捕获(错误$e){
//处理错误
}
捕获(例外$e){
//处理异常
}
//还原所有错误处理程序
foreach($errorHandler作为$errorHandler){
if(isset($errorHandler)){
设置错误处理程序($errorHandler);
}
}
foreach($exceptionHandler作为$exceptionHandler){
if(isset($exceptionHandler)){
设置异常处理程序($exceptionHandler);
}
}
我们可以禁用所有自定义错误处理程序,并存储它们,以便在需要时进行恢复

我在保存和还原时使用循环,以防设置了其他错误处理程序。通过这种方式,您可以恢复所有错误处理程序,因为其他地方可能存在类似的代码,这些代码出于某些特定目的返回到以前的错误处理程序,并且将被保留


您能更具体地描述一下哪些不起作用吗?发生了什么而不是你期望的?也许$result不是假的?
    //Disable CodeIgniter error handling so we can use try catch blocks
    $errorHandlers = array();
    do {
        $errorHandler = set_error_handler(function() {}); //Get the current handler
        array_push($errorHandlers, $errorHandler); //Store the handler so that it can be restored if necessary
        for ($i = 0; $i < 2; $i++) { //We have to reset twice to get to the previous handler since we added a dummy handler
            restore_error_handler();
        }
    }
    while (!is_null($errorHandler)); //Is null when there are no handlers
    $exceptionHandlers = array(); //Do the same with exceptions
    do {
        $exceptionHandler = set_exception_handler(function() {});
        array_push($exceptionHandlers, $exceptionHandler);
        for ($i = 0; $i < 2; $i++) {
            restore_exception_handler();
        }
    }
    while (!is_null($exceptionHandler));

    try {
        //Your code goes here
    }
    catch (Error $e) {
        //Handle error
    }
    catch (Exception $e) {
        //Handle exception
    }

    //Restore all error handlers
    foreach ($errorHandlers as $errorHandler) {
        if (isset($errorHandler)) {
            set_error_handler($errorHandler);
        }
    }
    foreach ($exceptionHandlers as $exceptionHandler) {
        if (isset($exceptionHandler)) {
            set_exception_handler($exceptionHandler);
        }
    }
$db['default']['db_debug'] = FALSE;