Assume I'm in need to loop twice with the result I got form PDO prepared statement.
First loop works fine, the next one does not work
The value of var_dump(q->fetch()) is empty array. Any ideas?
<?php
$q = $dbconnection->prepare("SELECT * from users WHERE role=?");
$q->execute(array('$id')); //Boolean true or false
// first loop
while ($row = $q->fetch(PDO::FETCH_ASSOC)) {
echo "<br/>" . $row['user_id'] . "--". $row['fname']. "</br>";
}
// second loop this loop will NOT echo any thing ?!
while ($row = $q->fetch(PDO::FETCH_ASSOC)) {
echo "<br/>" . $row['user_id'] . "--". $row['fname']. "</br>";
}
When you loop the row, you empty out the result set. If you want to loop over multiple times, you can use fetchAll(), store that in a variable and loop that where you need using a foreach loop.
$q = $dbconnection->prepare("SELECT * from users WHERE role=?");
$q->execute(array($id)); //Boolean true or false
$res = $q->fetchAll();
foreach ($res as $row) {
echo "<br/>" . $row['user_id'] . "--". $row['fname']. "</br>";
}
foreach ($res as $row) {
echo "<br/>" . $row['user_id'] . "--". $row['fname']. "</br>";
}
Alternatively, you can execute the query again, but if you do that, you make a double query to the database. So you query twice for the same data, which isn't very efficient.
Also you had execute(array('$id')), which would be the exact string $id, and not the variable representation. See the PHP manual on strings. So it should be execute(array($id)) instead.
PHP.net on PDOStatement::fetchAll()
Your are fecth a row time by time if you need two iteration you should perform a copy eg storing rows
while ($row = $q->fetch(PDO::FETCH_ASSOC)){
echo "<br/>" . $row['user_id'] . "--". $row['fname']. "</br>";
$my_rows[] = $row;
}
// second loop this loop will NOT echo any thing ?!
foreach($my_rows as $key=>$value){
echo "<br/>" . $value['user_id'] . "--". $value['fname']. "</br>";
}
Related
I am using the entries from a database to fill a row and a column in a table. But I cannot access the SQL returned data twice using mysqli_fetch_array() twice. I need to loop mysqli result more than once. This doesn't work:
//Copy the result
$db_res = mysqli_query( $db_link, $sql );
$db_res2=$db_res;
//Top row
while ($row = mysqli_fetch_array( $db_res, MYSQL_ASSOC))
{
echo "<td>". $row['Title'] . "</td>";
}
//leftmost column
while ($row = mysqli_fetch_array( $db_res2, MYSQL_ASSOC))
{
echo "<tr>";
echo "<td>". $row['Title'] . "</td>";
.....
echo "</tr>";
}
How can I apply mysqli_fetch_array twice on the same result?
You should always separate data manipulations from output.
Select your data first:
$db_res = mysqli_query( $db_link, $sql );
$data = array();
while ($row = mysqli_fetch_assoc($db_res))
{
$data[] = $row;
}
Note that since PHP 5.3 you can use fetch_all() instead of the explicit loop:
$db_res = mysqli_query( $db_link, $sql );
$data = $db_res->fetch_all(MYSQLI_ASSOC);
Then use it as many times as you wish:
//Top row
foreach ($data as $row)
{
echo "<td>". $row['Title'] . "</td>";
}
//leftmost column
foreach ($data as $row)
{
echo "<tr>";
echo "<td>". $row['Title'] . "</td>";
.....
echo "</tr>";
}
Yes. mysqli_fetch_array() moves the pointer forward each time you call it. You need mysqli_data_seek() to set the pointer back to the start and then call mysqli_fetch_array() again.
So before calling the function a second time, do:
mysqli_data_seek($db_res, 0);
You don't need the while loop and you don't need to use mysqli_fetch_array() at all!
You can simply loop on the mysqli_result object itself many times. It implements Traversable interface that allows it to be used in foreach.
//Top row
foreach($db_res as $row) {
echo "<td>". $row['Title'] . "</td>";
}
//leftmost column
foreach($db_res as $row) {
echo "<tr>";
echo "<td>". $row['Title'] . "</td>";
.....
echo "</tr>";
}
However, you should separate your DB logic from your display logic and to achieve this it is best to use fetch_all(MYSQLI_ASSOC) in your DB logic to retrieve all records into an array.
If you fetch all the data into an array, you can loop that array as many times as you want.
$data = $db_res->fetch_all(MYSQLI_ASSOC);
foreach($data as $row) {
// logic here...
}
$squery = mysqli_query($con,"SELECT * FROM table");
while($s = mysqli_fetch_array($query)){
....
}
// add this line
mysqli_data_seek( $query, 0 );
while($r = mysqli_fetch_array($query)){
...
}
try it.....
I have a query which is supposed to retrieve data from mysql and print it on the browser. It is working with a few rows of data but when the data gets bigger it just stops working and doesn't give any errors.
$result = mysql_query($query);
$json_array = array();
while($row = mysql_fetch_assoc($result)){
$json_array[] = $row;
}
print mysql_error();
print json_encode($json_array);
I have tried everything but nothing seems to work.
I'm very surprised it works at all.
This would work if $row was formatted.
Use foreach()
I doubt this would work either:
foreach($json_array as $row){
echo "$row<br>\n"
}
This should work (replace colx with the name of the table columns):
foreach($json_array as $row){
echo $row['col1'] . ', ' . $row['col2'] . ', ' . $row['col2'] . "<br>\n"
}
foreach($json_array as $row){
echo $row['name'] . ', ' . $row['address'] . ', ' . $row['phone'] . "<br>\n"
}
#Lessmore has right, maybe the PHP process has reached the memory limits in the server, try with less columns or registers, but I understand your need, then you need to write your self json_encode code to write row by row. Some like this:
$first = null;
header('Content-Type: application/json');
echo '[';
while ($row = mysql_fetch_assoc($result)) {
if ($first) {
echo ',';
}
echo json_encode($row);
!$first && $first = true;
}
echo ']';
exit;
I have problem with my code.
I use nested while in my code and the nested while doesn't work, only the outer while is work
I don't know where is the bug of my code.
This is the piece of my code :
$database = new mysqli('127.0.0.1', 'user', 'user', 'mini_email');
$query = 'SELECT * FROM mails';
$query2 = 'SELECT * FROM users';
$result_set = $database->query($query);
$result2 = $database->query($query2);
while ($row2 = $result2->fetch_assoc()) {
if ($row2['username'] == $_SESSION['user']) {
$id_email = $row2['id'];
}
}
if (isset($_SESSION['is_logged_in'])) {
echo('<center><font size="10">Mailing List</font></center><br><br>');
echo('<center><table border="3" bgcolor="#f0cdfa">');
echo('<tr>');
echo ('<td>No</td>');
echo ('<td>ID</td>');
echo ('<td>From</td>');
echo('<td>Subject</td>');
echo ('<td>Message</td>');
echo ('<td>Action</td>');
echo ('</tr>');
$i = 1;
while ($row = $result_set->fetch_assoc()) {
if ($row['to_user_id'] == $id_email) {
echo('<tr>');
echo ('<td>' . $i . '</td>');
echo ('<td>' . $row['id'] . '</td>');
while($row2 = $result2->fetch_assoc()){
if($row2['id']== $row['from_user_id']){
echo ('<td>' . $row2['username'] . '</td>');
}
}
echo ('<td>' . $row['subject'] . '</td>');
echo ('<td>' . $row['message'] . '</td>');
echo ('<td>View</td>');
echo ('</tr>');
$i++;
}
}
Your initial
while ($row2 = $result2->fetch_assoc()) {
is looping through all the records to the end of the set,
so looping a second time won't retrieve any further records because you're already at the end of the resultset
Resultset pointers aren't automatically reset when you initiate a new loop, but you can reset them manually using
$result2->data_seek(0);
before each subsequent loop
But iterating the point made in the comments by #Sirko you'd be better using a JOIN to make a single query
If I may help, I think you shouldn't even perform the queries when your if statement with the session returns false.
In the first lines or your script you should define a function with all this code, and write it like this :
function YourFunction()
{
if (isset($_SESSION['is_logged_in'])) {
return false;
}
// Database connection and queries
// your business
}
This will be more clean.
Next, your query doesn't seem to be correct. You get all the mails of your website, and then in a loop you check if the mail user id is the user id you have in session. Imagine the lack of performance if you have 35 000 mails in your database.
Improve your query with a WHERE statement : http://www.w3schools.com/sql/sql_where.asp
then, are you sure that $_SESSION['user'] contains an id ? I think your second if statement never returns true because of that.
<?php
$con=mysqli_connect("","","","");
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$result = mysqli_query($con,"SELECT * FROM itiraf");
$result2 = mysqli_query($con,"SELECT oy FROM users WHERE username='". $Account->session('display_name') ."'");
if(mysqli_num_rows($result)=="0"){echo "Henüz itiraf yapılmamış";}
else{
echo "<table border='1' class='imagetable'>
<tr>
<th>NO:</th>
<th>İsim</th>
<th>İtiraf</th>
<th>Oy</th>
<th>Oy Kullan</th>
</tr>";
while($row = mysqli_fetch_array($result)){
echo "<tr>";
echo "<td><b>" . $row['id'] . "</b></td>";
echo "<td><b>" . $row['username'] . "</b></td>";
echo "<td><b>" . $row['itiraf'] . "</b><br></td>";
echo "<td><b>" . $row['oy'] . "</b><br></th>";
while($row2 = mysqli_fetch_array($result2)){
if ($row2['oy'] ==10) { echo "<td>Oy kullandınız</td>";}
else{echo "<td><a href='oy.php?id={$row[id]}'><img src='assets/images/up.png'/></a></td>";}}
echo "</tr>";
echo "</form>";}
echo "</table>"; }
mysqli_close($con);?>
first while is working. also Second while is working but not so well. just one time i can see the thumbs up image. i added all code in here about table. any idea?
In pseudo code, it appends :
{ //first iteration of while($row = mysqli_fetch_array($result))
...
{ //first iteration of while($row2 = mysqli_fetch_array($result2))
}
{ //Second iteration of while($row2 = mysqli_fetch_array($result2))
}
...
{ //last iteration of while($row2 = mysqli_fetch_array($result2))
}
// know, $result2 is empty
}
{//Second iteration of while($row = mysqli_fetch_array($result))
...
//Here, $result2 is empty, so the second while loop doesn't work
}
if you want to reuse $result2, you can store it in an array before, and then use this array in the while loop
Your second while loop iterates over the query result stored in $result2.
So, the first time the second while loop is executed fully, cursor moves to the end of the table and does not come back to the first position.
One solution would be to store all the values of the second query(whose result is in $result2) in another array, and then use that array in the second while loop.
Another solution would be to move the second query itself inside the first while loop, but that would mean that the query will be executed everytime.
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?
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.
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
This is because you are reading a cursor, not an array. This means that you are reading sequentially through the results and when you get to the end you would need to reset the cursor to the beginning of the results to read them again.
If you did want to read over the results multiple times, you could use fetchAll to read the results into a true array and then it would work as you are expecting.
$users = $dbh->query($sql);
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
Here $users is a PDOStatement object over which you can iterate. The first iteration outputs all results, the second does nothing since you can only iterate over the result once. That's because the data is being streamed from the database and iterating over the result with foreach is essentially shorthand for:
while ($row = $users->fetch()) ...
Once you've completed that loop, you need to reset the cursor on the database side before you can loop over it again.
$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/>";
}
Here all results are being output by the first loop. The call to fetch will return false, since you have already exhausted the result set (see above), so you get an error trying to loop over false.
In the last example you are simply fetching the first result row and are looping over it.
$row = $db->getAllRecords(DB_TBLPREFIX . '_payplans', '*', ' AND ppid = "' . $myid . '"');
foreach ($row as $value) {
$bpprow = array_merge($bpprow, $value);
}
This is based on PHP functions where you can globally use this data.