"Commands out of sync;" Prepared Stored Procedure Error - php

I seem to be having some trouble with running a 2nd prepared query after running a 1st prepared stored procedure. I understand this is because I can't buffer results in mySQL, but I'm not sure exactly I should be using to get all the results.
I've tried:
$stmt->store_result();
$stmt->fetch();
$stmt->bind_result($var1, $var2);
$stmt->free_result();
But I still get the same error. The procedure works fine, and is designed to only return 1 row, so not sure.
The full error is:
Commands out of sync; you can't run this command now
UPDATE:
More relevant code:
$stmt = $mysqli->prepare('CALL createNewListing(?,?,?,?,?,?)');
$time = time();
$stmt->bind_param('sdssii', $listing['title'], $listing['price'], $_SESSION['user']['id'], $listing['description'], $time, $listing['featured']);
$stmt->execute();
$stmt->store_result();
$stmt->fetch();
$stmt->bind_result($listing['primarypic']['id'], $listing['id']);
$stmt->free_result();
$stmt->close();
// Error is generated here.
$statement = $mysqli->prepare('INSERT INTO pictures (listid, primarypic) VALUES (?, ?)');
if (!$statement) {
echo $mysqli->error;
die();
}

Related

MySQL Query not returning a row value in PHP

I don't know why this query won't return a value because when I copy the "echoed" portion into phpmyadmin I do get a record returning:
echo $_GET["cname"];
// Query template
$sql = 'SELECT C.cid FROM `Contact` C WHERE C.email="'.$_GET["cname"].'"';
echo $sql;
// Prepare statement
$stmt = $conn->prepare($sql);
$stmt->execute();
$stmt->bind_result( $res_cid);
echo $res_cid;
$res_cid is apparently 0, but I don't know why because when I paste that query manually into phpmyadmin I do get a value... So why doesn't it return anything?
As already mentioned in the comments - you should make sure your code is secured. You better use the bindparam for that.
As for your question - after you execute your query and bind_result you should also fetch to get the actual value from the database, based on your query:
// Prepare statement
$stmt = $conn->prepare($sql);
$stmt->execute();
$stmt->bind_result( $res_cid);
// Fetch to get the actual result
$stmt->fetch();
echo $res_cid;

MYSQLi bind_result is returning null

I am trying to output the variables that I get from the database in my query but nothing is being returned. Using MYSQLi prepared statements.
Please see code below:
$stmt = $con->prepare("SELECT first_name, last_name FROM transactions WHERE order_id = ?");
$stmt->bind_param('i', $order_id);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($first_name, $last_name);
$stmt->close();
// Output review live to page
echo $first_name;
Where am I going wrong?
You forgot the line to fetch the result. fetch().
Try that:
$stmt->bind_result($first_name, $last_name);
$stmt->fetch(); // ----- > you forget that line to fetch results.
$stmt->close();

PDO: How can I run multiple prepared statements in a transaction?

Using PDO, I am trying to run two prepared statements within a transaction. I only want the second prepared statement to run if the first one executes successfully and vice versa.
//Open Database Connection
$dbh = new PDO("mysql:host=$host;dbname=$dbname", $user, $pwd);
//Set Error Handling
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//Run First Prepared Statement
$sql = 'UPDATE listers SET
first_name = :first_name,
last_name = :last_name,
address = :address,
apt = :apt,
city = :city,
state = :state,
zip_1 = :zip_1,
phone_prefix = :phone_prefix,
phone_first = :phone_first,
phone_last = :phone_last
WHERE lister_id = :lister_id';
try {
$dbh->beginTransaction();
$result = $dbh->prepare($sql);
$result->bindParam(':first_name', $_POST['first_name'], PDO::PARAM_STR);
$result->bindParam(':last_name', $_POST['last_name'], PDO::PARAM_STR);
$result->bindParam(':address', $_POST['address'], PDO::PARAM_STR);
$result->bindParam(':apt', $_POST['apt'], PDO::PARAM_STR);
$result->bindParam(':city', $_POST['city'], PDO::PARAM_STR);
$result->bindParam(':state', $_POST['state'], PDO::PARAM_STR);
$result->bindParam(':zip_1', $_POST['zip_1'], PDO::PARAM_INT);
$result->bindParam(':phone_prefix', $phone_1_prefix, PDO::PARAM_INT);
$result->bindParam(':phone_first', $phone_1_first, PDO::PARAM_INT);
$result->bindParam(':phone_last', $phone_1_last, PDO::PARAM_INT);
$result->bindParam(':lister_id', $_GET['lister_id'], PDO::PARAM_INT);
$result->execute();
//Run Second Prepared Statement
$current_date = time(); //Current Date/time in Unix format
$sql = 'INSERT INTO hidddstory_details SET
history_id = :history_id,
listing_type = "lister",
date_added = :date_added,
listing_id = :listing_id';
$result = $dbh->prepare($sql);
$result->bindParam(':history_id', $account_edited_admin, PDO::PARAM_INT);
$result->bindParam(':date_added', $current_date, PDO::PARAM_INT);
$result->bindParam(':listing_id', $row['lister_id'], PDO::PARAM_INT);
$result->execute();
$dbh->commit();
} catch(PDOException $e) {
$error = '<div id="error"><p class="error_message">The account could not be edited due to a system error. We apologize for any inconvenience.</p></div>';
$dbh->rollBack();
echo errorHandle($e);
}
When I load the page without any syntax errors, it runs the prepared statements correctly. When I purposefully add some letters to the history_details table name, as you can see above, it displays the error message relating to the incorrect table name, as it should. Unfortunately though, it doesn't rollback the first prepared statement, so when I check the listers table, it has actually updated that table, which it shouldn't.
How can I run multiple prepared statements in a transaction?
Examine the storage engine for the table you are trying to perform transactions on to ensure that it in fact supports transactions. As far as I know InnoDB is on the only format that currently supports transactions. Engines that do not support transactions will silently do nothing, no errors will be issued nor will any rollback be done.

