A While Loop Condition In PHP - php

I have seen the following while loop condition in many examples and even I have used it in many times. I know how it works and how to use it. But as i code the condition here doesn't make any sense.
As I see the code, the condition is like it's always true. Just like while(1). Because to the *mysql_fetch_assoc()*, the same data is passed is passed all the time. So the condition is a constant.
while($arr = mysql_fetch_assoc($data))
{
//other code
}
Now, where Am I Wrong ????

Each call to mysql_fetch_assoc gets the next row from the result set. If there is no row anymore it returns false and the loop terminates.
$data is a resource data type and will probably keep the state about which row was fetched last.
This is not so unusual, even arrays have an internal pointer to the current element which can be manipulated using certain array functions.

From the PHP website, mysql_fetch_assoc "Returns an associative array of strings that corresponds to the fetched row, or FALSE if there are no more rows."
Therefore, whenever there are still rows available, mysql_fetch_assoc will return an associated array of the row contents, will increment the pointer to the next row and the while loop will execute.
When there are no more rows mysql_fetch_assoc will return FALSE and the loop will break.
Also note that as of PHP 5.5.5 this function will be deprecated.

Related

PHP Gives Infinite While Loop when mysqli_fetch_assoc Expression is Replaced with just a Variable

I'm a complete newbie in PHP and I just don't understand how while loop works with mysqli_fetch_assoc. The former execute statements based upon expressions, the latter retrieves a row from the database. So if you don't end the loop, it will continue to iterate the field in the first row infinitely;
<?php
$connect_db=mysqli_connect('localhost','root','root','db');
$fetch_data="SELECT * FROM tabel";
$query_db=mysqli_query($connect_db,$fetch_data);
$fetch_row=mysqli_fetch_assoc($query_db);
while($fetch_row){
$column_2_array=$fetch_row['column_2'];
echo($column_2_array);
break;
}
?>
What I'm scratching my head is if the whole expression is put inside the parentheses instead of just the variable, then the loop will iterates the whole content of the column.
<?php
$connect_db=mysqli_connect('localhost','root','root','db');
$fetch_data="SELECT * FROM tabel";
$query_db=mysqli_query($connect_db,$fetch_data);
while($fetch_row=mysqli_fetch_assoc($query_db)){
$column_2_array=$fetch_row['column_2'];
echo($column_2_array);
}
?>
Why is it that on the second example above, after the first loop, while is iterating the subsequent rows on the selected column?
Clarifying my question further, if I take away break from the first example, then what is the difference between example 1 and 2? This is what confuses me since I thought they're identical.
To understand why this approach of looping mysqli_result works with a while loop you need to understand two things:
PHP uses type juggling. Each row returned by mysqli_fetch_assoc() will be an array. It is safe to assume that this array will never be empty, so the value will always be cast to true when used in boolean context.
mysqli_fetch_assoc() returns a single row from the result and moves an internal pointer to the next row. When pointer reaches the last row, each subsequent call will return NULL.
This while loop is equivalent to:
$fetch_row = mysqli_fetch_assoc($query_db); // save the first row in the variable. It could also be false
while($fetch_row) { // as long as $fetch_row is not false-ish
$column_2_array = $fetch_row['column_2'];
echo $column_2_array;
// fetch false or the next row
$fetch_row = mysqli_fetch_assoc($query_db)
}
Worth noting that such an approach to looping is not recommended. It is much easier to use a foreach loop. This will loop on the whole resultset one by one from the first row until the last. You can loop the same mysqli_result object multiple times.
foreach($query_db as $fetch_row) {
$column_2_array = $fetch_row['column_2'];
echo $column_2_array;
}
An even better alternative is to use fetch_all(MYSQLI_ASSOC) and store all rows in a multi-dimensional array. And as always, use PDO instead of mysqli whenever possible.
The simplest explanation is,
When you run mysqli_query() For successful SELECT, SHOW, DESCRIBE or EXPLAIN queries mysqli_query() will return a mysqli_result object which contains data from the database.
mysqli_fetch_assoc() - Fetch a result row(one row from the mysqli_result object) as an associative array at each time it called and moves the internal pointer to the next. $fetch_row is used to store that associative array containing data of single row getting from the mysqli_result object'
you can retrieve data belongs to that raw by using $fetch_row['column_name']
The while loop does the calling of mysqli_fetch_assoc() over and over. After one row is fetched, it goes to the next one and so on till it reaches the end of the object and returns NULL, which means false and breaks the while loop.
So in your first code sample,
$fetch_row=mysqli_fetch_assoc($query_db); will return and assign only one data row to $fetch_row (data type- assoc. array). Which makes the condition of the while loop true.

