Infinite while loop issue with PHP - php

I'm using the same while loop on two pages where the only difference is a different SQL call on each page. The first works as it should, grabbing the contents from the query and displaying it in an image slider:
<?php
$qry = mysql_query(sprintf("SELECT * FROM manageme WHERE element IN ('%s')", $element));
$i = 0;
while (($t = mysql_fetch_array($qry)) != null && $i < 52) { $i++;?>
<li>
<a href="">
<img src="<?php print $t['fileLocation']; ?>";
title="<?php print $t['element_name']; ?>";
name="<?php print $t['clickLocation']; ?>";
alt="wat"
class="btnshow" />
</a>
</li>
<?php } ?>
This works as it should stepping through the loop and grabbing the contents from the query so long as there are less than 52 entries returned, ending when each record has displayed once.
Upon implementing the same while loop with a different SQL call, the problem occurs.
<?php
$qry = mysql_query(sprintf("SELECT u.username, us.user_id, us.service_id,
s.imageID, s.title, s.clickLocation, s.fileLocation, s.element_name
FROM user u, user_service us, manageme s
WHERE us.user_id = %s
AND s.imageID = us.service_id", $_COOKIE['user_id']));
$i = 0;
while (($t = mysql_fetch_array($qry)) != null && $i < 52) { $i++;?>
<li>
<a href="">
<img src="<?php print $t['fileLocation']; ?>";
title="<?php print $t['element_name']; ?>";
name="<?php print $t['clickLocation']; ?>";
alt="wat"
class="btnshow" />
</a>
</li>
<?php } ?>
Instead of grabbing from the array and ending the while loop when the contents have displayed once, it continues to loop the contents in the image slider until 52 entries have been displayed. So for instance, if the SQL call only finds 4 records to display in the image slider, the set of 4 displays 13 times (52/4) before ending the loop.
Can anyone help me figure out how to end this loop after it has displayed each record from my database once and only once? Thanks in advance!

Try adding LIMIT 52 to your query, and do the while loop as,
while ($t = mysql_fetch_array($qry)) {
//do something
}

Major problems:
1) Vulnerable to SQL injection attacks. Enjoy having your server
destroyed.
2) Terminology: you're not fetching "from an array". You're fetching a row of data from a result set, returning that row AS an array.
3) Your loop should terminate after 52 records OR no more records are avaialble, even though you're using some ugly syntax in the while() condition. Check that your query is actually fetching the right records, in the order/format you're expecting. There's nothing in your code that'd cause PHP to output "duplicate" rows.

use mysql_num_rows($qry) to terminate the loop in addition to < 52
Something like:
(($t = mysql_fetch_array($qry)) != null && ($i < mysql_num_rows($qry) || $i < 52))

From the manual it seems that your call to mysql_fetch_array($qry) will never return null. At the end of the result set you will get a false return. If you change your conditional to check for this you should be able to terminate the loop

Get rid of the $i < 52 check. Instead add LIMIT 52 to the end of your SQL query. Then change the while loop to:
while ($t = mysql_fetch_array($qry)) {
....
}

Related

php add a counter in while loop and return to a new line when i reach this counter

