This is probably a silly beginner question and i don't think it's limited to mysqli_fetch_assoc() so it's probably a general programming question.
Anyways, i have this PHP code for getting data from a database using mysqli
$sql = "SELECT name FROM table1";
$result = mysqli_query($conn, $sql);
if($result){
if(mysqli_num_rows($result) > 0){
while($row = mysqli_fetch_assoc($result)){
echo "Name: " . $row["name"]. "<br>";
}
}
}
What i don't understand is how the while loop there works. How does it iterates to the next element and know when to end? mysqli_fetch_assoc() returns a associative array which is stored in row variable which means it is not null therefore true and let's the while loop run. What i don't understand is how it iterates through the rows and ends when there are no more rows left. I'm not specifically doing anything to change the row to the next one so how does it do it on it's own?
Also mysqli_fetch_assoc() returns a associative array so shouldn't "name" key contain 1 element? Or is it a array of all the rows in that column?
(I hope you can understand what i'm trying to say, i'm not the best at explaining .-.)
Edit: What i don't understand is how this code iterates through all the rows. Is it part of the "inbuilt code" in this function? (I couldn't find it anywhere to confirm)
Each time when
mysqli_fetch_assoc($result) is accessed, the pointer moves to the next record. At last when no records are found, it returns null which breaks the while condition.
Eventually, when mysqli_fetch_assoc($result) runs out of rows it will return NULL, which evaluates to false, which breaks out of the loop.
$row results in a single row in the database, so $row['name'] would be the value of 'name' for a particular row.
Let's break it down, with perhaps a dumbed down example of how it works internally (Please note, this works a lot more efficiently, and wont actually run multiple queries):
$result = ['currentRow' => 0, 'query' => 'SELECT name FROM table1'];
while ($row = mysqli_fetch_result($result)) {
}
//First iteration
mysqli_fetch_result queries 'SELECT name FROM table1 LIMIT 0, 1'
it increments internally $result['currentRow'] to 1
it returns the row that was found
//Second iteration
mysqli_fetch_result queries 'SELECT name FROM table1 LIMIT 1, 1'
it increments internally $result['currentRow'] to 2
it returns the row that was found
//Third iteration
mysqli_fetch_result queries 'SELECT name FROM table1 LIMIT 2, 1'
no rows returned! Just simply return null (This will cause your while loop to break out)
You always pass $result as an argument to mysqli_fetch_assoc. This argument holds the iterator information, which will be used by mysqli_fetch_assoc to advance each time you call this function to the next row.
During each iteration, $row['name'] will be a single string.
Related
<?php
$connect = mysqli_connect("localhost", "root", "", "hempbag_db") or die("Connection failed");
$query= "Select * from tbl_sales";
$ress = mysqli_query($connect, $query);
$result = mysqli_fetch_array($ress);
foreach($result as $a)
{
echo $a['ID']; // This doesnt print although i used fetch array
}
foreach($ress as $a)
{
echo $a['ID']; // This works why???? This variable has only query run
}
?>
Why does the upper foreach does not run and lower one does? Can anyone explain please?
When you run a query, it returns a result:
$ress = mysqli_query($connect, $query);
var_dump($ress); // You will see it's a result.
At this point $ress just contains the result of what you just queried. Think of it like this:
You goto the warehouse, and you make and order for 1000 boxes of crackers. She heads to the back, and gets your boxes ready, and comes back and hands you a piece of paper with the order number. (This is $ress). Now, you can't loop through that, you can't do anything with that.
You now take that piece of paper, and you hand it to your assistant, and you say you want to get all the crackers on your trucks (This is now mysqli_fetch_array()). Your assistant goes, fetches it, and returns you the crackers.
Simply put, mysqli_query just returns an object like Result#1. From Result#1, mysql can tell you how many rows were returned mysql_num_rows(Result#1), or get actual data if it was a select query: mysqli_fetch_array(Result#1).
Now onto the reasoning: Performance. Let's say you didn't want 1000 crackers, you just wanted to know if they had 1000 crackers. If she came back with all the boxes of crackers and you had to count them yourself, it would be much more difficult. Instead, with that piece of paper, she can determine how many boxes you were able to order. Less data being transferred, and much more efficient.
Just a small note, in later versions of php, they made it so the result is iterable, meaning that if you try and loop through it, it will automagically call mysqli_fetch_array on that result, and return you the results.
Additionally, mysql_fetch_array will return one row from the database, and is not able to be looped through via foreach. Perhaps you were thinking of mysqli_fetch_all? This returns all rows and can be looped through (Although is a bit less performant than using a while loop with mysqli_fetch_array)
$ress = mysqli_query($connect, $query);
This line returns a result set which is Traversable. So your second foreach works fine.
whereas the following line (mysqli_fetch_array) gets one row at a time and makes it an array.
$result = mysqli_fetch_array($ress); // Suppose you have 3 rows, Now cursor is at row 1
echo $result["ID"]; // this will print FIRST row's ID
$result = mysqli_fetch_array($ress); // Now cursor is at row 2
echo $result["ID"]; // this will print SECOND row's ID.
$result = mysqli_fetch_array($ress); // Now cursor is at row 3
echo $result["ID"]; // this will print THIRD row's ID.
To echo all IDs
while($result = mysqli_fetch_array($ress)) {
echo $result["ID"];
}
I have one question about mysqli_fetch_assoc in a while loop.
$query = "SELECT * FROM category ";
$result = mysqli_query($connection, $query);
while($row = mysqli_fetch_assoc($result))
{
$cat_id = $row['cat_id'];
$cat_title = $row['cat_title'];
echo $cat_id . " " . $cat_title ."<br>";
}
So, how does $row = mysqli_fetch_assoc($result) work?
So it loops one row at a time from $results and stores that information in $row until it there is no row to return?
And this mysqli_fetch_assoc($result) in while loop iterations is this " array(some rows that it got from $result) "?
$row = mysqli_fetch_assoc($result) is same as $row = array(all rows from $result that are gathered by mysqli_fetch_assoc) ?
And that means $row is actually an array, and every time it loops the information is not overwriten by new instead it is added?
When using the mysqli_fetch_assoc() function, PHP is placing the data from the database into an associative array. You can then pull the data out of the array inside of the loop.
Since there is no incrementation to tell the loop when to stop, the while loop takes care of that. So you could read it like so:
While the mysqli_fetch_assoc() has more records, keep looping. When it runs out, stop.
Returns an associative array that corresponds to the fetched row or NULL if there are no more rows. - from PHP manual on mysqli_fetch_assoc()
Whenever you call get_result() or mysqli_query() you will receive a mysqli_result object. This object contains the data fetched from the MySQL database server. The data from SQL is returned to PHP in rows. The purpose of mysqli_fetch_assoc() is to fetch a row from this object and move an internal pointer to the next row. Next time you call this method on the same object it will fetch a second row and move the pointer to the next row. Once a pointer moves beyond the last row this function will keep on returning NULL.
The values in each of the returned arrays correspond to a single row from the MySQL result set. The values are stored as an associative array. Each key is a column name from the SQL.
The purpose of the while loop is to simply call the same function over and over again until it returns NULL.
Bear in mind that using while loop is not the best approach. It is better to simply use foreach.
$query = "SELECT * FROM category ";
$result = $connection->query($query);
foreach ($result as $row) {
$cat_id = $row['cat_id'];
$cat_title = $row['cat_title'];
echo $cat_id . " " . $cat_title ."<br>";
}
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. $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 $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.
I'm trying to run if and else if inside a while loop in my PHP code.
The code looks like this:
<?php
$sql = "SELECT * FROM table ORDER BY id";
$query = mysqli_query($db_conx, $sql);
$productCount = mysqli_num_rows($query);
if ($productCount > 0) {
while($row = mysqli_fetch_array($query, MYSQLI_ASSOC)){
$deviceType = $row["deviceType"];
if($deviceType == 'iPhone' || $deviceType == 'iPad'){
echo 'IOS';
}else if($deviceType == 'Android'){
echo 'Android';
}
}
} else {
}
?>
The code above works (sort of) but not as I was expecting it.
To give you an example, lets say I have 2 rows in MYSQL database.
like this:
id deviceType
1 Android
2 iPhone
when i run my PHP code above, I get this echo-ed on my page:
IOS
IOS
Android
Android
BUT I only have 2 rows in the database so the result should be:
IOS
Android
Could someone please advise on this issue?
This question is clearly misrepresenting your actual code/data.
When your database table has 2 rows, but you are receiving 4 rows then the onus is not on the fetching function, but on your query or database table data.
If your actual query is as posted in your question, then your table data contains more than two rows.
If your actual query is different from what you posted (say, joining the table with a copy of itself), then your data is fine and your query is failing you.
Regardless of if you are using mysqli_fetch_array($result), mysqli_fetch_array($result,MYSQLI_ASSOC), or mysqli_fetch_assoc($result), your while() loop will only do one iteration for each row of data.
The difference in resultset fetching functions:
mysqli_fetch_array($result):
array(0=>'1', 'id'=>'1', 1=>'Android', 'deviceType'=>'Android') // 1 row w/ 4 elements
array(0=>'2', 'id'=>'2', 1=>'iPhone', 'deviceType'=>'iPhone') // 1 row w/ 4 elements
mysqli_fetch_array($result,MYSQLI_ASSOC), or mysqli_fetch_assoc($result):
array('id'=>'1', 'deviceType'=>'Android') // 1 row w/ 2 elements
array('id'=>'2', 'deviceType'=>'iPhone') // 1 row w/ 2 elements
I will rewrite your code and implement some good practices:
if($result=mysqli_query($db_conx,"SELECT `deviceType` FROM `table` ORDER BY `id`;")){
if(mysqli_num_rows($result)){
while($row=mysqli_fetch_assoc($result)){
echo ($row["deviceType"]=="Android"?"Android":"IOS"); // inline condition is a personal preference
}
}else{
echo "No rows in `table`.";
}
}
Only bother declaring a variable if you will use its value more than once (*or if it dramatically improves readability to separate it from its single use.)
So that your variable names are intuitive, name your query variable $sql or $query; and name your query's result variable $result.
Only SELECT columns that you intend to use; * is unnecessary for your case.
Backtick ` wrapping is not required on column and table names, but doing so will avoid any potential clashes with MySQL keywords.
Perform a conditional check and declare the $result variable as false or [resultset] in a single step.
Always check that $result is true before calling any functions that access the resultset. (e.g. mysqli_num_rows() and mysqli_fetch_assoc()).
if(mysqli_num_rows($result)){ will check for a non-falsey value -- I mean 0 equates to false and anything greater than 0 will be true.
Your code appears to be perfectly fine. However, instead of the expected output, you get more items than needed. If I am not mistaken, this means that you have duplicate deviceType in your database table. $productCount probably has a value of 4. You can get two values if you use this query instead:
SELECT DISTINCT `deviceType` FROM `table` ORDER BY `id`
but while this should fix the output you get, your data will still hold duplicates, so you might want to look into the data of your table and into the way it was created, find out and fix the problem.
the answer is very simple you are fetching the results twice with the while loop change this line
while($row = mysqli_fetch_array($query, MYSQLI_ASSOC)){
to
while($row = mysqli_fetch_assoc($query)){
then it will work right, you can see buy the order iPhone iPhone android android that is doing it twice instead of once per loop
I am trying to run a query to my mysql database through php and and am trying to get all the resulting rows. I also have to compare every row to the next row returned. I am trying to do this by setting the result variable to another temporary variable and calling mysqli_fetch_assoc() on that so that the while loop runs again for the next row. But what happens is that when I try to use mysqli_fetch_assoc() even on the other variables, somehow mysqli_fetch_assoc($result) also progresses to the next of the next row when while($row = mysqli_fetch_assoc($result)) goes to next iteration.
Here is the code example to illustrate this :
$query = "SELECT * FROM records ORDER BY num ASC;";
if($result = mysqli_query($conn, $query))
{
while($row = mysqli_fetch_assoc($result))
{
$temporaryresult = $result;
$rowtwo = mysqli_fetch_assoc($temporaryresult);// this makes mysqli_fetch_assoc($result) skip the next row which is unwanted
}
}
So how can I keep mysqli_fetch_assoc($result) from moving forward when I call mysqli_fetch_assoc($temporaryresult) ?
Any help would be appreciated.
am trying to do this by setting the result variable to another temporary variable and calling mysqli_fetch_assoc() on that so that the while loop runs again for the next row
It doesn’t work that way. Just because you assigned the resource id to a second variable, doesn’t mean that you now have a second result set that you could operate on separately. Both variables refer to the same resource id. Fetching a row will still move the row pointer of the “original” data set.
I also have to compare every row to the next row returned
Most likely, you are making things harder on yourself by trying to look ahead. Stuff like this is usually easier done when you look at the previous row instead. That one you have fetched already - so you don’t need to do an additional fetch now that would mess with the row pointer.
Pseudo code example:
$prevRow = null;
while($row = fetch(...)) {
if($prevRow) { // for the first row, this will still be null, so we only
// start comparing stuff when that is not the case
// compare whatever you need to compare here
}
...
$prevRow = $row;
}
After #CBroe's answer, I tried to solve this problem while still trying to look forward. I achieved this by storing the rows returned by the database and then looping through them. This makes it very easy too look ahead in the rows returned while avoiding the complexity of changing your code to look backwards.
$array = array();
// look through query
while($row = mysql_fetch_assoc($query)){
// add each row returned into an array
$array[] = $row;
}
Now, looping through these rows,
$i = 0;
for(;$i<count($array)-1;$i++)
{
if($array[$i]['somecolumn']==$array[$i+1]['anothercolumn'])//compare this column to another column in the next row
{
// do something
}
}
This successfully solved my problem. I hope it helps anyone stuck in the same position I was in.
I have a mysql query:
$a=mysql_query("SELECT id FROM table1 WHERE p2='fruit' LIMIT 1");
This will only ever return one result or none.
I'm trying to first count the results, then if it 1, to pass the returned id to a variable.
Question: If I do
$results=count(mysql_fetch_assoc($a));
to count the number of rows returned, can I still do later
while($row = mysql_fetch_array($a)){
$id=$row['id'];
}
or will the first delete the array somehow???
Is their a better way to do all this?
You really not need to do anything if there is one row or null
Consider below code it will set id value if there is 1 row fetched otherwise it will be null
$id=''
while($row = mysql_fetch_array($a)){
$id=$row['id'];
}
No count needed.
$results=count(mysql_fetch_assoc($a));
does not count the number of rows as mysql_fetch_assoc returns one row. I believe you're looking for mysql_num_rows:
$results = mysql_num_rows($a);
$num_rows = mysql_num_rows($a);
You can then do an IF statement on this and later do a while loop on the fetched array
Have you tried mysql_num_rows ??
http://php.net/manual/en/function.mysql-num-rows.php
What happens when using:
while($row = mysql_fetch_array($a)){
$id=$row['id'];
}
it is just like reading a file,every time mysql_fetch_array($a) is called the next line is parsed untill it reaches the end of the file. A cursor of some sort is known in the background. Meaning that if you would enter by hand
//backgroundCursor = 0
$row = mysql_fetch_array($a)
//backgroundCursor = 1
$row = mysql_fetch_array($a)
//backgroundCursor =2
$row = mysql_fetch_array($a)
//backgroundCursor = 3
The while instruction just automates the stuff.
mysql_fetch_array increases the background cursor at every call so if you call it twice it will not give you the same line.
To get a clear view on this read something about reading from a file line by line.
No you cannot as each call to mysql_fetch_assoc() loads a new row, if there is any. You could indeed assign both variables at once:
$results=count($row = mysql_fetch_assoc($a));
but
But mysql_fetch_assoc($a)) returns false and as the result of count(false) is 1 this will not tell you anything. Besides, if there is no row all you really need is $row = mysql_fetch_assoc($a) and test if ($row) {...}.