Close statement object before starting a new with prepared statements

I'm quite new at using prepared statements and is wondering if I should close the stmt_init() after each call or could I just keep it open?
$stmt = $mysqli->stmt_init();
if($stmt->prepare("SELECT player_draws, player_turn, player_passes, swapped FROM ".$prefix."_gameplayer WHERE fk_game_id = ? AND fk_player_id = ?")){
$stmt->bind_param('ii', $currgame, $playerid);
$stmt->execute();
$stmt->bind_result($udraws, $uturn, $upass, $uswaps);
$stmt->fetch();
echo $udraws.'-'.$uturn.'-'.$upass.'-'.$uswaps.'<br>';
// Close statement object
$stmt->close();
}
$stmt = $mysqli->stmt_init();
if($stmt->prepare("SELECT player_draws, player_turn, player_passes, swapped FROM ".$prefix."_gameplayer WHERE fk_game_id = ? AND fk_player_id != ?")){
$stmt->bind_param('ii', $currgame, $playerid);
$stmt->execute();
$stmt->bind_result($odraws, $oturn, $opass, $oswaps);
$stmt->fetch();
echo $odraws.'-'.$oturn.'-'.$opass.'-'.$oswaps.'<br>';
// Close statement object
$stmt->close();
}
Is one of them better for the database considering calls?
Thanks in advance!
...A prepared statement or a parameterized statement is used to execute the same statement repeatedly with high efficiency...
EDIT
Since the queries are different each of them will need to be prepared separately but you should be able to reuse the $mysqli->stmt_init();
On a side note someone mentions this in the comments:
*if you are repeating an statement in an loop using bind_param and so on inside it for a larger operation. i thougt id would be good to clean it with stmt->close. but it broke always with an error after aprox. 250 operations . As i tried it with stmt->reset it worked for me.*

MySQLi failing to prepare a statement

I'm running two queries in my script room.php. Both are using MySQLi prepared statements, and their code are as follows:
/* Get room name */
$stmt = $mysqli->prepare('SELECT name FROM `rooms` WHERE r_id=?');
$stmt->bind_param('i', $roomID);
$stmt->execute();
$stmt->bind_result($roomName)
/* Add this user to the room */
$stmt = $mysqli->prepare('INSERT INTO `room_users` (r_id, u_id) VALUES (?, ?)');
$stmt->bind_param('ii', $roomID, $_SESSION['userID']);
$stmt->execute();
When I run the script, I get this error:
Fatal error: Call to a member function bind_param() on a non-object in C:\wamp\www\room.php on line 24
Which is the second query. If I remove the first query from the script, everything runs fine. Likewise if I remove the second query. Which leads me to believe there's a problem because I'm reusing the $stmt object. If I try the second query using $stmt2 I still get the error.
All my database tables and fields exist, so there's nothing wrong with the queries.
All of the mysqli functions/methods can fail in which case they will return false. I.e. if prepare() fails $stmt isn't an object you can call a method on but a bool(false). You have to check the return values and add some error handling, e.g.
$stmt = $mysqli->prepare('SELECT name FROM `rooms` WHERE r_id=?');
if ( !$stmt ) {
printf('errno: %d, error: %s', $mysqli->errno, $mysqli->error);
die;
}
$b = $stmt->bind_param('i', $roomID);
if ( !$b ) {
printf('errno: %d, error: %s', $stmt->errno, $stmt->error);
}
$b = $stmt->execute();
if ( !$b ) {
and so on and on
see http://docs.php.net/mysqli-stmt.errno et al
in this case you probably bumped into the problem that you can't create an other statement while there are still results/result sets pending for the previous statement.
see http://docs.php.net/mysqli-stmt.close:
Closes a prepared statement. mysqli_stmt_close() also deallocates the statement handle. If the current statement has pending or unread results, this function cancels them so that the next query can be executed.

Categories