this is my code:
$q=mysqli_query($idcon,"SELECT * FROM `subscribed-team`");
while($row=mysqli_fetch_array($q)){
if($row['id-team']==$_POST["teamm"]){
if($row['year-st']==$_SESSION["year"]){
$p=mysqli_query($idcon,"SELECT * FROM `subscription`");
while($row1=mysqli_fetch_array($p)){
if($row1['id-subs']==$row['id-subs'])
echo"<img src='".$row1[8]."'/>";
}
}
}
}
now this code works fine, but it echo my results on the same line since its a loop.
i want my output to be 3 photos per line for example:
image1 image2 image3 (jumps to line)
image4 image5 image6
and not:
image1 image2 image3 image4 image5 image6.
To be more precise i want to add a condition that when the loop reaches 3 values, it returns to a new line and continue printing the results.
Try this. not tested but should work as your need.
$q=mysqli_query($idcon,"SELECT * FROM `subscribed-team`");
while($row=mysqli_fetch_array($q)){
if($row['id-team']==$_POST["teamm"]){
if($row['year-st']==$_SESSION["year"]){
$p=mysqli_query($idcon,"SELECT * FROM `subscription`");
$counter = 0;
while($row1=mysqli_fetch_array($p)){
if($row1['id-subs']==$row['id-subs'])
echo"<img src='".$row1[8]."'/>";
$counter++;
if($counter == 2){
echo "<br>";
$counter = 0;
}
}
}
}
}
I think you are trying to actually put in line breaks. If that is the case use this:
$q=mysqli_query($idcon,"SELECT * FROM `subscribed-team`");
$counter = 0;
while($row=mysqli_fetch_array($q)){
if($row['id-team']==$_POST["teamm"]){
if($row['year-st']==$_SESSION["year"]){
$p=mysqli_query($idcon,"SELECT * FROM `subscription`");
while($row1=mysqli_fetch_array($p)){
if($row1['id-subs']==$row['id-subs'])
echo"<img src='".$row1[8]."'/>";
$counter++;
if($counter % 3 == 0){
echo "\n";
}
}
}
}
}
If you are trying to put in HTML breaks, try this
$q=mysqli_query($idcon,"SELECT * FROM `subscribed-team`");
$counter = 0;
while($row=mysqli_fetch_array($q)){
if($row['id-team']==$_POST["teamm"]){
if($row['year-st']==$_SESSION["year"]){
$p=mysqli_query($idcon,"SELECT * FROM `subscription`");
while($row1=mysqli_fetch_array($p)){
if($row1['id-subs']==$row['id-subs'])
echo"<img src='".$row1[8]."'/>";
$counter++;
if($counter % 3 == 0){
echo "<br/>\n";
}
}
}
}
}
You should avoid making iterated queries.
You should avoid pulling more rows than you intend to use.
You should avoid SELECTing more columns than you intend to use.
You should apply your filtering criteria to the earliest point of data retrieval; in this case, you should use WHERE in your sql instead of an if in your php loop.
You should always use a prepared statement instead of directly inserting user-supplied data into your sql.
I don't know what column number eight is actually called, so I am going to call it src.
I will urge you to make the switch to object-oriented mysqli syntax because it is simpler and more concise than procedural syntax.
The result set object is iterable, so it can be fed directly into the foreach().
To create an html line break between every three rows, echo <br> if $i is not zero and is evenly divisible by 3.
Recommended Code: (untested)
$sql = "SELECT `src`
FROM `subscription` AS s
JOIN `subscribed-team` AS st ON s.`id-subs` = st.`id-subs`
WHERE st.`id-team` = ?
AND st.`year-st` = ?";
$stmt = $idcon->prepare($sql);
$stmt->bind_param("ss", $_POST["teamm"], $_SESSION["year"]);
$stmt->execute();
foreach ($stmt->get_result() as $i => $row) {
if ($i && $i % 3 === 0) {
echo "<br>";
}
echo '<img src="' . $row['src'] . '"/>';
}

variables changing during IF loop

