PHP: cannot loop through mysql rows more than once - php

I'm working on pagination, and for some reason I cannot use mysql_fetch_array to loop through a result more than once.
//both $page and $imagesPerPage != 0
$offset = $page * $imagesPerPage
while ($row = mysql_fetch_array($result)) {
$total_images++;
}
echo $total_images;
//echos correct amount
$row = null;
$images_to_offset = 0;
while ($row = mysql_fetch_array($result) && $images_to_offset < $offset) {
$images_to_offset++;
}
echo $images_to_offset;
//echos 0... which is wrong
Should I be using a different php function to get row data in a database?
Thanks!

This is the error
while ($row = mysql_fetch_array($result)) {
$total_images++;
}
once you fetched the array the array pointer set to the end.
use this
$total_images=mysql_num_rows($result);
and
$images_to_offset=mysql_num_rows($result);
OR
To reset the position of pointer Use mysql_data_seek(). it moves internal result pointer

If you wish to start fetching from the beginning after you've already fetched, you'll need you use mysql_data_seek().
Also, please note that the mysql line of functions have been deprecated, and the community is encouraging use instead of MySQLi or PDO_MySQL lines of functions.

You could point the pointer back to the first row with mysql_data_seek.
mysql_data_seek($result, 0);
Also see: http://ca2.php.net/manual/en/function.mysql-data-seek.php

You have to 'rewind' the array, by using the mysql_data_seek function:
$offset = $page * $imagesPerPage
while ($row = mysql_fetch_array($result)) {
$total_images++;
}
echo $total_images;
//echos correct amount
$row = null;
mysql_data_seek(); // <-- rewind to the beginning
$images_to_offset = 0;
while ($row = mysql_fetch_array($result) && $images_to_offset < $offset) {
$images_to_offset++;
}
echo $images_to_offset;

mysql_fetch_array not only returns an array that corresponds to the fetched row, it also moves the internal data pointer ahead.
There are more than one way of dealing with this, the most obvious is to "park" your result in an array itself and then work from there. Or query 2 times. Or use mysql_data_seek. In your case, maybe mysql_num_rows is more appropriate, since your code indicates you only want to know how many rows you have to iterate through, and thats what this function is there for.
Whatever decide, keep in mind that use of the mysql extension is discouraged. Instead, the MySQLi or PDO_MySQL extension should be used.

Try using mysql_num_rows() , that way you don't have to iterate the $result twice which is giving you error in the second loop as you have to reset the result pointer. So do it like this which only iterates once:
//both $page and $imagesPerPage != 0
$offset = $page * $imagesPerPage
$total_images = mysql_num_rows($result);
echo $total_images;
//echos correct amount
$row = null;
$images_to_offset = 0;
while ($row = mysql_fetch_array($result) && $images_to_offset < $offset) {
$images_to_offset++;
}
echo $images_to_offset;
As a side note, you should try to migrate to MySQLi or PDO_MySQL to access mysql as the interface you are using is now deprecated, see the red box in http://es.php.net/manual/en/function.mysql-num-rows.php

You can only loop through the results array once, after that they effectively 'disappear'. the way to loop over the results multiple times is to store them into a new array during the first loop, then loop over the new array as many times as you want...

Related

Understanding mysqli_fetch_array()

Is there a way to make the code below cleaner?
I wanted to access the rows of $query4week like this: $query4week[0].
But mysqli_query() returns an Object on which I don't know how to access its particular rows. So, using fetch_array and a for loop I decided to create my own index.
$sql2 = "SELECT * FROM meals ORDER BY RAND() LIMIT 7";
$query4week = mysqli_query($con, $sql2) or die(mysqli_error($con));
for ($i = 0; $result = mysqli_fetch_array($query4week, MYSQLI_ASSOC); $i++)
{
$meal4week[$i] = $result['meal'];
}
I am still learning PHP and yet quite weak with OOP topics, please be patient :-)
Do it in this way
$i = 0;
while ($result = mysqli_fetch_array($query4week, MYSQLI_ASSOC))
{
$meal4week[$i] = $result['meal'];
$i++;
}
should work.
You shouldn't need a for loop if your fetching an associative array.
$i = 0;
while($row = mysqli_fetch_array($query4week, MYSQLI_ASSOC))
{
$meal4week[$i] = $row['meal'];
$i++;
}
There are already some perfectly reasonable answers here, but this is a little long for a comment. If all you are creating is a numerically indexed array starting with index 0, you don't need to explicitly define the index.
while($row = mysqli_fetch_array($query4week, MYSQLI_ASSOC)) {
$meal4week[] = $row['meal'];
}
should work just fine. No $i necessary.
mysqli_query returns you a resource which represents the query result. You need to use the mysql_fetch_* functions to iterate over the result row by row. So yes, you need some kind of loop, if you are interested in more than the first row.

While loop with assignment operator

I can't seem to figure out how this loop works in PHP:
$people = array();
while($row = $result->fetch_assoc())
$people[] = $row;
It seems as though the loop would just keep going, infinitely. But, it doesn't How exactly does this work? Can someone explain it to me step-by-step? I'm guessing that the while loop could also be written like this:
while(($row = $result->fetch_assoc()) == true)
The fetch_assoc fetches one result row at a time and stores it in $row. Since this is in a loop, you are fetching until you run out of rows
In the loop you are essentially pushing the $row value into a $people array
Your code:
$people = array();
while($row = $result->fetch_assoc())
$people[] = $row;
Example how its works (MySQL):
$people = array();
$result = mysql_query($query);
$rows_count = mysql_num_rows($result);
for ($i = $rows_count - 1; $i >= 0; $i--) {
mysql_data_seek($result, $i);
$people[] = mysql_fetch_assoc($result);
}
How U see first option is more compact.
fetch_assoc will return false either upon an error or when the cursor for the fetch hits the end of all the rows and no more rows can be fetched, so it will return false.
Every time you fetch for the query, a cursor keeps track of the last returned row and will continue to keep track ultimately till you finish reading all rows.
Edit: Sorry I was thinking about PDO and not mysqli, however it should be about the same thing.

