Nested While loop only runs inside loop correctly - php

I've got two while loops that I'm using to run through some MySQL data.
The first while loop runs through a bunch of reports and checks the 'state' (as in United States) that is stored in the table.
Within that loop, I'm checking a second table with a while loop for 'state' as well and if the states match then I push some info to an array. I got rid of the other code for simplicity's sake here.
Basically, I started with the first while loop and logged all the info to the console and it successfully looped through all the entries in the table.
I then put the nested while loop in there and when I try to alert or log it to the console, it's only looped through the instances of the first entry in the parent loop.
What I mean is that in the $row_wind loop, the first entry is CT (Connecticut). When I log out the parent loop, it logs everything in that table (with CT being the first one). When I use the below code it's logging just CT and then all the entries in the child loop but doesn't counter the parent loop after that. Am I not able to nest while loops?
while($row_wind = mysqli_fetch_array($sql_wind_result)){
while($row_alert = mysqli_fetch_array($result_user_alerts)){
echo "<script>alert('".$row_wind['state']." ".$row_alert['state']."');</script>";
}
}

mysqli_fetch_array is similar to array_pop() in that once it fetches a result, it's not going to fetch that result again.
So my guess is that your $row_wind loop is actually running through just fine, but the second time through the $row_alert loop looks for more results, finds that it's already run through them (in the loop where $row_wind = 'CT').
If you put some debug info inside the $row_wind loop but outside the $row_alert loop you should see the difference.
To fix this, you'll either have to re-run the $result_user_alerts query before the inner loop, or - probably better if the inner query isn't dependent on the state - run mysqli_fetch_all() beforehand to fetch all your results for the inner loop up front, and then loop through the resulting array with your inner loop with a foreach() or while(). That way you only have to fetch them once.
If you don't have mysqli_fetch_all() avaialble, you can just manually loop through:
$user_alerts = array();
while($row_alert = mysqli_fetch_array($result_user_alerts)){
$user_alerts[] = $row_alert;
}
A cautionary note: The way this is structured, however, seems like it could be better-executed with some better queries - I don't know the details of your application, but when you're matching values from two SQL queries in a PHP loop, that matching can usually be done more quickly and efficiently by the database.

Related

Is it better to traverse through a PHP array than traversing through MySQLi associative array?

I have the following code in which I am using a loop inside a loop to create a PHP array:
$result= mysqli_query($myqueri1);
while($row = mysqli_fetch_assoc($result))
{
$result1=mysqli_query($myqueri2); //This query utilizes a variable obtained from the outer loop. So this cant be written outside the loop.
while($row = mysqli_fetch_assoc($result))
{
//Operations
}
}
The two arrays contain almost 50k rows. And they are indexed.
However, I am more concerned about the optimization issue. If I store all the results of loop 1 into a PHP array and then iterate through it, does it make any difference? Or is using while($row = mysqli_fetch_assoc($result)) same as going through a common PHP loop? Which is more optimized?
Database access is slow compared to accessing elements of an array. But if the array comes from a database access, there should not be much difference.
I doubt your claim "So this cant be written outside the loop." For example
for ($i = 0; $i < 3, ++$i) {
mysqli_query("SELECT foo FROM bar WHERE id = $i");
}
can be written as
mysqli_query("SELECT foo FROM bar WHERE id IN (0, 1, 2)");
As with all optimizations: before you optimize, find out where the bottleneck is. After optimization, confirm that the bottleneck is actually gone.
If I store all the reults of loop 1 into a PHP array and then iterate through it,
...then you will iterate twice
Whihc is more optimized?
Running a loop once is more optimized than running a loop twice. So it makes your question is rather on the arithmetic, not optimization.
However, I am more concerned about the optimization issue.
Then you have to use JOIN in your first query and get all the data without a nested query at all.
If you are using mysqli_query() with default flags MYSQLI_STORE_RESULT you already transfer the whole result set from the database into your application. See http://php.net/manual/en/mysqli.query.php specifically the result_mode flag, and mysqli_store_result() vs. mysqli_use_result() for a better explanation of what the flags do.
This means that the outer loop in your case shouldn't differ much in performance if you first populate a php array with it or just keep doing what you are doing now.
The big performance difference you can make here is if it is at all possible to combine the second, inner loop querys into some kind of join into the first query.
Sending multiple queries to the database inside the loop is what is going to take time here.

foreach loops - adding items once it's been initiated?

I have a question about PHP foreach loops. I'm using it in Codeigniter.
Basically I have a list of items in a db and I'm using a foreach loop to run a script on each item in the db until the script has been run on every item.
My question is: If I had, for example, 45 items in the database and then initiated the loop, what would happen if additional items were added to the database list while the loop was still running, thus making a bigger list of items to be looped over?
Would it either:
Run all the items that were in the loop when it was initiated (in this case, 45).
or
Run all the items in the loop and when it gets down to the end (at number 45) continue to run the script on the additional ones I added after the loop was initiated.
I can't seem to find any answers for this, any info is most appreciated
When you fetch all items from the db with CodeIgniter, it puts the results in an result object or array, depending if you use $this->db->result(); or $this->db->result_array();
So when you loop over this result, any new records won't show up in this object or array. Only when you fire a new query, any new rows will be added to the result.
Initially when you fired a query their was 45 records in db and then record has been added , so there will be only 45 records which will be displayed
When a php script run for extracting records from DB table, it actually extract all the records from table according to u'r query & save it in a PHP variable. After that, foreach loop extract data one by one from that variable & execute it.
At the execution time, if any more records comes to u'r DB table then that'll get store in u'r table not in u'r PHP array. So, forloop execution will not get effected by those extra rows.
If u want to execute, all those extra records.. then again u've to make SELECT query to the DB table & extract those additional records.. Need to keep them a PHP array & execute them by foreach.

