I have a mysql query that I'd like to wrap-up like this: $sql = $dbh->prepare("SELECT * FROM log"); Then, I execute it like this: $sql->execute(); , now my question is why can't I use it into a: foreach($dbh->query($sql) as $row) loop ? When I try to get it to run into the foreach loop the loggin form does not read from the db anymore. If I remove the dbh->prepare statement it works just fine, but I wanted to block SQL Injection on it. Thanks.
- 702
- 2
- 13
- 35
2 Answers
You are using prepared statements $db->prepare($my_sql_query). When you use prepared statements, you usually may have some variables binded to the query. For example
$my_query = 'SELECT * FROM users WHERE user_id=:user_id'
$prepared_statement = $db->prepare($my_query);
$prepared_statement->bindValue(':user_id', 123);
Now when you have binded your values you need to execute your query
$prepared_statement->execute();
When you execute the prepared statement it generates the actual sql code and then executes it in mysql. And then to retrieve the results you would execute
$record = $prepared_statement->fetch(); //if you want to get only one record from the table
$records = $prepared_statement->fetchAll(); // if you want to get multiple records from the table
foreach($records as $row) {
// your code here...
}
If you're using $db->query() you should be able to get the results with the following code:
$sql = 'SELECT name, color, calories FROM fruit ORDER BY name';
foreach ($db->query($sql) as $row) {
print $row['name'] . "\t";
print $row['color'] . "\t";
print $row['calories'] . "\n";
}
// outputs
// apple red 150
// banana yellow 250
// kiwi brown 75
// lemon yellow 25
// orange orange 300
// pear green 150
// watermelon pink 90
(taken from php.net)
There is a big difference between the methods query and prepare:
querymethod will directly execute the sql code you've enteredpreparewill "prepare" your sql code. This process replaces all params in the sql code with some actual values (i.e.SELECT * FROM users WHERE user_id=:user_idwill becomeSELECT * FROM users WHERE user_id=1). Thus, when you use prepared statements you need to doexecuteso that the code is send to mysql.
- 16,203
- 11
- 62
- 106
-
Hi tftd, thanks for your answer. Yes, I do, but I was afraid that just leaving the MySQL query unwrapped would be less safe than passing it through a PDO::"prepare" statement to avoid potential MySQL-injection attacks. – Nactus Jun 18 '13 at 21:09
-
Yes, using prepared statements are better in all cases. They prevent sql injection and are good practice. – tftd Jun 18 '13 at 21:25
You need to fetch the results first (after you execute the statement):
$rows = $sql->fetchAll();
foreach($rows as $row){
...
}
query() expects string only (the SQL query). But you were passing the return result of prepare() to it, which is a PDOStatement object.
prepare() is used in succession with execute(), not query(). It makes sense to prepare your statements when you have input parameters that you want to pass to execute().
In short:
$stm = $dbh->prepare('SELECT...');
$stm->execute();
is equivalent to:
$stm = $dbh->query('SELECT...');
if you have no input parameters to send.
- 16,471
- 7
- 50
- 89
-
Thanks much (vote up), so when using "prepare" I have to fetch before looping through ? – Nactus Jun 18 '13 at 21:00
-
Actually no. It seems that `PDOStatement` is traversable. Perhaps something is wrong in your query? Does it work if you `fetch` first? – nice ass Jun 18 '13 at 21:02
-
Well, the way I had it before the "prepare" statement was like this: 1. $sql = "SELECT * FROM log"; 2. foreach($dbh->query($sql) as $row) {//somecode}; It worked just fine. Then just by adding the $sql = $dbh->prepare("mySQL code"); it stopped working. – Nactus Jun 18 '13 at 21:11
-