I'm working on a PHP script to make a catalog. The relevant columns in my database are Vid, banner, category and Scategory. Vid is the primary key, banner is the path to my img files, and category and Scategory are both numbers for the their respective ID. Everything is over simplified as I'm just testing the scripts. There is currently 20 records in the table.
<html>
<head>
<style type="text/css">
</style>
</head>
<body>
<?php
require "config.php";
$sql = "SELECT Vid,banner,category,Scategory FROM display";
$result = $conn->query($sql);
$row = $result;
$min = 10;
$max = 20;
while ($row = mysqli_fetch_assoc($result)) {
implode ('', $row);
$vid = $row['Vid'];
$banner = $row['banner'];
$cid = $row['category'];
$sid = $row['Scategory'];
if ($cid = 2 && $sid = 1){
echo
'
<div style="display:inline-block;">
<div style="border-color:blue; border-style:solid;">
<a href="#test'.$vid.'">
<img src="'.$banner.'" />
</div>
</div>';
echo $vid;
echo $cid;
echo $sid;
if ($vid % 2 == 0){
echo '<br>';
}
}
}
require'close.php';
?>
</body>
</html>
Now the code runs just fine, but it gets strange I use $cid and $sid as conditions in that IF loop. Given there is 20 records, both $cid and $sid have half their values as '1' and half as '2, so when I set the IF conditions I figured it would return 5 records, but it instead returned all 20. When I echo $vid $cid and $sid, it returns the proper $vid, but $sid returns as whatever condition I set it to. For example conditions set to $cid=1 and $sid=2 returns 1:1:2, 2:1:2, 3:1:2 etc.
Now here is where it gets really strange, regardless of the condition set for $cid it returns as '1', if I set it '7' it still returns as '1'. Whereas $sid returns as whatever number is set. Also when I set either condition to null it returns nothing.
So my question is why it's acting the way it is or how it should be written if I'm writing it wrong.
Also as a side question, when I put <a> before <img> it returns the proper ID that's linked to the <img>. But when I put <a> directly after <img>, it returns the ID of the next iteration's row, and the first iteration returns blank. Anyone happen to know why that happens since regardless of their position in the statement it's still part of the same loop iteration?
You are using a single equal and assign the value to the variable. To compare values you have to use == or ===!
What is the difference between == and ===?
See the following condition to see the difference:
2 == "2" -> Equal
2 == 2 -> Equal
2 === "2" -> Not Equal
2 === 2 -> Equal
How you can avoid this on future? - Yoda condition
You can change your conditions to the following to make sure you are using the conditions on the right way. You only shoud use this for equal comparison not for >, <, <=, >=.
//throws an error
if (0 = $isNull) { ... }
//the right one
if (0 == $isNull) { ... }
== not = in your if statement.
implode line does nothing
Use double-equals instead of singles. Not:
if( $foo = 2 )
...but:
if( $foo == 2 )
Your code is changing the values instead of testing them.
Change if ($cid = 2 && $sid = 1) with if ($cid == 2 && $sid == 1). I think you did it only by mistake, since your other if is fine!
In your if statement you're using a single equals operator it needs to be == or ===

PHP while loop to fetch post data from database

I am creating my own blog from scratch with a homepage that loads the latest posts in order of time published. I call the posts using a front controller and store the data on a MySQL database. The website itself is great and the posts all load perfectly with no issue. The issue is getting the homepage to work.
I created a few PHP functions for the homepage. They generally order the posts (database rows) by ID in descending order, since it's an autoincrement field, and call their data. And then to show the latest post as a sort of 'featured post' right at the top, by fetching the data from the very top row in the database, which is the latest post.
And that works fine - when I echo the result it shows the latest post just as I want it.
Below that I want two boxes, side by side, for the two posts before the first one. So I made this function to call them:
function fetch_rest_posts_1($conn) {
$stuff = $conn->query("SELECT * FROM table WHERE is_post = 1 ORDER BY id DESC LIMIT 1,2");
while ($row = $stuff->fetch_array()) {
$i=1;
return '<div id="post_'.$i.'" style="width:308px;height:215px;padding:5px">
<h2>'.$row['title'].'</h2>
<p>'.date('d/m/Y',strtotime($row['published_date'])).' by '.$row['author'].' | </p>
<p>'.$row['meta_description'].'</p>
</div>';
$i++;
} // style="white-space:nowrap;width:100%;overflow:hidden;text-overflow:ellipsis"
}
And it actually does work great when I echo the result, shows everything I want, but it only shows one div, not two. When I take the SQL query and directly enter it into phpMyAdmin, it gives me two rows. Have I done something wrong?
(I put the auto-increasing $i in there so that I could isolate each box and alter the style later.)
Your problem is caused by the return statement in the loop. You should add $return = '' at the top of your function, replace return by $result .=, and return $result at the end of your function.
In addition, the loop counter $i is reset in every iteration. Move the initial assignment out of the loop.
EDIT: The .= is intentional to append to $result instead of replacing it with another value constructed from the next dataset.
initiate $i outside the loop and use echo() instead of return()
return() breaks the loop
or use
$result .= '<div id="post_'.$i.'" style="width:308px;height:215px;padding:5px">
<h2>'.$row['title'].'</h2>
<p>'.date('d/m/Y',strtotime($row['published_date'])).' by '.$row['author'].' | </p>
<p>'.$row['meta_description'].'</p>
</div>';
and return $result; after the loop
That's because return will stop execution of the function try this approach:
function fetch_rest_posts_1($conn) {
$stuff = $conn->query("SELECT * FROM table WHERE is_post = 1 ORDER BY id DESC LIMIT 1,2");
$post = array();
while ($row = $stuff->fetch_array()) {
$post[] = $row;
}
return $post;
}
So the function purpose is to just get the data, so you can later print it:
$row = fetch_rest_posts_1($conn);
for($i = 0; count(row); $i++){
echo '<div id="post_'.$i.'" style="width:308px;height:215px;padding:5px">
<h2>'.$row[$i]['title'].'</h2>
<p>'.date('d/m/Y',strtotime($row['published_date'])).' by '.$row[$i]['author'].' | </p>
<p>'.$row[$i]['meta_description'].'</p>
</div>';
}

