Is there a way to make CI throw an exception when it encounters a DB error instead of displaying a message like:
A Database Error Occurred Error Number: 1054 Unknown column 'foo' in 'where clause' SELECT * FROM (
FooBar
) WHEREfoo
= '1'
NOTE: I only want this to happen in one controller. In the other controllers, I'm happy for it to display the DB error messages.
Try these CI functions
$this->db->_error_message(); (mysql_error equivalent)
$this->db->_error_number(); (mysql_errno equivalent)
Maybe this:
$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
You must turn debug off for database in config/database.php ->
$db['default']['db_debug'] = FALSE;
It is better for your website security.
Use it
$this->db->_error_message();
It is better for finding error.After completing your site. Close the error messages using it
$db['default']['db_debug'] = FALSE;
You will change it in your config folder's database.php
I know this thread is old, but just in case there's someone else having this issue. This is a trick I used without touching the CI db classes. Leave your debug on and in your error view file, throw an exception.
So in you db config, you have :
$db['default']['db_debug'] = true;
Then in your db error view file, mine is in application/errors/error_db.php
replace all content with the following:
<?php
$message = preg_replace('/(<\/?p>)+/', ' ', $message);
throw new Exception("Database error occured with message : {$message}");
?>
Since the view file will be called, the error will always get thrown as an exception, you may later add different views for different environment.
In Codeigniter 3.0 (CI3), all you have to do is $this->db->error()
If you need to get the last error that has occured, the error() method will return an array containing its code and message
http://www.codeigniter.com/user_guide/database/queries.html#handling-errors
Put this code in a file called MY_Exceptions.php in application/core folder:
<?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
{
}
It will make all the Code Igniter errors to be treated as Exception (CiError). Then, turn all your database debug on:
$db['default']['db_debug'] = true;
I have created an simple library for that:
<?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
)
);
}
}
The example query:
function insertId($id){
$data = array(
'id' => $id,
);
$this->db->insert('test', $data);
$this->exceptions->checkForError();
return $this->db->insert_id();
}
And I can catch it this way in my controller:
try {
$this->insertThings->insertId("1");
} catch (UserException $error){
//do whatever you want when there is an mysql error
}
If one uses PDO, additional to all the answers above.
I log my errors silently as below
$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']);
}
Disable debugging of errors.
$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;
}
an example that worked for me:
$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
}
...
Best