PHP: difference between array and variable containing an array?

In this [I-believe] famous loop condition
($row = $result->fetch()) (in which $result is a PDOStatement object) what is the type of the $row? Is it an "array" or an "array container"? Is there a difference between an array and a variable that holds an array?!
I ask this specially because if there wasn't any difference, then I should have been able to have my rows the whole in the $row variable after the loop is done, which is not the case, and I need another array to hold each row for me(the syntax is also different and I need empty brackets in front of the name of that array to add elements)
(According to my tutorial, fetch() is a method of the PDOStatement object that returns the next row of my table as an array).
Actually
$row is a run-time array variable which is re-created each time when loop (while loop) runs.So previous values will not be available. That's why you have to save it's data to another array variable which is created statically.
Is this recreation an intrinsic quality of the while loop?
Simon.B no it's not.
You can try
$row = [];
while($row[] = $result->fetch()){};
print_r($row);
and check.
Better alternative is to use fetchAll();
But why this above apporach is not used often:-
Because above approach will load the whole array again and again into Memory when loop runs and then assign array to that.
While when you are using run-time variable and doing assignment then the whole array is not loaded each time, only assignment will done.

MySQLi fetch_all Error with Consecutive Calls

I've set up a class to handle my MySQLi calls. The calls are working as they should, so no problems there.
I recently removed the result handling from my class's query method to two separate setter methods. There is now an error resulting from two consecutive fetch_all calls.
The previous (working) code with a single fetch_all call loads results into the two arrays res_rows and res_cols:
// Convert results into two sets of values
// and store in properties
// $res_rows=results by row (column names in element 0)
// Each row is an indexed array
// $res_cols=results by column (associative arrays)
// Key is the column name; Value is an array
$results=$res->fetch_all(MYSQLI_ASSOC);
// $colNames is an array of the column names
$colNames=array_keys($results[0]);
// Rows
foreach($results as $r) {
$this->res_rows[]=array_values($r);
}
array_unshift($this->res_rows,$colNames);
// Columns
$vals=array();
// Count the number columns in the query
$numCols=count($colNames);
// Iterate through the columns
for($i=0;$i<$numCols;$i++) {
$col=$colNames[i];
$storage=array();
foreach($results as $r) {
$storage[]=$r[$colNames[$i]];
}
$vals[]=$storage;
}
$this->res_cols=array_combine($colNames,$vals);
I've moved this code into two methods setRes_rows and setRes_cols and called them sequentially (see code). Each method pulls results from the result object using fetch all.
$this->setRes_rows($res);
$this->setRes_cols($res);
What happens is that the first call behaves as expected, and the second call returns an empty array.
If I reverse the calls (e.g. setRes_cols first), the same thing happens (first call works as expected; second call is empty). So I know the code is good. I even changed all the variable names in one of the methods with no effect.
I dumped all properties and methods on the result object between calls and it doesn't look like it changes. But for some reason that second fetch_all does not work.
The easy fix is for me to use a single fetch_all then call my methods. But I'm interested in knowing if there's anything weird I'm missing.
Thanks, everyone.
It looks like you need to reset the result pointer after a fetch_all.
I didn't find anything in the docs specifically for fetch_all - only about resetting after a fetch_assoc(), where we can find a reference to data_seek(): http://php.net/manual/en/mysqli-result.data-seek.php
So here's what you should do:
before the second fetch_all() do a
$res->data_seek(0); // where $res is your mysqli result Object
This basicly sets the result pointer to the first record.

