【发布时间】:2011-12-12 04:56:18
【问题描述】:
有没有办法让 CI 在遇到 DB 错误 时抛出 exception 而不是显示如下消息:
发生数据库错误错误号:1054 'where 子句' SELECT * FROM (
FooBar) WHEREfoo= '1' 中的未知列 'foo'
注意:我只希望这发生在一个控制器中。在其他控制器中,我很高兴它能够显示 DB 错误消息。
【问题讨论】:
标签: php codeigniter
有没有办法让 CI 在遇到 DB 错误 时抛出 exception 而不是显示如下消息:
发生数据库错误错误号:1054 'where 子句' SELECT * FROM (
FooBar) WHEREfoo= '1' 中的未知列 'foo'
注意:我只希望这发生在一个控制器中。在其他控制器中,我很高兴它能够显示 DB 错误消息。
【问题讨论】:
标签: php codeigniter
试试这些 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() 也很有用。
$this->db->error()。 (见codeigniter.com/user_guide/database/…)
在 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.
【讨论】:
一个对我有用的例子:
$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
}
...
最好的
【讨论】:
禁用错误调试。
$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;
}
【讨论】:
如果有人使用 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']);
}
【讨论】:
我为此创建了一个简单的库:
<?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
}
【讨论】:
在 Codeigniter 3.0 (CI3) 中,您只需$this->db->error()
如果您需要获取最后发生的错误,error() 方法将返回一个包含其代码和消息的数组
http://www.codeigniter.com/user_guide/database/queries.html#handling-errors
【讨论】:
$db['default']['db_debug'] 为真时才停止执行。见stackoverflow.com/a/21073711/25507。
将此代码放在 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;
【讨论】:
我知道这个帖子很旧,但以防万一其他人遇到这个问题。这是我在不涉及 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}");
?>
由于会调用视图文件,错误总是会作为异常抛出,您可以稍后为不同的环境添加不同的视图。
【讨论】:
使用它
$this->db->_error_message();
更好地发现错误。完成您的网站后。 关闭错误信息 使用它
$db['default']['db_debug'] = FALSE;
您将在配置文件夹的 database.php 中更改它
【讨论】:
您必须在 config/database.php 中关闭数据库调试 ->
$db['default']['db_debug'] = FALSE;
这对您的网站安全性更好。
【讨论】:
也许是这样的:
$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
【讨论】:
'db_debug' => (ENVIRONMENT !== 'production') 在新下载的 CI v3 中设置为 FALSE?我看到将其设置为 false 将显示 db error 更多详细信息,这在生产中是不应该的,对吧?我很困惑。