PHP MySQL - Error trying to update record [duplicate] - php

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 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

Related

Data won't delete from table in MYSQL [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 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

Why can't I catch the error with PDOException?

Get info passed by POST method, and trim all space in the string, then start a new pdo instance, connect mysql, and insert info passed by POST into table.
$title = trim($_POST["title"]);
$content = trim($_POST["content"]);
$dsn = "mysql:host=localhost;dbname=blog";
$con = new PDO($dsn,"root","xxxx");
$title = $con->quote($title);
$content = $con->quote($content);
try
{
$sql = "insert into tmp (`title`,`content`) values('$title','$content')";
$stmt = $con->prepare($sql);
$stmt->execute();
}
catch(PDOException $e)
{
echo $e->getMessage();
}
The above is my PHP code to make the job done,the most import command is
insert into tmp (`title`,`content`) values('$title','$content')";
No error info is shown by running the above PHP code, and no error exists in /var/log/mysql/error.log, but info has not been inserted into the database.
I changed the
insert into tmp (`title`,`content`) values('$title','$content')";
into
insert into tmp (`title`,`content`) values($title,$content)";
The info passed by POST can be inserted into mysql now, the issue that confuses me is that:
echo $e->getMessage(); take no effect at all.
no error info in /var/log/mysql/error.log
How can I catch these errors?
The exception you are trying to catch will never be thrown, because you need to tell PDO how you want it to handle errors.
$con = new PDO($dsn,"root","xxxx");
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Otherwise, the default PDO::ERRMODE_SILENT will be used:
This is the default mode. PDO will simply set the error code for you to inspect using the PDO::errorCode() and PDO::errorInfo() methods on both the statement and database objects; if the error resulted from a call on a statement object, you would invoke the PDOStatement::errorCode() or PDOStatement::errorInfo() method on that object. If the error resulted from a call on the database object, you would invoke those methods on the database object instead.
Tangentially, you should be using prepared statements. You are using a prepare() call, but you are not parametrizing the query and binding the variables as you should. Using quote() is not secure enough.
2020 Update:
Interestingly, starting with PHP 8, the default behaviour for PDO will change and will throw exceptions by default. The change was voted on this RFC, which mentions:
The current default error mode for PDO is silent. This means that when an SQL error occurs, no errors or warnings may be emitted and no exceptions thrown unless the developer implements their own explicit error handling.
This causes issues for new developers because the only errors they often see from PDO code are knock-on errors such as “call to fetch() on non-object” - there's no indication that the SQL query (or other action) failed or why.
When PHP 8 is released on November 2020, the default error mode will be PDO::ERRMODE_EXCEPTION.

Mysqli update throwing Call to a member function bind_param() error [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 3 years ago.
I have a 70/80 field form that I need to insert into a table so instead of manually creating one huge insert statement I firstly have created a table in my db from the names of the inputs in the form here is the code that I use to create/alter the table
function createTable($array, $memberMysqli)
{
foreach ($array as $key => $value)
{
//echo "<p>Key: ".$key." => Value: ".$value . "</p>";
$query = "ALTER TABLE questionnaire ADD ".$key." text";
if($stmt = $memberMysqli->prepare($query))
{
$success = $stmt->execute();
}
}
echo "<h1>Array count: ". count($array) ."</h1>" ;
}
This works fine and altered the table exactly how I wanted it. Now to insert the form values to do this I do a basic one field insert store the id of the row and then have loop all the post variables updating that row. Here is my code for that:
$stmt = $memberMysqli->prepare("INSERT INTO questionnaire(userid) VALUES (?)");
$stmt->bind_param('s', $_POST['userid']);
$stmt->execute();
$rowid = $stmt->insert_id;
$stmt->close();
$memberMysqli->autocommit(FALSE);
function updateColumn($memberMysqli, $query, $uid, $value)
{
if ($value)
{
$stmt = $memberMysqli->prepare($query);
//Throws bind param error here
$stmt->bind_param("ss", $value, $uid);
$stmt->execute();
}
}
function loopInputs($array, $memberMysqli, $rowid)
{
foreach ($array as $key => $formvalue)
{
var_dump($key);
updateColumn($memberMysqli, "UPDATE questionnaire SET $key = ? WHERE id = ?", $rowid, $formvalue);
}
}
loopInputs($_POST, $memberMysqli, $rowid);
$memberMysqli->commit();
$memberMysqli->close();
This throws a bind param error and I have no idea why.
O, let's try a canonical answer.
Call to a member function (or expects parameter 1 to be mysqli_result, boolean given for the procedural style) is not an error itself but just a symptom, for some other problem.
This very error message means that no object was created where should.
So - there was a problem with creating an $stmt object.
Most likely it's a problem with the query.
So, we need to track that error down.
Mysqli won't tell you what's going on unless asked explicitly. So, you have to always check the result of every mysqli function interacting with server and if result is FALSE - check $mysqli->error.
It is also very important to convert mysqli error message into PHP error, to let it go according site-wide error reporting settings.
If you are using mysqli_query() all over the application code without encapsulating it into some helper class, trigger_error() is a good way to raise a PHP error, as it will tell you also the file and the line number where error occurred
So, all your prepare(), execute() and query() calls have to be written this way:
$stmt = $mysqli->prepare($query) or trigger_error($mysqli->error."[$query]");
or in procedural style
$res = mysqli_query($mysqli,$query) or trigger_error(mysqli_error($mysqli)."[$query]");
in all your scripts
and since then you will be notified of the reason, why the object weren't created.
(If you're curious of this or syntax, I've explained it here)
Note that query also included in the error message, to let you inspect it visually and test in another environment.
However, if you're encapsulating your query into some class, file and line from trigger error will be quite useless as they will point to the call itself, not the application code that caused certain problem. So, when running mysqli commands encapsulated, another way have to be used:
$result = $mysqli->query($sql);
if (!$result) {
throw new Exception($mysqli->error." [$query]");
}
as Exception will provide you with a stack trace, which will lead you the the place from which an erroneous query were called.
Note that you have to be able to see PHP errors in general. On a live site you have to peek into error logs, so, settings have to be
error_reporting(E_ALL);
ini_set('display_errors',0);
ini_set('log_errors',1);
while on a local development server it's all right to make errors on screen:
error_reporting(E_ALL);
ini_set('display_errors',1);
and of course you should never ever use error suppression operator (#) in front of your statements.

mysqli - handling errors with transactions [duplicate]

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

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