Alternative to while loop - php

I am a newbie. I asked a question earlier regarding retrieving duplicates of the data i need from the db, for example the opening times from each takeaway duplicating on each take away (see image below); and i received a very helpful comment. The comment suggested that my while loop is causing my problem of query results duplication, as it is overriding my data.
duplication example
After looking at my code and working out which while loops are causing this problem (as I have a few), and playing around with them to understand my issue, I am now intrigued to know what loop can be used in replacement or as alternative to a while loop.
$rest_query = "SELECT Resturant_ID FROM Rest_Details";
$res_results = $dbc->query($rest_query);
//while($row_results = $res_results->fetch_assoc()){
$row_results = $res_results->fetch_assoc();{
{
$rests = $row_results['Resturant_ID'];
}
}
Above is one of the while loops I have removed, I know I will need a loop to gain all the information needed. And I do not know the number of repetitions I will need, therefore a for loop is not helpful.
Just trying to gain a better understanding, as I am building this website to teach myself.

"SELECT DISTINCT my_column_with_duplicates FROM Rest_Details"
and then
while($row_results = $res_results->fetch_assoc())
will work just fine.
Also there are other ways like $res_results->fetchAll() to get all the results in an array then use foreach loop. Just an idea.

Related

Some Tips to properly number SQL queries

As an Amateur PHP Developer I often have this problem of mixing sequences and variables.
SHORT :
So what would be the tips to keep in mind when writing a webpage that has many SQL queries.
I have thought of an idea of making a function but I am not sure if that would be of any good.
LONG:
The problem is I have a PHP page that has many sql queries which are followed by result, row , row_number, and die() if result unsuccessful after running the query.
I number them as sql1, result1, row1, error1, mysqlouput1 and sql2.... and so on..
When I add one more query after five or six days I have to go through the whole code to find out which was the last sequence used and take the next one, many times i just use the same and it creates strange problems.
The same problem with variables, as the same page is loading again and again with different POST and GET ids keeping track of variables is just too messy.
So what would be the tips to keep the code well sequenced, readable and variable names unique and understandable.
I have though of writing a function that takes the SQL as the input and gives the result, row, row count, and error as output.
What would you experienced people suggest ?
Thanks.
at first you should really try to just use relevant names for your variables.
Like if you are lookin for all the users use variables like $sqlUsers, $queryUsers, $resultUsers/$usersArray
The idea with the function would be one way to tackle the problem, as it no longer possible to code errors in the process itself, so if you do not want to switch to objectoriented programming I would probably choose that way.
Another way would be a mix, you could create only some classes in which you handle the database-interactions for specific domains. I.e. class userDataHandler would have the methods getUserById(), getAllUsers() et cetera. This way you would still have to write the querying process, but you know exactly where your queries are, have them in a structured way, there are no problems with naming your variables inside the methods, and your code doesn't get messy as you have different files for different domains -> separation of domainspecific code.
Can you explain your problem with the request-variables($_POST and $_GET) a little more? Why does your site get called with so many different variables, maybe you could structure your application a little better.

is there any shorthand method to handle loops if you know exactly how much times a loop needs to be executed

I have no problem in using loops but sometimes it really feels odd to use an separate variable just to count how many times loop has been executed especially when you know exactly how many times the loop needs to be executed just for example:
for($i=1;$i<6;$i++) echo "<input type='text' name='abc[]'/><br/>\n";
Now here I know exactly that the loop needs to do same thing 5 times so why to use an extra variable $i,initialize it,check condition each time and update it.
is there any short hand method such as:
execute(5){
echo "<input type='text' name='abc[]'/><br/>\n";}
which simply knows it have to do some work for a fixed number of times.
Currently i am familiar with these loops
for()
foreach()
while()
&
do while()
Please let me know if there exist any other.
Shortest way I can think of is using the while loop.
<?php
$i=5;
while($i--){
//Your code here
}
What you are looking for unfortunately doesn't exist.
But the idea of loops without extra variables is really great I will suggest you to submit an Idea on PHP official site So that they can create such methods in next release.
When the number of loops is known, the best option is the for loop. As your example shows, it will loop until the desired number of times, in your case 5 (the original loop and goes up 5 times for a total of 6, unless you have 7 entries in which case the 6 is your required value).
Foreach comes in handy particularly for arrays.
A while loop is used when calling information from a database.
#DigitalChris recommends str_repeat, but I think the for loop is clearer in terms of code. The best solution isn't always to be quick to do right away, it's often to be able to make quick changes if the need comes. Personal opinion, anyways.
Not as far as I know. The closest I can come is str_repeat but of course that's not what you're looking for. You could try writing a function that accepts an integer and a callable and roll your own. However, I recommend just using for loops in case other programmers have to read your code. If I need to do something five times I write:
for( $i = 0; $i < 5; $i++ ) {
// do stuff
}
That way the five is literally in the code and it's nice and readable. Your own for loop has a 6 instead of a 5, which to me makes it less readable.
As Jessica pointed out in the comments to this answer, you should really not hard code digits either way, you're better off using a constant or a parameter of some kind. That way you can improve readability even more and have a single place where you can change all occurrences of that particular "5" with some other number.

