mysql query failing in php - php

I am trying to run the following query in php, but its failing.
$results = $conn->prepare("INSERT INTO book_loans
VALUES (:book_id, :branch_id, :card_no, CURDATE(), DATE_ADD(CURDATE(), INTERVAL 14 DAY))");
//Binding params and executing insert for checking out
$results->bindParam(':book_id', $book_id, PDO::PARAM_STR);
$results->bindParam(':branch_id', $branch_id, PDO::PARAM_INT);
$results->bindParam(':card_no', $card_no, PDO::PARAM_STR);
if($results->execute()) {
return array("success");
} else {
return array("failure");
}
I am returning arrays with strings to check back and display a message.
But even for valid elements, the query is failing.

What is the error message?
Usually the cause is an error in the SQL query! Check that the query actually works in the MySQL console.
If you require more specific help you need post the desription of the book_loans table. Can you post the create table statement for this table?

In stead of returning array ('failure') return array($results->errorInfo()), analyze the error text and then fix it

Related

How to debug PDO script?

I have a PHP script that is executed daily by my server thanks to cron.
This script contains PDO queries to add, edit, and delete data from my MySQL database.
The script does not work as expected, especially the last part of the query which is supposed to remove some rows:
$stmt = $conn->prepare("DELETE FROM `mkgaction` WHERE score IS NULL");
$stmt->execute();
if($stmt->execute()) {
echo "delete succeeded<br>";
} else {
echo "delete failed<br>";
}
When executed manually via PHPMyAdmin, every query works fine. When executed via this script it does not work despite the message showing "delete succeeded".
I suppose the best way to understand what actually happens is to read the response from the database, but I don't know how to do that.
Would you help me? :-)
Thanks
Always check the return value of prepare() and execute(). They return the boolean value false if there's a problem.
Then you should check the specific error and report that error to help debugging.
$stmt = $conn->prepare("DELETE FROM `mkgaction` WHERE score IS NULL");
if ($stmt === false) {
die(print_r($conn->errorInfo(), true));
}
$ok = $stmt->execute();
if ($ok === false) {
die(print_r($stmt->errorInfo(), true));
}
echo "delete succeeded<br>";
Admittedly, checking every call gets to be a lot of repetitive code. An alternative is to enable exceptions, if you're comfortable writing code to handle exceptions. See https://www.php.net/manual/en/pdo.error-handling.php

mysqli_stmt_bind_result not returning a value

