Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP PDO with foreach and fetch

Tags:

The following code:

<?php try {     $dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);     echo "Connection is successful!<br/>";     $sql = "SELECT * FROM users";     $users = $dbh->query($sql);     foreach ($users as $row) {         print $row["name"] . "-" . $row["sex"] ."<br/>";     }     foreach ($users as $row) {         print $row["name"] . "-" . $row["sex"] ."<br/>";     }     $dbh = null; } catch (PDOexception $e) {     echo "Error is: " . $e-> etmessage(); } 

Output:

Connection is successful!  person A-male person B-female 

Running "foreach" twice is not my purpose, I'm just curious why TWO "foreach" statements only output the result once?

Following is the similar case:

<?php try {     $dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);     echo "Connection is successful!<br/>";     $sql = "SELECT * FROM users";     $users = $dbh->query($sql);     foreach ($users as $row) {         print $row["name"] . "-" . $row["sex"] ."<br/>";     }     echo "<br/>";     $result = $users->fetch(PDO::FETCH_ASSOC);     foreach($result as $key => $value) {         echo $key . "-" . $value . "<br/>";     }     $dbh = null; } catch (PDOexception $e) {     echo "Error is: " . $e-> etmessage(); } 

Output:

Connection is successful!  person A-male person B-female  SCREAM: Error suppression ignored for Warning: Invalid argument supplied for foreach() 

But when I delete the first "foreach" from the above codes, the output will become normal:

<?php try {     $dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);     echo "Connection is successful!<br/>";     $sql = "SELECT * FROM users";     $users = $dbh->query($sql);      echo "<br/>";     $result = $users->fetch(PDO::FETCH_ASSOC);     foreach($result as $key => $value) {         echo $key . "-" . $value . "<br/>";     }     $dbh = null; } catch (PDOexception $e) {     echo "Error is: " . $e-> etmessage(); } 

Output:

Connection is successful!  user_id-0000000001 name-person A sex-male 

Why does this happen?

like image 797
nut Avatar asked Mar 13 '13 12:03

nut


People also ask

How to fetch array in PHP PDO?

PDOStatement::fetchAll() returns an array containing all of the remaining rows in the result set. The array represents each row as either an array of column values or an object with properties corresponding to each column name. An empty array is returned if there are zero results to fetch.

How to use fetchAll in PHP?

The fetch_all() / mysqli_fetch_all() function fetches all result rows and returns the result-set as an associative array, a numeric array, or both. Note: This function is available only with MySQL Native Driver.

When using PHP PDOStatement fetch method the next row from a result set is retrieved?

Introduction to the PHP fetch() method Therefore, the subsequent call to the fetch() method will return the next row from the result set. To fetch all rows from a result set one by one, you typically use the fetch() method in a while loop. The fetch() method accepts three optional parameters.

What is the default data type for the fetchAll () result?

By default, user-missing values are converted to the Python data type None.


2 Answers

A PDOStatement (which you have in $users) is a forward-cursor. That means, once consumed (the first foreach iteration), it won't rewind to the beginning of the resultset.

You can close the cursor after the foreach and execute the statement again:

$users       = $dbh->query($sql); foreach ($users as $row) {     print $row["name"] . " - " . $row["sex"] . "<br/>"; }  $users->execute();  foreach ($users as $row) {     print $row["name"] . " - " . $row["sex"] . "<br/>"; } 

Or you could cache using tailored CachingIterator with a fullcache:

$users       = $dbh->query($sql);  $usersCached = new CachedPDOStatement($users);  foreach ($usersCached as $row) {     print $row["name"] . " - " . $row["sex"] . "<br/>"; } foreach ($usersCached as $row) {     print $row["name"] . " - " . $row["sex"] . "<br/>"; } 

You find the CachedPDOStatement class as a gist. The caching iterator is probably more sane than storing the result set into an array because it still offers all properties and methods of the PDOStatement object it has wrapped.

like image 82
hakre Avatar answered Oct 01 '22 10:10

hakre


Executing the same query again only to get the results you already had, as suggested in the accepted answer, is a madness. Adding some extra code to perform such a simple task also makes no sense. I have no idea why people would devise such complex and inefficient methods to complicate such primitive, most basic actions.

PDOStatement is not an array. Using foreach over a statement is just a syntax sugar that internally uses the familiar one-way while loop. If you want to loop over your data more than once, simply select it as a regular array first

$sql = "SELECT * FROM users"; $stm = $dbh->query($sql); // here you go: $users = $stm->fetchAll(); 

and then use this array as many times as you need:

foreach ($users as $row) {     print $row["name"] . "-" . $row["sex"] ."<br/>"; } echo "<br/>"; foreach ($users as $row) {     print $row["name"] . "-" . $row["sex"] ."<br/>"; } 

Also quit that try..catch thing. Don't use it, but set the proper error reporting for PHP and PDO

like image 27
Your Common Sense Avatar answered Oct 01 '22 08:10

Your Common Sense