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
:
query
method will directly execute the sql code you've enteredprepare
will "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_id
will becomeSELECT * FROM users WHERE user_id=1
). Thus, when you use prepared statements you need to doexecute
so 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
-