Alright so this bugs the crap out of me, and I can't seem to find anything in the PHP documentation, nor anywhere in the Google resultosphere, so maybe someone can help here.
I'm trying to make a simple request to a database to return a varchar(30).
Code:
$qryID = "select idPhotos from housesphotos where idHouse = ?";
//Prepare the query
$stmt = mysqli_prepare($link, $qryID);
$x = 106;
//Bind the login parameter to the statement
if(mysqli_stmt_bind_param($stmt, "i", $x)){
if(mysqli_stmt_execute($stmt)){
//Bind every column in the select
if(mysqli_stmt_bind_result($stmt, $photoID)){
// $photoID = mysqli_stmt_fetch($stmt);
echo $photoID;
}
}
}
if(empty($photoID)){
printf("EMPTY");
}
As you can guess the output was EMPTY. I have tried using this solution: Strange issue with mysqli_stmt_bind_result but it did not work.
To make sure that everthing was suppost to go correctly I have made the query in the mysql and it worked wonders:
select idPhotos from housesphotos where idHouse = 106
OUTPUT:
591219e92b2fe_591219e92b302
The housephotos is a varchar(30) field. I'm not sure if it's the field type that is messing with the return value. I'm not sure also if it's the connections that I made earlier on the code but I have tried unset($stmt) and other variables to solve the problem but it's not working.
Is this some kind of bug with mysqli_stmt_bind_result() or just a new person's mistake?
You're not actually fetching the results - you commented the mysqli_stmt_fetch() out. The fetch also returns a boolean, not the actual results. Uncomment that line, and remove the variable assignment to it.
$qryID = "select idPhotos from housesphotos where idHouse = ?";
//Prepare the query
$stmt = mysqli_prepare($link, $qryID);
$x = 106;
//Bind the login parameter to the statement
if(mysqli_stmt_bind_param($stmt, "i", $x)){
if(mysqli_stmt_execute($stmt)){
//Bind every column in the select
if(mysqli_stmt_bind_result($stmt, $photoID)){
mysqli_stmt_fetch($stmt); // Remove the comment and variable assignment
echo $photoID;
}
}
}
If you still don't get any results, it might be because the number of rows returned was zero (you can check that with $stmt->num_rows after executing), but since you said the query worked in phpMyAdmin, it's likely that there's some sort of error you're ignoring. To check for errors, add an else to your if conditions, and log $stmt->error inside.
http://php.net/manual/en/mysqli-stmt.fetch.php
It seems that PHP 5.4 (at least the way it's installed on Comcast servers) has a bug that causes bind-result to fail on a varchar field. Changing the field definition to "text" solves the problem.

PHP Fatal error: Call to a member function bind_param() [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 months ago.
I've been stuck on this error , please help me this is my code
PHP Fatal error: Call to a member function bind_param()
$statement= $db->prepare("insert into uploaddetails(idnum,title,desc,author,tags,title) values(?,?,?,?,?,?)");
$id='NULL';
$title=$_POST['title'];
$description=$_POST['description'];
$author=$_POST['author'];
$tags=$_POST['tags'];
$file= basename($_FILES["fileToUpload"]["name"]);
$statement->bind_param( 'isssss', $id,$title, $description,$author,$tags,$file);
$statement->execute();
$db->close();
$statement->close();
Since nobody else has spotted the issue, I'll post it for you. The reason you're prepare() is failing is because you're trying to use a MySQL Reserved Word. The word desc is a reserved word in MYSQL, which means you need to wrap it in backticks like this:
$statement= $db->prepare("insert into uploaddetails(idnum,title,`desc`,author,tags,file) values(?,?,?,?,?,?)");
It also helps to use proper practice when inserting into a database/using prepared statements.
$statement= $db->prepare("insert into uploaddetails(idnum,title,`desc`,author,tags,title) values(?,?,?,?,?,?)");
if($statement !== FALSE) {
// do the binds...etc
}
Notes
file is also a reserved word, I don't know what your actual file columns name is, so keep that in mind.
Your prepare statement is failing because of the query, what you need to do is to make sure the statement is not false in order to execute bind_param, otherwise view the prepare query error as follows :
//Make sure the statement is not false
if($statement !== FALSE)
{
$statement->bind_param( 'isssss', $id,$title, $description,$author,$tags,$file);
$statement->execute();
$db->close();
$statement->close();
}
//Otherwise check why the prepare statement failed
else
{
die('prepare() failed: ' . htmlspecialchars($db->error));
}
Try this. your code is modified.
$statement= $db->prepare("INSERT INTO uploaddetails (title,desc,author,tags,file) VALUES(?,?,?,?,?)");
//$id='NULL';
$title=$_POST['title'];
$description=$_POST['description'];
$author=$_POST['author'];
$tags=$_POST['tags'];
$file= $_FILES["fileToUpload"]["name"];
$statement->bind_param( 'isssss',$title, $description,$author,$tags,$file);
$statement->execute();
$db->close();
$statement->close();
//---- Move the file to desired location...
-ID is not required because it is auto increment and mysql will take care of it,
-and you had wrong field name for file, which was title and I change it to file(correct it if you have any other name instead).
possible errors
1)column count in the table is different from your query.
2)although it shows the error in the bind_param line, the error may occur in the prepare statement line(in your case line 1)
3)you can put echo statement before and after these lines and caught the error
(in my case I repeated the same field name twice in the prepared statement)
fetch following code with your requirements and tryout
$stmt = $conn->prepare("INSERT INTO SalesReturn(CRDNUMBER, CRDDATE, REFERENCE,CUSTOMER,ITEM,QTYRETURN,UNITPRICE,TIAMOUNT1,TIAMOUNT2,EXTCRDMISC,TAMOUNT1,TAMOUNT2,CRDSUBTOT,CRDNET,CRDETAXTOT,CRDNETNOTX,CRDNETWTX,TransactionType) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
echo "after prepare";
$stmt->bind_param("ssssssssssssssssss",$CRDNUMBER,$CRDDATE,$REFERENCE,$CUSTOMER,$ITEM,$QTYRETURN,$UNITPRICE,$TIAMOUNT1,$TIAMOUNT2,$EXTCRDMISC,$TAMOUNT1,$TAMOUNT2,$CRDSUBTOT,$CRDNET,$CRDETAXTOT,$CRDNETNOTX,$CRDNETWTX,$TransactionType);
echo "after bind_param statement";

MYSQL result not returning correctly

So I have a piece of code that will check if you have followed a user or not. And basically let you follow them if you haven't. So here it is
if($_SESSION['loggedIn'] == true){
$result = $con->prepare("SELECT * FROM followers WHERE follow_from = :username AND follow_to = :post_id");
$result->bindParam(':username', $username);
$result->bindParam(':post_id', $follower);
$result->execute();
$reprint = $result->fetchAll(PDO::FETCH_ASSOC);
}
print_r($reprint);
if($reprint < 1){
$stmt = $con->prepare("INSERT INTO followers (follow_from, follow_to) VALUES (:ff, :ft)");
$stmt->bindValue(':ff', $follower, PDO::PARAM_STR);
$stmt->bindValue(':ft', $username, PDO::PARAM_STR);
$stmt->execute();
}
else{
echo 'Error';
exit();
}
//Display follower
$stmt1 = $con->prepare("SELECT COUNT(*) AS count FROM followers WHERE follow_to = :username");
$stmt1->bindValue(':username', $username, PDO::PARAM_STR);
$stmt1->execute();
$likes = $stmt1->fetchAll(PDO::FETCH_ASSOC);
print_r($likes);
So when I run it once. I get the else statement echoed. My question is why does this happen? In the database I have no record, so I'd expect it to go in once. I get no errors at all. loggedIn is true. And variables are being passed through successfully.
Any ideas?
You're misusing the result you get from fetchAll(). It's an associative array, not a scalar value. It could, as you've probably guessed, be empty.
But, more significantly than that, your code has a potential race condition. What happens if two different sessions are trying to set this same followers row? (Admittedly, in a small system that is unlikely, but in a large system it might happen).
What you actually do is just the INSERT operation. If your followers row has a unique key on the (follow_from,follow_to) columns, then, if that row is already there you'll get a 'Duplicate entry' error on the INSERT. Otherwise it will just happen. You can just ignore the 'Duplicate entry' error, because all you want is for that row to make it into that table.
So your code would go like this:
$stmt = $con->prepare("INSERT
INTO followers (follow_from, follow_to)
VALUES (:ff, :ft)");
$stmt->bindValue(':ff', $follower, PDO::PARAM_STR);
$stmt->bindValue(':ft', $username, PDO::PARAM_STR);
$result = $stmt->execute();
if ($result) {
/* this follow pair was successfully added */
} else {
/* MySQL may return the error 'Duplicate entry' */
if (false == stripos($stmt->errorCode,'Duplicate')){
echo 'Something failed in the insert: ' . '$stmt->errorCode';
}
else {
/* this follow pair was already in your table */
}
}
Pro tip: Don't use SELECT * in software; it can mess up query optimization; it often sends more data than you need from the server to your program, and it makes your program less resilient if your change your table definitions.
Pro tip: If you must count rows matching a particular WHERE statement, use COUNT() rather than fetching the rows and counting them in the client. What if you get a million rows?
You'd want to use count($reprint) other that a direct comparison. $reprint is an array, not a number
if(count($reprint) < 1)
{
$stmt = $con->prepare("INSERT INTO followers (follow_from, follow_to) VALUES (:ff, :ft)");
$stmt->bindValue(':ff', $follower, PDO::PARAM_STR);
$stmt->bindValue(':ft', $username, PDO::PARAM_STR);
$stmt->execute();
}
else
{
echo 'Error';
exit();
}
PDOStatement::fetchAll
PDOStatement::fetchAll — Returns an array containing all of the result set rows
If you check the size of the array then you would actually know if something happened.
Using proper error handling can tell you if something's failing deep down:
try
{
...
}
catch (PDOException $e)
{
echo $e->getMessage();
}
You will need to enable PDO error-displaying:
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
If checking the size of the array doesn't do it and you get no errors then it's simply some logic error.
Most likely the logic error is that
$reprint = $result->fetchAll(PDO::FETCH_ASSOC);
doesn't get executed (wrapping the error handling around that should tell you why), so
$reprint = $result->fetchAll(PDO::FETCH_ASSOC);
isn't given a proper value, meaning you'll always hit the else statement.
Edit
Your original problem was that "So when I run it once. I get the else statement echoed. [...] In the database I have no record" but now you're saying "It adds the record, but doesn't limit it to me one".
Can you be more clear about the actual, current, problem?

Specific MySQL PDO datetime insert [HY0093] error

I have spent a lot of time trying to figure out what is wrong here and I am stumped.
Here's the specific PHP code that is failing:
//Handy function I use to do all my bound queries - yes you can have it.
function prepareBindAndExecute($pdo, $qry, $aParams) {
if (!$stmt = $pdo->prepare($qry)) {
setSessionError("Failed to prepare $qry");
return false;
}
foreach ($aParams as $aParam) {
// $aParam[0] = ":labelToBind"
// $aParam[1] = value to Bind
// $aParam[2] = PDO::PARAM_TYPE
if (strpos($qry, $aParam[0]) !== false) { // skip binding if label isn't in query. This allows built up queries to not fail if parts were not created for a parameter.
if (!$stmt->bindParam($aParam[0], $aParam[1], $aParam[2])) {
setSessionError("Failed to bind $aParam[1] as $aParam[0] to $qry Error Info:".print_r($stmt->errorInfo()));
return false;
}
}
}
if (!$stmt->execute()) {
setSessionError("Failed to execute $qry bound with ".json_encode($aParams).' Error Info:'.print_r($stmt->errorInfo()));
return false;
}
return $stmt;
}
// Here's the problem call: The member_login is a VARCHAR(32) receiving an email address string
// and the submission_date is a DateTime column receiving the current date.
$stmt = prepareBindAndExecute($pdoRW,
'INSERT INTO videosubmissions (member_login, submission_date) VALUES (:login, :submission-date)',
[ [ ':login', $info['login'], PDO::PARAM_STR ],
[ ':submission-date', $submission_date->format(DateTime::ISO8601), PDO::PARAM_STR ] ]);
Here's the results I get with this code:
Failed to execute
INSERT INTO videosubmissions (member_login, submission_date) VALUES
(:login, :submission-date) bound with
[[":login","xTst2#gmail.com",2],
[":submission-date","2014-02-15T20:37:01+0100",2]]
With a related PHP error in the error log of:
PHP Warning: PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter
number: parameter was not defined in...
This simple case is NOT a mismatched number of parameters case as there are only two labels to bind. My helper function has been working with much more complex queries than this one.
For awhile I thought I had this fixed by quoting the :label tag -> VALUES (":label", :submission_date...
This let the call succeed but resulted in the sting ":label" being inserted into the DB and would in fact, by my understanding, cause a true parameter count mismatch.
The PDO::PARAM_ constants do not offer a DATE or DATETIME flavor. (see http://www.php.net/manual/en/pdo.constants.php)
I have verified that my helper function did not skip binding any parameters - and we can seed this from the error message returned.
I have also tried binding the submission_date with a DateTime PHP object instead of a string and I have tried various data/time formated strings.
I am wondering if the # in the login parameter is somehow screwing up the binding.
It would be nice if PDO would offer up what the actual query is that is being sent to the mySql but this might be buried in the driver.
Hopefully I am just missing something dumb.
Thanks!!!
Dunno what's the problem with this particular code, but if to take out all the useless parts it can be boiled down to this, and I am pretty sure would work
function query($pdo, $qry, $aParams) {
$stmt = $pdo->prepare($qry);
$stmt->execute($aParams);
return $stmt;
}
$sql = 'INSERT INTO videosubmissions (member_login, submission_date) VALUES (?, ?)';
query($pdoRW, $sql, [$info['login'], $submission_date->format(DateTime::ISO8601)]);
You can't have - in a placeholder name:
INSERT INTO [...snip...] (:login, :submission-date)',
^---
The - is not a valid char in a placeholder name, and MySQL will interpreter this as
... :submission MINUS date
Since you're not binding a value for submission, you get the invalid parameter number error. Even if you by-chance did have another placeholder whose name WAS :submission, you'd still end up with an SQL parser error due to the undefined/non-existent date field being used in what MySQL is seing as a subtraction operation.

Categories