Mysql Queries Error Inside a While Loop

I have a while loop from a query called $result.
Inside this while loop I have two other queries $anchors1 and $anchors2
The first one retrieves the first 2 rows;
The second one should retrieve the following ones using an offset.
For some reason the queries seem to interact one another, not displaying the 3 row and pulling a duplicate row which should not be there.
Is there any way this queries would interfere?
If I delete the first one, the second query works. Same vice versa.
The platform is Wordpress.
while($slice = mysql_fetch_assoc($result)){
$i++;
if($enable_position1 == 'y' && $i == $position[0]):
$anchors1 = mysql_query("SELECT * FROM anchors WHERE site_url = '$site_current' LIMIT 3");
while($anc = mysql_fetch_assoc($anchors)){
$site_anchor = $anc['site_anchor'];
$site_current = $anc['site_current'];
echo '<li>'.$site_anchor.'</li>';
}
elseif($enable_position2 == 'y' && $i == $position[1]):
$anchors2 = mysql_query("SELECT * FROM anchors WHERE site_url = '$site_current' LIMIT 999 OFFSET 3");
while($anc2 = mysql_fetch_assoc($anchors2)){
$site_anchor2 = $anc2['site_anchor'];
$site_current2 = $anc2['site_current'];
echo '<li>'.$site_anchor2.'</li>';
}
else:
the_post();
endif;
}
Ty very much!
In the second query, you're using the variable $site_current, which is set in the first query's block. Depending on how your application is designed, that could be causing the interference. I think you meant to put $site_current2 there.

Problem looping through usernames

I am trying to loop through an array of usernames and for each username, execute a mysql_query on each.
<?php
for ($i = 0; $i < count($u); $i++)
{
$j = $i + 1;
$s = $database->checkUserPlayedRecent($u);
if (mysql_num_rows($s) > 0)
{
?>
<tr>
<?php
echo "<td>$j</td>";
?>
<?php
echo "<td>$u[$i]</td>";
?>
<?php
echo "<td>$p[$i]</td>";
?>
</tr>
<?
}
}
?>
As you can see, $u is each username.
I want each username to only appear in the echo statements if each one has num_rows > 0.
At the moment nothing is displaying.
But there should be results being returned!
Can someone help please.
The sql:
$q = "SELECT id FROM ".TBL_CONF_RESULTS." WHERE (home_user = '$u' OR away_user = '$u') AND date_submitted >= DATE_SUB(CURDATE(),INTERVAL 14 DAY)";
This line :
for ($i = 0; $i < count($u); $i++)
indicates that $u is an array -- and not a single name.
And $i is used to keep track of the current index in that array.
So, in your loop, you should be working with $u[$i] -- which will be the "current" line of the array :
$s = $database->checkUserPlayedRecent($u[$i]);
Note that you could probably rewrite your loop, using a foreach loop, like this :
foreach ($u as $currentPlayer) {
$s = $database->checkUserPlayedRecent($currentPlayer);
// ...
}
With foreach, no need to keep track of the current index -- makes code easier to write and understand, in my opinion ;-)
You should get in the habit of keeping count() outside of your conditional. You're count()ing the same array every time which is a waste of cycles.
$total = count($u);
for ($i=o; $i < $total; $i++) ...
I would definitely query these users all at once, especially since your query is abusing mysql_num_rows when you should be using the following sql:
select username, count(username) from user where username IN (your,array,of,usernames) group by username;
then your foreach loop would iterate over the results and you could reference each row without having to call yet another mysql_* method.
I'd be tempted to rewrite the query to accept the array of names and use an IN statement, so that you could execute the whole of your database activity in a single query rather than once for every entry in the array. It would almost certainly be faster.
If you show us the query that you're using in your checkUserPlayedRecent() method, we may be able to help with this.

Categories