【问题标题】:CodeIgniter - how to catch DB errors?CodeIgniter - 如何捕获数据库错误?
【发布时间】:2011-12-12 04:56:18
【问题描述】:

有没有办法让 CI 在遇到 DB 错误 时抛出 exception 而不是显示如下消息:

发生数据库错误错误号:1054 'where 子句' SELECT * FROM (FooBar) WHERE foo = '1' 中的未知列 'foo'

注意:我只希望这发生在一个控制器中。在其他控制器中,我很高兴它能够显示 DB 错误消息

【问题讨论】:

    标签: php codeigniter


    【解决方案1】:

    试试这些 CI 功能

    $this->db->_error_message(); (mysql_error equivalent)
    $this->db->_error_number(); (mysql_errno equivalent)
    

    CODEIGNITER 3 更新

    函数已弃用,请改用error()

    $this->db->error(); 
    

    【讨论】:

    • 当查询被动态创建时,$this->db->last_query() 也很有用。
    • 这些如何阻止消息显示?
    • 您必须在 config/database.php 中关闭数据库调试 -> $db['default']['db_debug'] = FALSE;
    • 为什么不能使用 Exception 代替 :-( ?
    • 这些方法已在 CodeIgniter 版本 3 中删除。请改用$this->db->error()。 (见codeigniter.com/user_guide/database/…
    【解决方案2】:

    在 sybase_driver.php 中

    /**
    * Manejador de Mensajes de Error Sybase
    * Autor: Isaí Moreno
    * Fecha: 06/Nov/2019
    */
    
    static  $CODE_ERROR_SYBASE;
    
    public static function SetCodeErrorSybase($Code) {
        if ($Code != 3621) {  /*No se toma en cuenta el código de command aborted*/
            CI_DB_sybase_driver::$CODE_ERROR_SYBASE = trim(CI_DB_sybase_driver::$CODE_ERROR_SYBASE.' '.$Code);       
        }
    }
    
    public static function GetCodeErrorSybase() {               
        return CI_DB_sybase_driver::$CODE_ERROR_SYBASE;
    }
    
    public static function msg_handler($msgnumber, $severity, $state, $line, $text)
    {       
        log_message('info', 'CI_DB_sybase_driver - CODE ERROR ['.$msgnumber.'] Mensaje - '.$text);
        CI_DB_sybase_driver::SetCodeErrorSybase($msgnumber);   
    }
    
    // ------------------------------------------------------------------------
    

    在同一个sybase_driver.php文件中添加和修改以下方法

    /**
     * The error message number
     *
     * @access  private
     * @return  integer
     */
    function _error_number()
    {
        // Are error numbers supported?
        return CI_DB_sybase_driver::GetCodeErrorSybase();
    }
    
    function _sybase_set_message_handler()
    {
        // Are error numbers supported?     
        return sybase_set_message_handler('CI_DB_sybase_driver::msg_handler');
    }
    

    实现控制器的功能。

    public function Eliminar_DUPLA(){       
        if($this->session->userdata($this->config->item('mycfg_session_object_name'))){     
            //***/
            $Operacion_Borrado_Exitosa=false;
            $this->db->trans_begin();
    
            $this->db->_sybase_set_message_handler();  <<<<<------- Activar Manejador de errores de sybase
            $Dupla_Eliminada=$this->Mi_Modelo->QUERY_Eliminar_Dupla($PARAMETROS);                   
    
            if ($Dupla_Eliminada){
                $this->db->trans_commit();
                MostrarNotificacion("Se eliminó DUPLA exitosamente","OK",true);
                $Operacion_Borrado_Exitosa=true;
            }else{
                $Error = $this->db->_error_number();  <<<<----- Obtengo el código de error de sybase para personilzar mensaje al usuario    
                $this->db->trans_rollback();                
                MostrarNotificacion("Ocurrio un error al intentar eliminar Dupla","Error",true);
                if ($Error == 547) {
                    MostrarNotificacion("<strong>Código de error :[".$Error.']. No se puede eliminar documento Padre.</strong>',"Error",true);
                }  else {                   
                    MostrarNotificacion("<strong>Código de Error :[".$Error.']</strong><br>',"Error",true);                 
                }
            }
    
            echo "@".Obtener_Contador_Notificaciones();
            if ($Operacion_Borrado_Exitosa){
                echo "@T";
            }else{
                echo "@F";
            }
        }else{
            redirect($this->router->default_controller);
        }
    
    }
    

    在日志中可以查看数据库服务器发送的代码和消息。

    INFO - 2019-11-06 19:26:33 -> CI_DB_sybase_driver - CODE ERROR [547] Message - Dependent foreign key constraint violation in a referential integrity constraint. dbname = 'database', table name = 'mitabla', constraint name = 'FK_SR_RELAC_REFERENCE_SR_mitabla'. INFO - 2019-11-06 19:26:33 -> CI_DB_sybase_driver - CODE ERROR [3621] Message - Command has been aborted. ERROR - 2019-11-06 19:26:33 -> Query error: - Invalid query: delete from mitabla where ID = 1019.
    

    【讨论】:

    • 这里是英文网站,请用英文回答!
    【解决方案3】:

    一个对我有用的例子:

    $query = "some buggy sql statement";
    
    $this->db->db_debug = false;
    
    if(!@$this->db->query($query))
    {
        $error = $this->db->error();
        // do something in error case
    }else{
        // do something in success case
    }
    ...
    

    最好的

    【讨论】:

      【解决方案4】:

      禁用错误调试。

          $data_user = $this->getDataUser();
          $id_user   = $this->getId_user();
      
          $this->db->db_debug = false;
          $this->db->where(['id' => $id_user]);
          $res = $this->db->update(self::$table, $data_user['user']);
      
          if(!$res)
          {
              $error = $this->db->error();
              return $error;
              //return array $error['code'] & $error['message']
          }
          else
          {
              return 1;
          }
      

      【讨论】:

        【解决方案5】:

        如果有人使用 PDO,除了以上所有答案。

        我如下所示静默记录我的错误

                $q = $this->db->conn_id->prepare($query);
        
                if($q instanceof PDOStatement) {
                   // go on with bind values and execute
        
                } else {
        
                  $dbError = $this->db->error();
                  $this->Logger_model->logError('Db Error', date('Y-m-d H:i:s'), __METHOD__.' Line '.__LINE__, 'Code: '.$dbError['code'].' -  '.'Message: '.$dbError['message']);
        
                }
        

        【讨论】:

          【解决方案6】:

          我为此创建了一个简单的库:

          <?php
          defined('BASEPATH') OR exit('No direct script access allowed');
          
          class exceptions {
          
              public function checkForError() {
                  get_instance()->load->database();
                  $error = get_instance()->db->error();
                  if ($error['code'])
                      throw new MySQLException($error);
              }
          }
          
          abstract class UserException extends Exception {
              public abstract function getUserMessage();
          }
          
          class MySQLException extends UserException {
              private $errorNumber;
              private $errorMessage;
          
              public function __construct(array $error) {
                  $this->errorNumber = "Error Code(" . $error['code'] . ")";
                  $this->errorMessage = $error['message'];
              }
          
              public function getUserMessage() {
                  return array(
                      "error" => array (
                          "code" => $this->errorNumber,
                          "message" => $this->errorMessage
                      )
                  );
              }
          
          }
          

          示例查询:

          function insertId($id){
              $data = array(
                  'id' => $id,
              );
          
              $this->db->insert('test', $data);
              $this->exceptions->checkForError();
              return $this->db->insert_id();
          }
          

          我可以在我的控制器中以这种方式捕捉它:

           try {
               $this->insertThings->insertId("1");
           } catch (UserException $error){
               //do whatever you want when there is an mysql error
          
           }
          

          【讨论】:

            【解决方案7】:

            在 Codeigniter 3.0 (CI3) 中,您只需$this-&gt;db-&gt;error()

            如果您需要获取最后发生的错误,error() 方法将返回一个包含其代码和消息的数组

            http://www.codeigniter.com/user_guide/database/queries.html#handling-errors

            【讨论】:

            • 谢谢!他们在 CI 2 -> 3 迁移指南中没有提到这一点!
            • 太棒了,你拯救了我的一天。从 CI 2 开始,我仍在这样做
            • Codeigniter 会暂停代码执行并在出现错误时输出错误消息,因此您将没有机会检查 $this->db->e​​rror。这个答案不正确。
            • @S.Imp - CodeIgniter 仅在 config/database.php 的 $db['default']['db_debug'] 为真时才停止执行。见stackoverflow.com/a/21073711/25507
            【解决方案8】:

            将此代码放在 application/core 文件夹中名为 MY_Exceptions.php 的文件中:

            <?php
            
            if (!defined('BASEPATH'))
                exit('No direct script access allowed');
            
            /**
             * Class dealing with errors as exceptions
             */
            class MY_Exceptions extends CI_Exceptions
            {
            
                /**
                 * Force exception throwing on erros
                 */
                public function show_error($heading, $message, $template = 'error_general', $status_code = 500)
                {
                    set_status_header($status_code);
            
                    $message = implode(" / ", (!is_array($message)) ? array($message) : $message);
            
                    throw new CiError($message);
                }
            
            }
            
            /**
             * Captured error from Code Igniter
             */
            class CiError extends Exception
            {
            
            }
            

            它将使所有 Code Igniter 错误都被视为异常 (CiError)。然后,打开所有数据库调试:

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

            【讨论】:

              【解决方案9】:

              我知道这个帖子很旧,但以防万一其他人遇到这个问题。这是我在不涉及 CI db 类的情况下使用的技巧。将调试保留在错误视图文件中,抛出异常。

              所以在你的数据库配置中,你有:

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

              然后在您的 db 错误视图文件中,我在 application/errors/error_db.php 中的所有内容替换为以下内容:

              <?php
              $message = preg_replace('/(<\/?p>)+/', ' ', $message);
              throw new Exception("Database error occured with message : {$message}");
              
              ?>
              

              由于会调用视图文件,错误总是会作为异常抛出,您可以稍后为不同的环境添加不同的视图。

              【讨论】:

                【解决方案10】:

                使用它

                    $this->db->_error_message(); 
                

                更好地发现错误。完成您的网站后。 关闭错误信息 使用它

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

                您将在配置文件夹的 database.php 中更改它

                【讨论】:

                  【解决方案11】:

                  您必须在 config/database.php 中关闭数据库调试 ->

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

                  这对您的网站安全性更好。

                  【讨论】:

                  • 你生活在平行世界吗?
                  • @jerinho.com 哈哈 :)
                  【解决方案12】:

                  也许是这样的:

                  $db_debug = $this->db->db_debug; //save setting
                  
                  $this->db->db_debug = FALSE; //disable debugging for queries
                  
                  $result = $this->db->query($sql); //run query
                  
                  //check for errors, etc
                  
                  $this->db->db_debug = $db_debug; //restore setting
                  

                  【讨论】:

                  • 这在为 psql 使用 pdo 驱动程序时很有帮助
                  • @RayJ 知道为什么 db_debug 'production' ENVIRONMENT 默认值 ('db_debug' =&gt; (ENVIRONMENT !== 'production') 在新下载的 CI v3 中设置为 FALSE?我看到将其设置为 false 将显示 db error 更多详细信息,这在生产中是不应该的,对吧?我很困惑。
                  • 首先我们需要回到主 index.php 文件,看看 ENVIRONMENT 是如何设置的以及为什么。 stackoverflow.com/questions/36051146/… 众所周知,这可以将其设置为任何值:define('ENVIRONMENT', 'development') :在开发时显示错误。 define('ENVIRONMENT', 'production') : 当网站上线时。所以行(在 database.php 配置中)说:'db_debug' => (ENVIRONMENT !== 'production'),或者如果“ENVIRONMENT”未设置为“production”,则将数据库调试模式设置为 TRUE。
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-08-31
                  • 2016-04-22
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-02-12
                  • 2019-11-12
                  相关资源
                  最近更新 更多