Db exception handling in php - php

So I have a class for each table in a database. Now I want to create the table in the database if it doesn't exist yet.
try {
$result = r\db($this->databaseName);
$result = $result->tableCreate($this->tableName);
$result = $result->run($manager);
} catch (\Exception $e) {
echo $e->getMessage();
//throw new \Exception("Error: $e");
}
This echo's:
Runtime error: Table `customers` already exists.
What would be a proper way to catch this specific error and resume the program, but still being able to catch other errors.

Related

PHP try/catch error

I have a PHP psql query. I am doing try catch to prevent Duplicates. When I ran the script I can see it's inserting something into my DB. But when I check my DB it's empty.
foreach($data as $n){
$query = $psql->pdo_prepared("INSERT INTO students(id,email,address,phone)VALUES".myFunction($array);
}
and I have a PHP class to handle the exception:
public function pdo_prepared($query,array){
try{
// some logic
}
catch(EXCEPTION $e){
//empty
}
}
The reason why I am doing try catch is to catch duplicates and ignore it. If I throw an exception in my catch block my insert statement won't execute because my current data contains duplicates.

How do I ensure all exceptions in this DB transaction are caught?

I use Yii and recently started using Transactions with try / catch blocks.
Here's how the code looks right now:
$dbConnection = Yii::app()->db();
try {
$transaction = $dbConnection->beginTransaction();
$dbConnection->createCommand("SELECT * from table_1")
->queryAll();
$transaction->commit();
} catch (Exception $ex) {
$transaction->rollback();
}
Suppose there's an exception with the DB (it's come up while unit-testing), I'm unable to rollback because the PHP dies with a fatal $transaction undefined error.
I'd rather not include isset() checks everywhere..
Is there a simpler way to make this work?
You can check if the exception is an instance of CDbException
$dbConnection = Yii::app()->db();
try {
$transaction = $dbConnection->beginTransaction();
$dbConnection->createCommand("SELECT * from table_1")
->queryAll();
$transaction->commit();
} catch (Exception $ex) {
if ($ex instanceof CDbException)
{
// handle CDBException
// ...
}
$transaction->rollback();
}

Catch a foreign key error in php

How to catch
Cannot delete or update a parent row: a foreign key constraint fails
Error
I want to show a message to users that they cannot delete this row when they delete
try
{
$success=$db->query("DELETE FROM tableName WHERE ID=1");
}
catch (Exception $e)
{
echo "You cannot delete this row";
}
Check value of success and proceed:
try {
$success = $db->query("DELETE FROM tableName WHERE ID=1");
if(!$success) {
$error = "You cannot delete this row";
throw new Exception($error);
}
} catch (Exception $e) {
echo $e->getMessage();
}
Check return of query; if false query for specific DB error number and/or message. Then take appropriate action. Something like this - Is there any way to catch MySQL and database errors in PHP?
Or if you are running PDO, catch specific PDOException and query for the DB error.
The above should be enough to get you started.

joomla exception handling with DB error

Trying to do exception handling and logging. So if I have something like this:
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('*')
$query->from('#__users');
try
{
$db->setQuery($query);
$result = $db->loadResult();
}
catch (RuntimeException $e)
{
$e->getMessage();
JLog::add('This query failed: '.$query);
}
My question is how best to test my exception code? Taking down the DB will just get Joomla to output this error and I never get into my exception code:
Database connection error (2): Could not connect to MySQL.
I want to be able to verify the exception and log get printed.
This is how I do it. First initialise loggers in entry point file:
JLog::addLogger(
array('text_file' => 'com_mycom.php'),
JLog::ALL ^ JLog::ERROR,
'com_mycom'
);
JLog::addLogger(
array('text_file' => 'com_mycom.errors.php'),
JLog::ERROR,
'com_mycom'
);
Then use it in models:
try
{
$rows = $this->_db->loadObjectList();
}
catch (Exception $e)
{
JLog::add($e->getMessage(), JLog::ERROR, 'com_mycom');
return false;
}
Try adding a throw statement in the try part of your try/catch section.

PHP Try and Catch for SQL Insert

