mysqli - handling errors with transactions [duplicate] - php

This question already has answers here:
How to start and end transaction in mysqli?
(5 answers)
Closed 1 year ago.
How to properly handle errors with transactions and prepared statements when using mysqli?
Snippet:
<?php
$conn = require_once 'dbconn.php';
$conn->autocommit(FALSE);
$stmt_ins_option = $conn->prepare('INSERT INTO options(option_name) VALUES(?)');
$option_name = 'foo';
$stmt_ins_option->bind_param('s', $option_name);
$stmt_ins_option->execute();
$conn->commit();
if($conn->errno) {
$conn->rollback();
echo $conn->error;
}
It won't add it a second time because there's a UNIQUE constraint on that column.
However the script won't report any error either.
What am I missing?

execute returns false on failure, so you may want to check it before committing. Also, rolling back in your code has no effect because you committed transaction previously. I'd write something like
try
{
....
if (!$stmt_ins_option->execute())
{
throw new Exception("Cannot insert record. Reason :".$stmt_ins_option->error);
// surely, it's better to define your own exception hierarchy
}
$conn->commit();
}
catch (Exception $e)
{
$conn->rollback();
// display error/re-raise/ or whatever you think makes sense for your function
}

Is there any way to make mysqli classes throw exceptions instead of me having to check for errors every time
According to this answer you can use the following call to enable exceptions for such errors:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
See mysqli_driver::$report_mode

Related

data from my form refused to be saved to database php [duplicate]

