Hopefully someone will be able to help me because I've been banging my head against the wall all night trying to solve this little problem.
I want to insert data into a database using PDO (which I am admittedly not the most knowledgeable about). I am using a statement that I have used many times in the past, but for some reason this time it's not working. The statement is as follows:
$userID = "Johnny5";
$sql = "INSERT INTO user_info(user_id) VALUES(:user-id)";
if($stmt = $this->_db->prepare($sql))
{
$stmt->bindParam(":user-id", $userID, PDO::PARAM_STR);
$stmt->execute();
$stmt->closeCursor();
return TRUE;
} else {
return FALSE;
}
But unfortunately this is always returning TRUE without ever entering anything into my database. I have tried every combination changes to the statement that I could think of, but I am still at a loss.
I hope someone out there can point out a really simple error that I have made.
Also, placing single quote marks around the parameter :user-id in the $sql string is the only way that I can get anything to appear into the database, but that obviously doesn't enter in any actual data into the database.
EDIT
I have also changed the PDO parameter types from PDO::PARAM_STR to PDO::PARAM_INT but have still had no luck.
After further investigation, execute() is returning FALSE.
Solution
Thanks to everyone for their guidance. #Nabeel was correct in saying not to use placeholders in PDO parameters.
Don't use dashes in your SQL statements.
Make this:
:user-id
as this:
:userid
$userId is a string in this code, yet you say it's in int by defining PDO::PARAM_INT. Try replacing it with PDO::PARAM_STRING or try setting $userId to a number(1 for example)
If something fails, then there most certainly was an error. First you need to find out which statement fails by checking their return values (always read about every command you use in the PHP Manual first).
If you've located which command failed, use PDOStatement->errorInfo to find out more about the concrete error.
That information should help you to solve your issue.
Update: And if you want to deal with Exceptions (as Pekka suggested): How to squeeze error message out of PDO?
Related
So, I'm working with PHP and prepared statements sent to a MySQL database. I've ran into a problem that I can't quite debug. Here is my code:
// Check if the input username is in the database
$stmtQuery = "SELECT * FROM updatedplayers WHERE Player=?;";
$preparedStmt = $dbc->prepare($stmtQuery);
$preparedStmt->bind_param("s", $setUsername);
$preparedStmt->execute();
$preparedStmt->bind_result($resultUUID, $resultUsername);
$preparedStmt->fetch();
// If it's not, kill the page.
if ($resultUUID == null) {
incorrect();
}
$stmtQuery = "SELECT Password, Salt FROM logins WHERE UUID=?;";
echo 'flag1 ';
$preparedStmt = $dbc->prepare($stmtQuery);
echo 'flag2 ';
$preparedStmt->bind_param("s", $resultUUID);
echo 'flag3 ';
The fist prepared statement works fine, it's at the line $preparedStmt->bind_param("s", $resultUUID);. There are also a couple other prepared statements before these, so I know I'm doing this correctly, but I'm not too sure about the last statement.
The code just seems to stop running after echo 'flag2 ';, which I put there to find the specific line. I don't get any error messages, it just doesn't print out flag3.
I've tried replacing $resultUUID with a static string, yet I get the same outcome. Also, I know my SQL statement is correctly formatted, I've tested within the console manually.
That's pretty much it, I'd love to hear some criticism, as I am new to PHP. Also, is there any way to get a better idea about the errors I get, instead of trying to pinpoint the error myself? Thanks!
So, adding ini_set('display_error', 1);, suggested by #user2182349, gave me a little more insight, I got "Fatal error: Call to a member function bind_param() on boolean".
After some research, I tried adding mysqli_report(MYSQLI_REPORT_ALL);, which ended up throwing "No index used in query/prepared statement".
I did some research on that to realize that it wasn't a problem, just MySQLI reporting unnecessary errors (which is what I asked it to do lol). In order to get a better, more insightful stack trace, I used mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);.
This threw "Commands out of sync; you can't run this command now". Again, more research taught me to use $preparedStmt->store_result();, in order to allow for another prepared statement to run.
Big thanks to all y'alls' help, hope this can help someone too.
You should be able to use a single select statement similar to this:
SELECT u.UUID, u.Username, l.Password, l.Salt
FROM updatedplayers AS u
JOIN logins AS l ON (u.UUID = l.UUID)
WHERE u.Player = ?
Check the case of the field names to be sure they match the database.
At the top of the file, add ini_set('display_errors',1);. If you have any PHP errors, they will be displayed. Also check the return values from the database calls and use the error display functions.
I think you need to close the prepared statement before you use the variable for another query:
$preparedStmt->close();
Or use another variable name like $preparedStmt2 for the second query.
I would suggest you should start using PDO... I have issues encountered with mysqli prepared statement years ago. Since then, PDO gives me no headaches when it comes to multiple queries at a time.
You should try PDO.. :-) it's more efficient.
http://php.net/manual/en/intro.pdo.php
http://php.net/manual/en/class.pdostatement.php
Or you can do the following "if you want alternative solution"..
//Close connection
$preparedStmt->close();
//AND OPEN YOUR CONNECTION AGAIN TO PREPARE NEW QUERIES..
$stmtQuery = "SELECT Password, Salt FROM logins WHERE UUID=?;";
echo 'flag1 ';
$preparedStmt = $dbc->prepare($stmtQuery);
echo 'flag2 ';
$preparedStmt->bind_param("s", $resultUUID);
echo 'flag3 ';
So, here's the relevant code from my page. It connects to a sqlite3 database through PDO which I update through forms on the page. I have other sqlite statements, like INSERTS and UPDATES (that does use WHERE id=:id) that work no problem. This DELETE one does not, however. I do have all the code in a try catch block on my page (which is how I got the error, if you were wondeing) but I figured I can omit it here.
Thanks for the help!
<?php
$db = new PDO("sqlite:osuat.sqlite3");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$id = $_POST['id'];
$update = "DELETE FROM pages
WHERE id=:id";
$stmt = $db->prepare($update);
$stmt->bindParam(':id', $id);
$stmt->execute();
?>
Try adding PDO::PARAM_INT to the bind_param method, to make sure that the value being sent is an INT (which I'm assuming your ID field is) i.e.,
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
Echo the actual sql statement and die prior to actually running it. Then inspect and run the statement directly. I suspect $_POST['id'] doesn't contain what you think it does.
I finally figured it out. In my actual page, I have a bunch of if-else constructs in order to construct the correct $update string. I (wrongly) figured that I could just use bindParam() at the end without paying heed to how many bindParam()s each update statement would need. So, for my DELETE FROM pages WHERE id=:id, it was being supplied a whole bunch of other parameters only used in other $update strings, not just :id.
Its my fault for not including the entire source, I'm sure someone here would have caught it right away, but many thanks to duellsy, he/she led me on the right path looking for ways to log the actual SQL statement. In the end, using stmt->debugDumpParams(); helped me figure what I was doing wrong.
Try writing the DELETE command in one line.
PLEASE READ THE QUESTION CAREFULLY. It is not usual silly "my code doesn't work!!!" question.
When I run this code with intended error
try {
$sth = $dbh->prepare("SELECT id FROM users WHERE name INN(?,?) ");
$sth->execute(array("I'm","d'Artagnan"));
} catch (PDOException $e) {
echo $e->getMessage();
}
I get this error message
You have an error in your SQL syntax ... near 'INN('I\'m','d\'Artagnan')' at line 1
But I thought for years that query and data being sent to the server separately and never interfere. Thus I have some questions (though I doubt anyone got an answer...)
Where does it get such a familiar string representation - quoted and escaped? Is it being made especially to report an error or is it a part of actual query?
How does it work in real? Does it substitute a placeholder with data or not?
Is there a way to get whole query, not only little bit of it, for debugging purposes?
Update
mysqli does it as expected: it throws an error says near 'INN(?,?)'
try adding
$dbh->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );
;)
I'm not sure about all the details, but I will try to answer.
The quotation happens on the database side. The database escapes and sanitizes all values (see bullet 2) it receives so that it gets interpreted correctly.
The moment the error is thrown, the database (in this case MySQL) prints out the query it tried to run. This wouldn't be so helpful if it just showed the prepared part.
No, it doesn't. At preparation time the query gets compiled on the server side. When a query is executed with values, only the values are transmitted. This is pretty much the same as calling PREPARE and EXECUTE on the database directly.
This depends on the database you're using. MySQL for example can log all queries to a log file (check my.cnf settings for that). But you can also use debugDumpParams() on PHP side.
I hope this was a bit helpful.
I have a complex query that gets executed like this:
if ($stmt = $dbi->prepare($pt_query)) {
$stmt->bind_param('ssssssssi', $snome,$scognome,$ssocieta,$svia,$slocalita,$sprovincia,$scap,$stelefono,$sfax,$uid);
$stmt->execute();
echo $dbi->error;
$stmt->close();
} else {
printf("Error -> %s\n", $dbi->error);
}
This thing is failing without any error, it simply doesn't update the database. Since there is a ton of data that gets treated before this thing I would like to know if there is any way to show the actual query that mysqli is executing in order to understand where the problem is.
Thank you.
If your statement is failing, you should check $stmt->error (as opposed to $dbi->error). As far as getting the actual text of the query: it's not possible. When using prepared statements, the library is using a special protocol that doesn't generate an actual query string for each ->execute() call.
You could turn on logging on the MySQL DB itself, ie. add a log=logfile line to my.ini.
Refer to the MySQL documentation for more information if needed.
Based on the PHP mysql website there is no actual way of doing it. But you may try this function as it gives you errors in your query.
Here's a tool I found that may help MySQLi Prepare Statement checker
This is a terrible question because I don't have a simple way to reproduce it. However, I'm using the Zend Framework to connect to my MySQL database on OS X. Sometimes a call to the prepare function on a mysqli object returns null. The stated return values for the prepare function are false or a statement object.
I can't figure out where else to look for info on why the prepare statement is failing. Is there any way to get visibility into the prepare process to see why it is failing? All of my problems are coming up while a transaction is open.
Sorry for the lack of specifics, but I really can't nail down why this is happening.
Just to correct ToughPal, you should be using:
mysqli_query($db, "INSERT INTO table (variable1, variable2) VALUES (hello, mynameis);
Remember that you need to have the db connection defined and stated in the query first, before your actual SQL.
Remember to enclose the table name, column names and value data in backtick escapes.
Example prepared statement
$result = $db->query( 'INSERT INTO server (key, value) VALUES (:key, :value)',
array('key' => $foo, 'value' => $bar)
Can you let us know your DB query?
Try and execute your DB query with test data and see if the query works fine to start with. If the query is ok then we can look why the code fails.
Well I managed to find the issue over the weekend but was really only able to fix the symptoms and not the cause.
I didn't include any SQL in the original issue because the problem was happening randomly, the same code would sometimes work and sometimes not. The issue looks like it was a memory pointer problem. Whenever I had a problem Zend Debugger told me that I had a mysqli object. I believe this because otherwise I would've gotten an error when trying to run the prepare function on it. I have a singleton object that acts as a container for my mysqli connection but whenever the prepare function failed, === showed that the mysqli being used was not the same as the mysqli connection in my singleton object.
In the end, Zend Framework's only issue is that it doesn't fail if the the prepare function returns null. If you are seeing this problem use === to verify that the connection is actually the same as the one that you've previously initiated.
if you're doing something like this
$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
$query = "...";
$mysqli->prepare($query);
then you can inspect mysqli::$error next to see useful errors about why prepare() failed
print_r($mysqli->error);