Why "while" loop is always used to iterate through mysql_fecth_array() function result?

Why don't people use for ,foreach or do..while() and why omit increment counter in while?
`<?php while ( $fa = mysql_fetch_array($sel1) )//uesd mysql_fetch_array() function in while loop
{
echo $fa['cid'];//display client id
}
// while Syntax in w3school give to used this
$x = 1;
while($x <= 5) {
echo "The number is: $x";
$x++;
}
?>//show why we don't used mysql_fecth_array() like this
This is kind of dated information. In one way you're asking a question that is just accepted along the community. It is understood better that while I have information to show ... do something. You generally wouldn't say foreach of these items ... do something though you could. However, the other problem is mysql_fetch_array returns FALSE if there are no more rows. This would not work in a foreach because it is not an array. A for would also fail because to check for the finishing of a for you have to go to some point and end.. FALSE is not a valid point of check (that I have ever tried or used).
#Michael Berkowski Adds:
As of PHP 5.4+, the mysqli_result class does have Iterator support, meaning you can do $result = mysqli_query(...); and subsequently foreach ($result as $row) {...} and it will fetch associative arrays
Though this isn't to be said the most commonly used form which is why we have the question.
You could do...while but why would you. You don't have most the information that you're going to need from the fetch array.
While is accepted and generally better. Doesn't fail and has a fall back if the mysql fails any way.
Lastly... don't use mysql_* anymore. Switch to mysqli_*. Safer.. smarter.. better.
You can perfectly use any other loop to get the query results. The reason why people mostly use while loop is because it simply is the easiest way. The reason for that is that without any extra line of code we don't know how many rows were returned and so we don't know how many times we have to iterate to get all the rows from the result. Everytime mysql_fetch_array() is executed, it gives us the next row of data and when it runs out of rows it returns false. So using while loop we basically say: While there is still a new row, we take the data from it, fetch the next row and when we run out of rows, we stop.
You can accomplish the same with for loop for example. It's just not that straightforward.
Using for loop to iterate mysql_fetch_array() :
$r = mysql_query($query);
$num_rows = mysql_num_rows($r);
for($i = 0; $i < $num_rows; $i++) {
echo mysql_fetch_array()[$id];
}
Other choice would be to place an if statement inside the for loop to check if there are any new rows, when not, we can exit the for loop.
Using the while loop we kinda combine the loop and the if statement.

How can i find out if I am at the last row in a data set?

I would appreciate some help on this, I have a result set which I am trying to work with. The result contains 2 fields and any number of rows.
In calling fetch_row() how can you tell if the method has got to the last row?
I am iterating through the rows using:
while(list($className, $classID) = $result->fetch_row()) {
echo "<tr><td>$className has ID $classID.</td></tr>"
// Here, if the loop is for the last time I need to allow some extra code to run
// echo "<tr><td>Last Item.</td></tr>"
}
I was thinking about having an incremental counter in the while loop which compares the row to num_rows but was thinking that there must be a slicker was of telling if you have reached the last row
Any advice much appreciated.
Many Thanks
ShaunMc
I was thinking about having an incremental counter in the while loop which compares the row to num_rows but was thinking that there must be a slicker was of telling if you have reached the last row
Nope, I think that is actually the only way to do this, regardless of which DB wrapper you're using (I assume it's PDO.)
It's a shame really: PHP should have something like this built in, at least in foreach constructs. But it doesn't.
fetch_row() returns null when it hits the end of the result set.
http://php.net/manual/en/mysqli-result.fetch-row.php
Or am I missing something.

Categories