This question already has an answer here:
What to do with mysqli problems? Errors like mysqli_fetch_array(): Argument #1 must be of type mysqli_result and such
(1 answer)
Closed 2 years ago.
I'm trying to turn MySQLi query errors to Exceptions, but couldn't - mysqli_sql_exception is thrown only if it failed to connect the DB.
I used mysqli_report(MYSQLI_REPORT_STRICT) and procedural MySQLi functions embedded to custom wrapper class.
Former code:
public function mysqlQuery($SQL) {
$this->Result = mysqli_query($this->DBlink, $SQL);
if($this->Result === false)
throw new MySQLiQueryException($SQL, mysqli_error($this->DBlink), mysqli_errno($this->DBlink));
return $this->Result;
}
Question: Is it normal no Warning, nor Exception are thrown when query fails so I have to check if mysqli_query() returned false?
Some time ago I managed to sort this matter out. As it was pointed out in the other answer,
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
is a correct way to tell mysqli to throw exceptions.
Just make sure you don't wrap every query in a try-catch. This is a very common misconception that as soon as you started using exceptions you should start throwing tries and catches left and right. Quite contrary, try-catch should be used warily. While 99% of your errors shouldn't be handled in place, but rather by a site-wide error handler. You may read more on the topic from my article on PHP error reporting
do I have to check if mysqli_query() returned false?
No.
You should be able to do what you require and instruct the mysqli driver to throw exceptions on SQL errors, but you will need to enable MYSQLI_REPORT_ERROR if it is not already....
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT)
mysqli_query() should now throw exceptions on error. You do not need to check the return value for failure (which won't happen anyway because an exception is thrown).
public function mysqlQuery($SQL) {
try {
$this->Result = mysqli_query($this->DBlink, $SQL);
} catch (mysqli_sql_exception $e) {
throw new MySQLiQueryException($SQL, $e->getMessage(), $e->getCode());
}
return $this->Result;
}
(NB: I changed $this->SQL to $SQL in the re-thrown exception.)
I know it's a little too late, but for the sake of posterity. I find MYSQLI_REPORT_STRICT to be to restrictive, certain exceptions where not be raised and hence they could not be handled by the catch block.
mysqli_report(MYSQLI_REPORT_ALL); // Traps all mysqli error
try {
$mysqli = new mysqli('localhost','user,'pwd','db');
/* I don't need to explicitly throw an exception as this is being
done automatically */
} catch(Exception $e) {
echo $e->getMessage();
}

mysqli_commit() is called instead of mysqli_rollback() in prepared statement [duplicate]

This question already has an answer here:
What to do with mysqli problems? Errors like mysqli_fetch_array(): Argument #1 must be of type mysqli_result and such
(1 answer)
Closed 2 years ago.
I'm trying to turn MySQLi query errors to Exceptions, but couldn't - mysqli_sql_exception is thrown only if it failed to connect the DB.
I used mysqli_report(MYSQLI_REPORT_STRICT) and procedural MySQLi functions embedded to custom wrapper class.
Former code:
public function mysqlQuery($SQL) {
$this->Result = mysqli_query($this->DBlink, $SQL);
if($this->Result === false)
throw new MySQLiQueryException($SQL, mysqli_error($this->DBlink), mysqli_errno($this->DBlink));
return $this->Result;
}
Question: Is it normal no Warning, nor Exception are thrown when query fails so I have to check if mysqli_query() returned false?
Some time ago I managed to sort this matter out. As it was pointed out in the other answer,
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
is a correct way to tell mysqli to throw exceptions.
Just make sure you don't wrap every query in a try-catch. This is a very common misconception that as soon as you started using exceptions you should start throwing tries and catches left and right. Quite contrary, try-catch should be used warily. While 99% of your errors shouldn't be handled in place, but rather by a site-wide error handler. You may read more on the topic from my article on PHP error reporting
do I have to check if mysqli_query() returned false?
No.
You should be able to do what you require and instruct the mysqli driver to throw exceptions on SQL errors, but you will need to enable MYSQLI_REPORT_ERROR if it is not already....
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT)
mysqli_query() should now throw exceptions on error. You do not need to check the return value for failure (which won't happen anyway because an exception is thrown).
public function mysqlQuery($SQL) {
try {
$this->Result = mysqli_query($this->DBlink, $SQL);
} catch (mysqli_sql_exception $e) {
throw new MySQLiQueryException($SQL, $e->getMessage(), $e->getCode());
}
return $this->Result;
}
(NB: I changed $this->SQL to $SQL in the re-thrown exception.)
I know it's a little too late, but for the sake of posterity. I find MYSQLI_REPORT_STRICT to be to restrictive, certain exceptions where not be raised and hence they could not be handled by the catch block.
mysqli_report(MYSQLI_REPORT_ALL); // Traps all mysqli error
try {
$mysqli = new mysqli('localhost','user,'pwd','db');
/* I don't need to explicitly throw an exception as this is being
done automatically */
} catch(Exception $e) {
echo $e->getMessage();
}

UPDATE statement not working when executed [duplicate]

This question already has answers here:
What to do with mysqli problems? Errors like mysqli_fetch_array(): Argument #1 must be of type mysqli_result and such
(2 answers)
Closed 2 years ago.
I'm trying to turn MySQLi query errors to Exceptions, but couldn't - mysqli_sql_exception is thrown only if it failed to connect the DB.
I used mysqli_report(MYSQLI_REPORT_STRICT) and procedural MySQLi functions embedded to custom wrapper class.
Former code:
public function mysqlQuery($SQL) {
$this->Result = mysqli_query($this->DBlink, $SQL);
if($this->Result === false)
throw new MySQLiQueryException($SQL, mysqli_error($this->DBlink), mysqli_errno($this->DBlink));
return $this->Result;
}
Question: Is it normal no Warning, nor Exception are thrown when query fails so I have to check if mysqli_query() returned false?
Some time ago I managed to sort this matter out. As it was pointed out in the other answer,
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
is a correct way to tell mysqli to throw exceptions.
Just make sure you don't wrap every query in a try-catch. This is a very common misconception that as soon as you started using exceptions you should start throwing tries and catches left and right. Quite contrary, try-catch should be used warily. While 99% of your errors shouldn't be handled in place, but rather by a site-wide error handler. You may read more on the topic from my article on PHP error reporting
do I have to check if mysqli_query() returned false?
No.
You should be able to do what you require and instruct the mysqli driver to throw exceptions on SQL errors, but you will need to enable MYSQLI_REPORT_ERROR if it is not already....
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT)
mysqli_query() should now throw exceptions on error. You do not need to check the return value for failure (which won't happen anyway because an exception is thrown).
public function mysqlQuery($SQL) {
try {
$this->Result = mysqli_query($this->DBlink, $SQL);
} catch (mysqli_sql_exception $e) {
throw new MySQLiQueryException($SQL, $e->getMessage(), $e->getCode());
}
return $this->Result;
}
(NB: I changed $this->SQL to $SQL in the re-thrown exception.)
I know it's a little too late, but for the sake of posterity. I find MYSQLI_REPORT_STRICT to be to restrictive, certain exceptions where not be raised and hence they could not be handled by the catch block.
mysqli_report(MYSQLI_REPORT_ALL); // Traps all mysqli error
try {
$mysqli = new mysqli('localhost','user,'pwd','db');
/* I don't need to explicitly throw an exception as this is being
done automatically */
} catch(Exception $e) {
echo $e->getMessage();
}

Turning query errors to Exceptions in MySQLi [duplicate]

This question already has answers here:
What to do with mysqli problems? Errors like mysqli_fetch_array(): Argument #1 must be of type mysqli_result and such
(2 answers)
Closed 2 years ago.
I'm trying to turn MySQLi query errors to Exceptions, but couldn't - mysqli_sql_exception is thrown only if it failed to connect the DB.
I used mysqli_report(MYSQLI_REPORT_STRICT) and procedural MySQLi functions embedded to custom wrapper class.
Former code:
public function mysqlQuery($SQL) {
$this->Result = mysqli_query($this->DBlink, $SQL);
if($this->Result === false)
throw new MySQLiQueryException($SQL, mysqli_error($this->DBlink), mysqli_errno($this->DBlink));
return $this->Result;
}
Question: Is it normal no Warning, nor Exception are thrown when query fails so I have to check if mysqli_query() returned false?
Some time ago I managed to sort this matter out. As it was pointed out in the other answer,
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
is a correct way to tell mysqli to throw exceptions.
Just make sure you don't wrap every query in a try-catch. This is a very common misconception that as soon as you started using exceptions you should start throwing tries and catches left and right. Quite contrary, try-catch should be used warily. While 99% of your errors shouldn't be handled in place, but rather by a site-wide error handler. You may read more on the topic from my article on PHP error reporting
do I have to check if mysqli_query() returned false?
No.
You should be able to do what you require and instruct the mysqli driver to throw exceptions on SQL errors, but you will need to enable MYSQLI_REPORT_ERROR if it is not already....
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT)
mysqli_query() should now throw exceptions on error. You do not need to check the return value for failure (which won't happen anyway because an exception is thrown).
public function mysqlQuery($SQL) {
try {
$this->Result = mysqli_query($this->DBlink, $SQL);
} catch (mysqli_sql_exception $e) {
throw new MySQLiQueryException($SQL, $e->getMessage(), $e->getCode());
}
return $this->Result;
}
(NB: I changed $this->SQL to $SQL in the re-thrown exception.)
I know it's a little too late, but for the sake of posterity. I find MYSQLI_REPORT_STRICT to be to restrictive, certain exceptions where not be raised and hence they could not be handled by the catch block.
mysqli_report(MYSQLI_REPORT_ALL); // Traps all mysqli error
try {
$mysqli = new mysqli('localhost','user,'pwd','db');
/* I don't need to explicitly throw an exception as this is being
done automatically */
} catch(Exception $e) {
echo $e->getMessage();
}

MySQLi prepared statements error reporting [duplicate]

This question already has answers here:
What to do with mysqli problems? Errors like mysqli_fetch_array(): Argument #1 must be of type mysqli_result and such
(2 answers)
Closed 5 years ago.
I'm trying to get my head around MySQli and I'm confused by the error reporting.
I am using the return value of the MySQLi 'prepare' statement to detect errors when executing SQL, like this:
$stmt_test = $mysqliDatabaseConnection->stmt_init();
if($stmt_test->prepare("INSERT INTO testtable VALUES (23,44,56)"))
{
$stmt_test->execute();
$stmt_test->close();
}
else echo("Statement failed: ". $stmt_test->error . "<br>");
But, is the return value of the prepare statement only detecting if there is an error in the preperation of the SQL statement and not detecting execution errors? If so should I therefore change my execute line to flag errors as well like this:
if($stmt_test->execute()) $errorflag=true;
And then just to be safe should I also do the following after the statement has executed:
if($stmt_test->errno) {$errorflag=true;}
...Or was I OK to start with and the return value on the MySQLi prepare' statement captures all errors associated with the complete execution of the query it defines?
Thanks
C
Each method of mysqli can fail. Luckily, nowadays mysqli can report every problem to you, all you need is ask. Simply add this single line to the connection code,
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
And after that every error will reveal itself. No need to test any return values ever, just write your statements right away:
$stmt = $mysqli->prepare("INSERT INTO testtable VALUES (?,?,?)");
$stmt->bind_param('iii', $x, $y, $z);
$stmt->execute();
When the error occurs at any step, it will throw a usual PHP Exception that can be handled or just reported the same way as any other PHP error. Just make sure you configured PHP error reporting properly, i.e. on the dev server errors are displayed on-screen and on the production server errors are never displayed but logged instead.
Completeness
You need to check both $mysqli and $statement. If they are false, you need to output $mysqli->error or $statement->error respectively.
Efficiency
For simple scripts that may terminate, I use simple one-liners that trigger a PHP error with the message. For a more complex application, an error warning system should be activated instead, for example by throwing an exception.
Usage example 1: Simple script
# This is in a simple command line script
$mysqli = new mysqli('localhost', 'buzUser', 'buzPassword');
$q = "UPDATE foo SET bar=1";
($statement = $mysqli->prepare($q)) or trigger_error($mysqli->error, E_USER_ERROR);
$statement->execute() or trigger_error($statement->error, E_USER_ERROR);
Usage example 2: Application
# This is part of an application
class FuzDatabaseException extends Exception {
}
class Foo {
public $mysqli;
public function __construct(mysqli $mysqli) {
$this->mysqli = $mysqli;
}
public function updateBar() {
$q = "UPDATE foo SET bar=1";
$statement = $this->mysqli->prepare($q);
if (!$statement) {
throw new FuzDatabaseException($mysqli->error);
}
if (!$statement->execute()) {
throw new FuzDatabaseException($statement->error);
}
}
}
$foo = new Foo(new mysqli('localhost','buzUser','buzPassword'));
try {
$foo->updateBar();
} catch (FuzDatabaseException $e)
$msg = $e->getMessage();
// Now send warning emails, write log
}
Not sure if this answers your question or not. Sorry if not
To get the error reported from the mysql database about your query you need to use your connection object as the focus.
so:
echo $mysqliDatabaseConnection->error
would echo the error being sent from mysql about your query.
Hope that helps

Categories