Is it possible to select all id's without a while-loop

I'm not sure if there is an answer for this, but I was thinking about the fact that PHP isn't very fast with while loops. That got me thinking about a basic function, which does something like this:
$array = array();
$sItem = DB::cms_query("SELECT id FROM someTable");
while($fItem = $sItem->fetch_assoc() ){
$array[] = $fItem['id']; // store the id in an array
}
That will give me an array with all found id's. What I was wondering is this:
Is it possible to select all those id's in 1 query and only use one fetch (so no loops to fetch), without creating difficult code. The goal is a simple piece of code to select all id's.
Small edit: I could replace fetch_assoc() with fetch_row() to improve a tiny bit, but I'm looking to replace the loop
To answer some questions:
I'm using mysqli, in my own custom database class (I'm new to OO, so in time I might improve that, but thats another story)
No, the mysqli extension doesn't provide any way to fetch all rows with a single operation, you can only fetch them one at a time. The only PHP API that currently offers this feature is PDO.
but I was thinking about the fact that php isnt very fast with while loops
How much ids are you fetching and what is called "not fast" for you?
I think the reason for a bad performance would most likely not be a while loop, but some other glitch with your code...

How can I make the website I'm working on load faster?

I am working on a website that I "inherited" in my job and it currently uses PHP/HTML/CSS/JS and it takes AGES to load, but the thing is without the PHP it loads really fast. I, however, am not very experienced with PHP so I don't know exactly where should I tweak it for it to work faster. First at the very top of the page I have this code to preload everything:
<?
?>
Then further down a table gets made using this code (which I know I can get better just don't know how exactly since tables on the db seem to be unrelated and they specifically asked me not to touch the db.
<?
$count = 0;
foreach ($domains as $row){
$count++;
?>
a little of html goes here in between (mostly rows of a table) and then:
<?
} ?>
So after about 2 days messing with the site I know my html/css/js is optimized but the php keeps making me wait around 5 - 10 seconds for everything to load (sometimes even longer) which of course is unacceptable, could anybody please help me out here?
EDIT
I tried taking some of the connections outside from the foreach loop but I get an error if I do so =/
Use a profiler like xhprof or xdebug+kcachegrind to find the places of your code that take a long time (or are executed too often) and optimize them.
First you should start by stopping writing queries in the foreach loop.
Get rid of queries which use LIKE statements.
Then you should recheck the indexes for the given tables. Rule of thumb would be that all rows which appear in WHERE and GROUP BY clauses should be indexed ( well .. there are exceptions , but you should be able to figure on case-to-case base ).
And you could get rid of the switch statement and replace it with array lookup.
.. well .. my 2 cents.

Is it wise to call a method and nested loop in a foreach loop?

Hi I have a method that returns an array of support tickets. Each support ticket can have many notes so I have a method that returns an array of tickets notes with that ticket id. I want to display the notes alongside the ticket which would mean nesting the get notes inside the foreach loop.
foreach($tickets as $ticket){
//display ticket info
//now get ticket notes using method getNotes()
foreach($ticketnote as $note){
//display note
}
}
Do nested loops like this have performance implications? Is this good practice?
It's not a problem.
Do nested loops like this have performance implications? Is this good practice?
Nested loops have no specific performance implications.
But of course, a lot of data may be processed; depending on how much it is, you could reach memory or performance limits. But that is a given, and would also occur if you would use a different control structure instead of a nested loop.
An array-/foreach()-based solution will always require loading the full data set into memory before it starts processing.
If you are fetching data from a database, you could consider re-structuring your functions so they fetch and process a database record one by one instead of loading them all into an array, and foreaching over them. That allows you to process data sets that are larger than your script's memory limit.
Well, the program does what you tell it to do. It will pass through each note of all the tickets. If that has to be done - it has to be done. So far a better practice doesn't exist if you have to loop through all of them. The only performance implication is more iterations than it would be without the nested loop, but without the nested loop you'd get no results.
There are only performance implications if you have excessive numbers of tickets and notes. So, if you had 1000 tickets and each had 1000 notes, the inner loop would run c. 1,000,000 times. But, as others have said, if it's necessary to do it this way then it's necessary.
Others have already pointed you in the right direction.
However, another aproach which has yet to be mentioned, and worth(possibly?) looking into are the Spl Iterators
$iter = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
foreach($iter as $key=>$value) {
echo $key.' =>'.$value;
}
On first observation, since you would be displaying the 'ticket notes' anyway, it wouldn't matter much whether you do this in a single loop or two nested loops. The net iteration count would be same.
On presentation issue, it's not wise to display all this information at once. You would certainly want to apply some kind of pagination.
Definitely not a good practice but i've never found a better solution than this.

Categories