How can I loop through a MySQL result set more than once using the mysql_* functions?

For whatever reason, I need to go through a MySQL result set twice. Is there a way to do it?
I don't want to run the query twice and I don't want to have to rewrite the script so that it stores the rows somewhere and then reuses them later.
This is how you can do it:
$result = mysql_query(/* Your query */);
while($row = mysql_fetch_assoc($result)){
// do whatever here...
}
// set the pointer back to the beginning
mysql_data_seek($result, 0);
while($row = mysql_fetch_assoc($result)){
// do whatever here...
}
However, I would have to say, this doesn't seem the right way to handle this. Why not do the processing within the first loop?
For mysqli you should do the following;
$result= $con->query($sql); // $con is the connection object
$result->data_seek(0);
Try whether mysql_data_seek() does what you need.
mysql_data_seek() moves the internal
row pointer of the MySQL result
associated with the specified result
identifier to point to the specified
row number. The next call to a MySQL
fetch function, such as
mysql_fetch_assoc(), would return that
row.
row_number starts at 0. The row_number
should be a value in the range from 0
to mysql_num_rows() - 1. However if
the result set is empty
(mysql_num_rows() == 0), a seek to 0
will fail with a E_WARNING and
mysql_data_seek() will return FALSE
Alternative to the data seek is to store the values into an array:
$arrayVals = array();
$result = mysql_query(/* Your query */);
while($row = mysql_fetch_assoc($result)){
$arrayVals[] = $row;
}
// Now loop over the array twice instead
$len = count($arrayVals);
for($x = 0; $x < $len; $x++) {
$row = $arrayVals[$x];
// Do something here
}
$len = count($arrayVals);
for($x = 0; $x < $len; $x++) {
$row = $arrayVals[$x];
// Do something else here
}
I confess I haven't tried this, but have you tried after your first iteration
mysql_data_seek($queryresult,0);
to go to the first record?
You can use mysql_data_seek to move the internal pointer to the beginning of the data set. Then, you can just iterate through it again.
Well, you could always count the number of rows you read, and then do something like this:
if (rownumber == mysql_num_rows($result)) { mysql_data_seek($result, 0); }
Don't know why you would need to, but there it is.

MySQL select first 5 rows after query

I have a mysql result (having many rows) that I will use later. For now, I only need to access (sum) the first 5 rows. The problem is that the rows were saved from the query using "AS", so now they can be accessed by using $row['name'] . How can I select the first 5 rows without using the "name" for each of them?
Is there any way for doing like so:
PHP:
for($i=0;$i<5;++$i)
echo $row[$i];
?
EDIT
Sorry, my question was wrong.
Actually: How can I use the same $result 2 times without loosing the values by fetching the array?
What do you use for working with DB? PDO? MySQLi? MySQL extension?
If you use MySQL extension (mysql_connect(), mysql_query() etc), you can use mysql_data_seek() to move the internal row pointer of the MySQL result:
$res = mysql_query($sql);
if ( mysql_num_rows($res) ) {
// process first 5 lines
for ( $n = 0; $n < 5; ++$n ) {
$row = mysql_fetch_assoc($res);
if ( $row === false ) {
break;
}
// do something with $row
// ...
}
// reset pointer
mysql_data_seek($res, 0);
// process all rows
while ( $row = mysql_fetch_assoc($res) ) {
// do something with $row
// ...
}
}
mysql_free_result($res);
Another option would be to fetch all results into an array and then work with that array. I can't think of any benefit of holding MySQL resource opened.
$result = array();
while( $row = mysql_fetch_array($queryResult) ) {
$result[$row['primaryKey']] = $row; // index the $result according to any fieldValue(say primay key) so that you can access a single records without looping)
echo $row['name'];
}
use $result as many times as you want
you can use mysql query as
select * from table_name_ravi limit 0,5
just use this
I think you mix up things. $row['name'] accesses the column of a row with the name name sou you should work on your fetch function your while( $row = mysql_fetch_assoc($result) ) {}

Resetting a while loop

I have found a confusing thing in a php script I am writing to generate some javascript. Here it is below, slightly simplified.
The second while loop won't run unless I comment out the entire first while loop. Can anyone explain why? Many thanks.
<?php
$listid = 2; //DEMO ONLY
$result1 = mysql_query("SELECT words.wid,words.wordmd5,words.word FROM words,instances WHERE words.wid = instances.wid AND instances.lid = \"$listid\"");
$result1copy = $result1;
$count1 = 1;
while( $row = mysql_fetch_object( $result1 ) )
{
print "words_left[$count1] = \"".$row->word."\";\n";
//Increment the array counter (starts at 1)
$count1++;
}
?>
//Some javascript
<?php
$count2 = 1;
while( $row = mysql_fetch_object( $result1copy ) )
{
print "
$count2 then $row->wordmd5
";
$count2++;
}
?>
You haven't copied the result set, you've just ended up with two references to the result set. The underlying result set object is the same regardless of which reference to it you use, and so you've already processed all of the records by the time the second loop begins.
You probably want to switch to using a single loop, and keeping track of the data you want to output in an array. Alternately, as Flinsch points out, you could use mysql_data_seek to return to the beginning of the result set, since you're using a buffered query.
In addition to what T.J. Crowder already said, a mysql_data_seek($result1, 0) would do the job between the two loops, to reset the internal iterator.

Categories