2013-04-07 87 views
11

我對該列有一個unique約束。當這段代碼運行時,我從框架中獲得錯誤日誌,但它不是我在Exception塊中給出的。
如果存在唯一列,那麼我想查詢它的主鍵並將其設置爲$id並返回到頁面。現在它正在停止數據庫錯誤,不會進入Catch block
這裏是我的代碼:CodeIgniter:Try Catch在模型類中不起作用

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

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

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

我不知道什麼是錯的。

+0

你能給出一個更具體的描述什麼是不工作?會發生什麼,而不是你所期望的? – miorel 2013-04-07 02:54:38

+0

也許$結果是不是錯誤? – jcorry 2013-04-07 02:58:27

回答

25

CI對異常沒有很好的支持。您的數據庫查詢將調用一些模糊的CI error_logging thingie,名爲show_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"); 

註冊未捕獲的異常處理程序的頂部,把這樣的事情在你的配置/配置.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:

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

使用包裝像這樣在你的控制器

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方法。把這個應用程序/核心/ 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); 
    } 
} 

而在應用/配置/ database.php中離開FALSE此設置可以轉化爲異常的數據庫錯誤。

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

CI有一些(非常)弱點,例如異常處理,但是這將對糾正這種情況有很大的幫助。

如果您要使用事務,請確保您對異常進行回滾。與此無關(如在EVER中)使用持久連接作爲開放式事務和其他會話特定的DB狀態將被其他會話拾取/繼續。

0

如果打開數據庫調試,來自數據庫的錯誤將被路由到例外核心類,並調用exit(),這意味着腳本永遠不會達到您的if條件。

打開application/config/database.php並嘗試將db_debug設置爲false。無論如何,這對於製作網站來說是個好主意,因爲您不希望任何SQL查詢問題發佈關於您的數據庫結構的信息。

另外,無關,在雙引號內使用$時要小心,因爲它會被解析爲一個變量(即使它們在一行中一堆 - 它實際上是一個變量變量變量變量......) )。

0

如果將結果設置在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; 
} 

很難知道不知道什麼$result價值真的是像@jcorry說。