I'm new to PDO, so I suspect the cause of my problem is something I've overlooked somewhere. What's happening is this: when I run a query on a PDO like
$sql = "select * from some table";
$result = $pdo->query($sql);
$result always looks like this:
PDO Object()
{[field1:value], [field2:value]}
So what's going on? Why is the phrase "PDO Object()" always at the start of the result set? None of the examples I've seen show this, and many Google searches have been fruitless. Any help would be greatly appreciated.
As Michael Berkowski explained you need to fetch. Also since you're just learning use prepared statements (more secure). Here's how you do it.
$sql = "SELECT * FROM some_table WHERE field = :someVar";
$statement = $pdo->prepare($sql);
$statement->execute(array(':someVar'=>"expectedFieldValue"));
$result = $statement->fetchAll();
Related
When switching to Laravel, SQL queries are changed.
From this:
$sql = "SELECT * FROM table";
$result = mysqli_query($db, $sql);
to:
$sql = 'SELECT * FROM table';
$result = DB::select($sql);
(I want to use SQL raw queries in LARAVEL to make rewriting the code easier https://laravel.com/docs/7.x/database#running-queries)
Sorry if this question is obvious, but I'm a beginner and don't understand the other answers I've found. Now what to add to the new code, so the old $result and new $result behave the same?
Because new $result is an array, right? I need to have the new $result behave like the old $result to change the code easily.
Optional: do you know which topics I need to learn to understand this better myself?
I want to migrate a site from some poorly written MySQLi to clean PDO.
I have looked at three similar questions and their answers, and this is a straightforward question, but none of them are giving me results. Here's my code:
$state = "Alaska";
//trying to implement PDO here
$sql = "SELECT * FROM sales WHERE state = ? ORDER BY type";
$result = $conn->prepare($sql);
$result->execute(array($state));
/*
this was the old, successfully working way before
$sql = "SELECT * FROM sales WHERE state = '$state' ORDER BY type";
$result = $conn->query($sql);
*/
Previous questions on this site show me answers that look like my PDO implementation, yet mine doesn't work. I have made sure the PDO class exists and that the extension is loaded.
If you see the error, let me know!
The difference between the two, aside from difference in libraries, is that one is using a direct query() (the mysqli_*), while the other is using a prepared statement. Those are handled a bit different, regardless which API is running.
When using MySQLi, doing
$result = $conn->query($sql);
would have $result be a mysqli-result object, which holds the data. You can use mysqli_result::fetch_assoc() on that to fetch the data. However, when you're using PDO::prepare(), your $result variable will be a PDOStatement - which is a bit different. You'll need to run a fetch() method on it first, and then you can use the return-value of it, as such
$state = "Alaska";
$sql = "SELECT * FROM sales WHERE state = ? ORDER BY type";
$stmt = $conn->prepare($sql);
$stmt->execute(array($state));
$result = $stmt->fetch(PDO::FETCH_ASSOC);
Note that I've changed the names of your variables. Now $result is an array (if there are any results fetched), which you can use as you normally do when fetching associative-arrays. If there are no results, PDOStatement::fetch() will return a boolean false.
var_dump($result['state']);
You can loop the fetch() method as
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
if you expect more than one row. Use $result as you would without looping, as shown above.
Note that this assumes a valid PDO-connection. Beware that you cannot interchange any MySQL libraries, mysql_, mysqli_* and PDO are all different animals in the zoo.
PHP.net on PDOStatement::fetch()
Can I mix MySQL APIs in PHP?
From experience and also having been told constantly the benefits of using prepared statements and binding my parameters, I have constantly used those two techniques in my code, however I would like to understand exactly the purpose of each of those two techiques:
From my understanding of prepared statements:
$sql = "SELECT * FROM myTable WHERE id = ".$id;
$stmt = $conn->prepare($sql);
$stmt->execute();
The previous code should create a sort of a buffer in the database with the query I proposed. Now FROM MY UNDERSTANDING (and I could be very wrong), the previous code is insecure, because the string $sql could be anything depending on what $id actually is, and if $id = 1; DROP TABLE myTable;--, I would be inserting a malicious query even though I have a prepared statement.
FROM MY UNDERSTANDING this is where binding my parameters com in. If I do the following instead:
$sql = "SELECT * FROM myTable WHERE id = :id";
$stmt = $conn->prepare($sql);
$stmt->bindParam(':id', $id);
$stmt->execute();
The database should know exactly all the parts of the sql statement before hand:
SELECT these columns: * FROM myTable and WHERE id = "a variable that was input by the user", and if "a variable that was input by the user" != a variable, the query fails.
I have been told by some my understanding is correct, and by others that it is false, could someone please let me know if I am wrong, correct, or missing something? And elaborate as much as you want, all feedback is greatly appreciated!
You're correct that the first case is insecure. It's important to understand though, that preparing a statement only has value if you are using variable data, and/or executing the same query repeatedly. If you are executing plain statements with no variables, you could simply do this:
$sql = "SELECT * from myTable WHERE this_column IS NOT NULL";
$result = $conn->query($sql);
And end up with a PDOStatement object to work with, just like when you use PDO::exec().
For your second case, again, you're largely correct. What's happening is the variable passed to the database is escaped and quoted (unless you specify otherwise with the third argument to PDOStatement::bindParam(), it's sent as a string which is fine for most cases.) So, the query won't "fail" if bad data is sent. It behaves exactly as if you had passed a valid number that didn't exist as an ID in the database. There are, of course, some edge cases where you are still vulnerable even with a correctly prepared statement.
Also, to make life easier, you can use prepared statements like this, to do implicit binding:
$sql = "SELECT * FROM myTable WHERE id = :id";
$stmt = $conn->prepare($sql);
$stmt->execute([":id"=>$id]);
Or even like this, with un-named parameters:
$sql = "SELECT * FROM myTable WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->execute([$id]);
Naturally, most of this has been explained in the comments while I was typing up the answer!
I just recently started using PDO, not that much experience with it, but I recently crashed into an annoying problem.
I am trying to use bindValue with a fetch statement to retrieve informatie from a database. The variables I get are from a GET, from a previous page. Everything is going wel except for the fact that it is not assigning, I guess, a right value to one of the bindValue.
PDO:
$stmt = $dbconnect->prepare('SELECT * FROM :table WHERE id=:id');
$stmt->bindValue(':table', $table);
$stmt->bindValue(':id', $id);
$stmt->execute();
$row = $stmt->fetch();
I know the difference between bindValue and bindParam. The code is working fine when I hardcode the table value. I have been banging my head against a wall for a short hour now but I can't seem to figure it out. Could anyone beside giving me the correct syntax please explain what went wrong with my thinking because at this point I cannot think of a reason, besides maybe the misinterpretation of the string value, why this is going wrong.
Also for in the future I would like to know the precise content of the SQL command. I tried doing this:
$SQL = 'SELECT * FROM :table WHERE id=:id';
$stmt = $dbconnect->prepare($SQL);
$stmt->bindValue(':table', $table);
$stmt->bindValue(':id', $id);
$stmt->execute();
$row = $stmt->fetch();
But this won't bind the variable values to the SQL variable. Your help is much appreciated!
EDIT:
I noticed my post is a duplicate from a FAQ post: FAQ. So my question has been answered however my insight in PDO is not enough to undertand it. Could anyone please explain what happens with the next line of code and why this works, opbtained from the posted link!
$field = "`".str_replace("`","``",$field)."`";
$sql = "SELECT * FROM t ORDER BY $field";
Answer
Thanks to silkfire I came up with fix. Before inserting the SQL string just add the string content into the SQL string:
$SQL = 'SELECT * FROM '.$table.' WHERE id=:id';
PDO does not allow table names or column names to be placeholders. Just create the query with concatenation instead, but make sure the user supplies only valid values. This should be safe.
I am trying to write a keyword search using PDO prepared statements. Ideally, I'd like to make use of the LIKE operator to search for a substring inside the field value. Here is my code:
$statement = $this->db->prepare("select * from whatever where title like ? or author like ?");
$statement->execute(array("%$titleKeyword%","%$authorKeyword%"));
$rows = $statement->fetchAll(PDO::FETCH_ASSOC);
Unfortunately, $rows is always empty when I try this. However, if I copy the SQL into phpMyAdmin, and substitute '%keyword%' for each of the ? symbols, it works fine (I get results when the keyword used exists).
I have also tried the following code:
$statement = $this->db->prepare("select * from whatever where title like :titleKeyword or author like :authorKeyword");
$statement->bindValue(":titleKeyword", '%'.$titleKeyword.'%', PDO::PARAM_STR);
$statement->bindValue(":authorKeyword", '%'.$authorKeyword.'%', PDO::PARAM_STR);
$statement->execute();
$rows = $statement->fetchAll(PDO::FETCH_ASSOC);
I had read in another question that you are supposed to include the % when binding the parameters, not in the SQL itself (pre-prepared statement), but that doesn't work.
I could resort to just inserting the keyword directly into the SQL (after doing some sanitization), but I want to stick with prepared statements. Any help would be greatly appreciated.
This actually works for me:
$stmt = $pdo->prepare("select * from t where c like ?");
$stmt->execute(array("70%"));
print_r($stmt->fetchAll());
What PHP version do you use?
Thanks Steffen and Terry for the help.
I ended up solving the problem myself by switching to bindParam() instead of bindValue(). I am not sure why I couldn't do it with bindValue(), but right now I am just too tired to care.