2013-04-07 11 views
11

Ho un vincolo unique sulla colonna. Quando viene eseguito questo codice, ottengo il log degli errori dal framework ma non è ciò che ho dato nel blocco Exception.
Se esiste una colonna univoca, desidero interrogare la sua chiave primaria e impostarla come $id e tornare alla pagina. In questo momento si sta fermando su errore db e non andando in Catch block.
Ecco il mio codice:CodeIgniter: Try Catch non funziona nella classe del modello

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** che ricevo da quadro:

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

Non so che cosa è sbagliato con esso.

+0

Puoi fornire una descrizione più specifica di cosa esattamente non funziona? Cosa succede invece di ciò che ti aspetti? – miorel

+0

forse $ result non è falso? – jcorry

risposta

25

CI non ha un buon supporto per le eccezioni. Le query DB chiameranno qualche cosa di errore error_logging dell'elemento CI chiamato show_error(). Quello che devi fare è impostare correttamente la gestione delle eccezioni.

Fondamentalmente è possibile seguire l'intera ricetta.

Ora tutti gli errori del database generano automaticamente eccezioni. E come bonus hai una buona gestione delle eccezioni nell'intera applicazione CI.

Registrare un ErrorHandler personalizzato che trasforma gli errori PHP in eccezioni, per esempio mettere questo in cima alla vostra 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"); 

Pubblicare un gestore di eccezioni non intercettata, mettere qualcosa di simile nel tuo 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"); 

Impostare un gestore di terminazione:

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

Imposta un gestore di asser personalizzato che converte asserti in eccezioni, inserisci qualcosa di simile in 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'); 

utilizzare i wrapper come questo nel tuo controller

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

È possibile ottimizzare e personalizzare il tutto ai vostri gusti!

Spero che questo aiuti.

Sarà inoltre necessario intercettare il metodo show_error CI. Mettere questo in applicazione/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); 
    } 
} 

e lasciare in application/config/database.php questa impostazione su FALSE di avere errori del database convertiti in eccezioni.

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

CI ha alcuni (più) punti deboli, come gestione delle eccezioni, ma questo andrà un senso lungo correggere questo.

Se si intende utilizzare le transazioni, assicurarsi di eseguire rollback sulle eccezioni. In relazione a questo MAIUSCOLO (come in MAI), le connessioni persistenti come transazioni aperte e altri stati DB specifici della sessione verranno raccolti/continuati da altre sessioni.

0

Se il debug del database è attivato, gli errori dal DB verranno indirizzati alla classe principale Exceptions e exit() verrà chiamato dopo, il che significa che lo script non raggiungerà mai il tuo condizionale if.

Aprire application/config/database.php e provare a impostare db_debug su falso. Questa è una buona idea da fare per siti Web di produzione, in ogni caso, perché non si desidera alcun problema di query SQL per rilasciare informazioni sulla struttura del database.

Inoltre, non correlato, fare attenzione con $ all'interno di virgolette doppie, perché verrà analizzato come variabile (anche un gruppo di esse in una riga - sarà letteralmente una variabile variabile variabile variabile ...).

0

Cosa succede se si imposta il risultato all'esterno del blocco try? O un operatore ternario:

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

E 'difficile sapere senza sapere quale sia il valore di $result realmente è, come @jcorry detto.