I have a page on my website (high traffic) that does an insert on every page load.
I am curious of the fastest and safest way to (catch an error) and continue if the system is not able to do the insert into MySQL. Should I use try/catch or die or something else. I want to make sure the insert happens but if for some reason it can't I want the page to continue to load anyway.
...
$db = mysql_select_db('mobile', $conn);
mysql_query("INSERT INTO redirects SET ua_string = '$ua_string'") or die('Error #10');
mysql_close($conn);
...
Checking the documentation shows that its returns false on an error. So use the return status rather than or die(). It will return false if it fails, which you can log (or whatever you want to do) and then continue.
$rv = mysql_query("INSERT INTO redirects SET ua_string = '$ua_string'");
if ( $rv === false ){
//handle the error here
}
//page continues loading
This can do the trick,
function createLog($data){
$file = "Your path/incompletejobs.txt";
$fh = fopen($file, 'a') or die("can't open file");
fwrite($fh,$data);
fclose($fh);
}
$qry="INSERT INTO redirects SET ua_string = '$ua_string'"
$result=mysql_query($qry);
if(!$result){
createLog(mysql_error());
}
You can implement throwing exceptions on mysql query fail on your own. What you need is to write a wrapper for mysql_query function, e.g.:
// user defined. corresponding MySQL errno for duplicate key entry
const MYSQL_DUPLICATE_KEY_ENTRY = 1022;
// user defined MySQL exceptions
class MySQLException extends Exception {}
class MySQLDuplicateKeyException extends MySQLException {}
function my_mysql_query($query, $conn=false) {
$res = mysql_query($query, $conn);
if (!$res) {
$errno = mysql_errno($conn);
$error = mysql_error($conn);
switch ($errno) {
case MYSQL_DUPLICATE_KEY_ENTRY:
throw new MySQLDuplicateKeyException($error, $errno);
break;
default:
throw MySQLException($error, $errno);
break;
}
}
// ...
// doing something
// ...
if ($something_is_wrong) {
throw new Exception("Logic exception while performing query result processing");
}
}
try {
mysql_query("INSERT INTO redirects SET ua_string = '$ua_string'")
}
catch (MySQLDuplicateKeyException $e) {
// duplicate entry exception
$e->getMessage();
}
catch (MySQLException $e) {
// other mysql exception (not duplicate key entry)
$e->getMessage();
}
catch (Exception $e) {
// not a MySQL exception
$e->getMessage();
}
if you want to log the error etc you should use try/catch, if you dont; just put # before mysql_query
edit :
you can use try catch like this; so you can log the error and let the page continue to load
function throw_ex($er){
throw new Exception($er);
}
try {
mysql_connect(localhost,'user','pass');
mysql_select_db('test');
$q = mysql_query('select * from asdasda') or throw_ex(mysql_error());
}
catch(exception $e) {
echo "ex: ".$e;
}
Elaborating on yasaluyari's answer I would stick with something like this:
We can just modify our mysql_query as follows:
function mysql_catchquery($query,$emsg='Error submitting the query'){
if ($result=mysql_query($query)) return $result;
else throw new Exception($emsg);
}
Now we can simply use it like this, some good example:
try {
mysql_catchquery('CREATE TEMPORARY TABLE a (ID int(6))');
mysql_catchquery('insert into a values(666),(418),(93)');
mysql_catchquery('insert into b(ID, name) select a.ID, c.name from a join c on a.ID=c.ID');
$result=mysql_catchquery('select * from d where ID=7777777');
while ($tmp=mysql_fetch_assoc($result)) { ... }
} catch (Exception $e) {
echo $e->getMessage();
}
Note how beautiful it is. Whenever any of the qq fails we gtfo with our errors. And you can also note that we don't need now to store the state of the writing queries into a $result variable for verification, because our function now handles it by itself. And the same way it handles the selects, it just assigns the result to a variable as does the normal function, yet handles the errors within itself.
Also note, we don't need to show the actual errors since they bear huge security risk, especially so with this outdated extension. That is why our default will be just fine most of the time. Yet, if we do want to notify the user for some particular query error, we can always pass the second parameter to display our custom error message.
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
I am not sure if there is a mysql version of this but adding this line of code allows throwing mysqli_sql_exception.
I know, passed a lot of time and the question is already checked answered but I got a different answer and it may be helpful.
$sql = "INSERT INTO customer(FIELDS)VALUES(VALUES)";
mysql_query($sql);
if (mysql_errno())
{
echo "<script>alert('License already registered');location.replace('customerform.html');</script>";
}
To catch specific error in Mysqli
$conn = ...;
$q = "INSERT INTO redirects (ua_string) VALUES ('$ua_string')";
if (mysqli_query($conn, $q)) {
// Successful
}
else {
die('Mysqli Error: '.$conn->error); // Show Error Complete Description
}
mysqli_close($conn);
Use any method described in the previous post to somehow catch the mysql error.
Most common is:
$res = mysql_query('bla');
if ($res===false) {
//error
die();
}
//normal page
This would also work:
function error() {
//error
die()
}
$res = mysql_query('bla') or error();
//normal page
try { ... } catch {Exception $e) { .... } will not work!
Note: Not directly related to you question but I think it would much more better if you display something usefull to the user. I would never revisit a website that just displays a blank screen or any mysterious error message.
$new_user = new User($user);
$mapper = $this->spot->mapper("App\User");
try{
$id = $mapper->save($new_user);
}catch(Exception $exception){
$data["error"] = true;
$data["message"] = "Error while insertion. Erron in the query";
$data["data"] = $exception->getMessage();
return $response->withStatus(409)
->withHeader("Content-Type", "application/json")
->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
}
if error occurs, you will get something like this->
{
"error": true,
"message": "Error while insertion. Erron in the query",
"data": "An exception occurred while executing 'INSERT INTO \"user\" (...) VALUES (...)' with params [...]:\n\nSQLSTATE[22P02]: Invalid text representation: 7 ERROR: invalid input syntax for integer: \"default\"" }
with status code:409.

Categories