Why does a one-line mysql query/fetch array statement not work?

I have run into this problem multiple times, and I cannot figure out why it happens. When I build a MySQL statement like the following it works just fine:
$sql=mysql_query("SELECT * FROM table WHERE id='$something'");
while($row=mysql_fetch_array($sql)){
$someVar=$row['whatever'];
//and so on
}
But when I combine the first two statements to the following:
while($row=mysql_fetch_array(mysql_query("SELECT * FROM table WHERE id='$something'")))
and try to loop through them, the page seems to loop infinitely without loading or returning an error. Why doesn't the second statement work?
mysql_query executes the query and returns a record id which mysql_fetch_array uses to fetch the next row. When you chain them together like you've tried doing, each iteration of the while loop will exectute the query, return a new record id and fetch the first row. As long as there's at least one row, it'll end up doing this in an infinite loop.

PHP MySQL while loop not returning anything

I'm quite new to php and mysql so hopefully someone with more experience will be able to give me some guidance here.
I have the following code:
<?php
$npcname = $_GET['npcname'];
$npcinfo="SELECT * from npcs where name='$npcname'";
$npcinfo2=mysql_query($npcinfo) or die("could not get npc!");
$npcinfo3=mysql_fetch_array($npcinfo2);
$listquests = "SELECT * from quests where npcid = '$npcinfo3[npcid]'";
$listquests2 = mysql_query($listquests) or die("No Quests to list");
$listquests3=mysql_fetch_array($listquests2);
echo "<b>Quests Available for ".$npcname."</b><br>";
while($row=mysql_fetch_array($listquests2)) {
echo $row['name'];
}
?>
To go with this I have some tables whcih look like this:
npcs
name|location|npcid
quests
name|qid|npcid
So a quest is associated to a NPC via the npcid field.
I have one entry in each table.
Bob|Scrapyard|1
AND
Sort Scrap Metal|1|1
As you can see the quest and Bob both share the npcid of 1.
In my loop I am trying to list all of the quests for Bob. However on running the code I do not get any quests listed.
If I put the code:
$listquests3['name'];
Outside of my loop it successfully displays "Sort Scrap Metal" as expected. The reason I have used the loop is to display multiple quests when I add them.
If somebody could be kind enough to take a look at the code and tell me what I have done wrong I would be grateful.
Thank You.
It may be a good idea to print out the SQL and run this against your database to see what results you get.
Looking at this it looks like there may only be one result which is fetched in the
$listquests3=mysql_fetch_array($listquests2);
line. Since there are no more results there is nothing to loop over.
The results are already fetched, since there is only one rule and you fetched it in $listquests3 :). It will work if you remove that line I think.
You need to do a INNER JOIN or a LEFT JOIN. Yes after carefully seeing the question again, I found that when doing the "mysql_fetch_array()" code for the first time (just before the "while" loop), the value of the variable "$listquests2" gets lost. So the "while" loop does nothing fruitful.
You must remove this single line for variable "$listquests3".
You only have one row, and you fetched that row when you called mysql_fetch_array the first time. When you call it the second time, there are no more rows to fetch in the result set, the function returns false and your loop exits.
This statement: "$listquests3=mysql_fetch_array($listquests2);" already fetches the first. Sicne you have only one, there's nothing more to fetch, so the next call to mysql_fetch_array will return nothing.
That should fix it, but for your own 'experience', this might be a good moment to start learning about MySQL joins (LEFT JOIN in particular). You can easily find a lot about it on the internet!

Nested mysql_query() - Resets first result's pointer?

I have a friend who's using FluxBB and he has just installed a modification for this forum software. The viewtopic.php file has a while-loop which does a mysql_fetch_assoc() on a result object. Inside of this loop there's a second mysql_fetch_assoc() on a second result object.
The reason for the nested while loop is that there are many posts, and each posts HasMany thank-you's.
Here's some code to better illustrate what I mean:
$result = mysql_query("some-query");
while($cur_post = mysql_fetch_assoc($result)) {
// For every post, execute this second query
$secondResult = mysql_query("some-query that uses the $cur_post id");
while($thank_you = mysql_fetch_assoc($secondResult)) {
// Display the thank_you
}
}
The problem is that the outer-most while loop stops after just one iteration when using the second mysql_query. It does work if the first query is run again, which is a ridiculously dirty hack that works fine with OFFSET.
To me it seems that when the second mysql query is run, whatever $result is pointing at is invalidated. However, I barely know PHP so that's why I've come to SO with this problem.
How would you go about solving this issue? Is it correct that the $result pointer is affected by the second mysql query?
mysql_query() sends a unique query
(multiple queries are not supported)
to the currently active database on
the server that's associated with the
specified link_identifier.
Youll have to grab all your posts (or a batch of them) and store the ids or whatever other data you need into an array or object and then iterate over it making the appropriate query and displaying output.
Or you could use some sql like this:
SELECT thank_you.* FROM thank_you, post WHERE post.id = thank_you.post_id ORDER BY thank_you.post_id;
Of course with this you lose grouping youd have to add some extra logic to build the proper presentation structures based on if the post_id has changed within the loop.

Categories