PHP Loop - dealing with non-sequential iterations - php

I have the following code - it produces a series of queries that are sent to a database:
$a = 'q';
$aa = 1;
$r = "$a$aa";
$q = 54;
while($aa <= $q){
$query .= "SELECT COUNT(". $r .") as Responses FROM tresults;";
$aa = $aa + 1;
$r = "$a$aa";
}
The issue I have is simple, within the database, the number is not sequential.
I have fields that go from q1 to q13 but then goes q14a, q14b, q14c, q14d and q14e and then from q15 to q54.
I've looked at continue but that's more for skipping iterations and hasn't helped me.
I'm struggling to adapt the above code to handle this non-sequential situation. Any ideas and suggestions welcomed.

I have fields that go from q1 to q13 but then goes q14a, q14b, q14c, q14d and q14e and then from q15 to q54.
for($i=1; $i<=54; ++$i) {
if($i != 14) {
echo 'q' . $i . "<br>";
}
else {
for($j='a'; $j<='e'; ++$j) {
echo 'q14' . $j . "<br>";
}
}
}
If you don’t need to execute the statements in order of numbering, then you could also just skip one in the first loop if the counter is 14, and then have a second loop (not nested into the first one), that does the q14s afterwards.

You could get the columns from the table and test to see if they start with q (or use a preg_match):
$result = query("DESCRIBE tresults");
while($row = fetch($result)) {
if(strpos($row['Field'], 'q') === 0) {
$query .= "SELECT COUNT(". $r .") as Responses FROM tresults;";
}
}
Or build the columns array and use it:
$columns = array('q1', 'q2', 'q54'); //etc...
foreach($columns as $r) {
$query .= "SELECT COUNT(". $r .") as Responses FROM tresults;";
}

Related

update entire column with different values

I need to update tags column so each cell has the content like this:
2-5-1-14-5
or
3-9-14-19-23
or simmilar (five integers, in range from 1-25).
id column is not consecutive from 1-117, but anyway min id is 1 and max 117.
$arr = [];
$str = '';
$id = 1;
for ($x = 1; $x <= 25; $x++){
array_push($arr, $x);
}
while ($id < 117) {
shuffle($arr);
array_splice($arr, 5, 25);
foreach ($arr as $el){
$str .= $el . '-';
}
$str = rtrim($str,'-');
$db->query("update posts set tags = '" . $str . "' where id = " . $id);
$id += 1;
}
I'm not sure how to describe the final result, but it seems that the majority of cells are written multiple times.
Any help ?
To combine my comments into one piece of code:
$full = range(1, 25);
$id = 1;
while ($id < 117) {
shuffle($full);
$section = array_slice($full, 0, 5);
$str = implode('-',$section);
$db->query("update posts set tags = '" . $str . "' where id = " . $id);
$id += 1;
}
So the reset of $str is not needed anymore since I have inserted the implode() where it seems functional. The other bits of code could probably be improved.
Two warnings:
Using PHP variables directly in queries is not a good idea. Please use parameter binding. This particular piece of code might not be vulnerable to SQL-injection but if you do the same elsewhere it might be.
Your database doesn't seem to be normalized. This might cause trouble for you in the long run when you expand your application.

PHP Count Generated Results From Loop

I have this for loop that generates 10 results:
<?php
include "dbconnect.php";
$table = "SELECT id FROM players ORDER BY RAND()* ( 1 / percentage)";
for ($i = 0; $i < 10; $i++){
$result[0] = mysql_fetch_array(mysql_query($table));
foreach ($result as $winner){
echo $winner[0] . " ";
}
}
?>
It generates a result like:
10 10 11 9 13 11 10 12 8 12
My question is how do I count the generation? For the above example it would be:
8's = 1, 9's = 1, 10's = 3, 11's = 2, 12's = 2, 13's = 1.
I basically want to count the amount of specific results generated. Sorry if i'm not making much sense.
You need to get off of MySQL functions and check out PDO or MySQLI at a minimum. But for the meat of the question:
Don't run a query, full or limited in the loop
Look at the LIMIT clause in the query
array_count_values will count the values. You can loop it and echo or whatever
Example:
$table = "SELECT id FROM players ORDER BY RAND()*(1/percentage) LIMIT 10";
$result = mysql_query($table);
while($row = mysql_fetch_array($result)) {
$winner[] = $row[0];
}
echo implode(' ', $winner);
foreach(array_count_values($winner) as $number => $count) {
$output = "$number's = $count";
}
echo implode(', ', $output);
You're existing code to make the random choice work would look like (LIMIT 1):
$table = "SELECT id FROM players ORDER BY RAND()*(1/percentage) LIMIT 1";
for($i = 0; $i < 10; $i++){
$result = mysql_fetch_array(mysql_query($table));
$winner[] = $row[0];
}
echo implode(' ', $winner);
if you check the php manual:
http://php.net/manual/en/function.mysql-query.php
then try something like this:
while ($row = mysql_fetch_assoc($table)) {
echo $row['column_name'];
echo $row['column_name'];
//.. you get the idea
}
The id is usually the first column in a database table. This is why you are just getting the id. You need to access each row in the same way you access arrays.
I should point out that the mysql library is deprecated. So you should consider using something like PDO instead.

Results are not showing correct in table

I am completely new in PHP so this question might be stupid. I could not find an answer after searching for hours.
I have made a query with a foreach loop but it does not show it right in the table I create. The part from the foreach show all in the field next to the last country.
I have tried to put the on all kind of other places but the result stays the same it does not come in the right column.
$query = "SELECT COUNT(landofbirth) as c, landofbirth FROM dog WHERE landofbirth IS NOT NULL GROUP BY landofbirth ORDER BY c desc LIMIT 1000";
$result = mysql_query($query) ;
$values = array();
$pct = array();
$total = 0;
while ($line = mysql_fetch_array($result)) {
echo "<tr><td>";
$values[$line[1]] = $line[0];
$total += $line[0];
echo "$line[1]</td><td> ";
echo "$line[0] </td><td>"; }
foreach($values as $key => $value) {
$pct[$key] = $value/$total ;
$count2 = $pct[$key] * 100;
$count = number_format($count2, 2);
echo "$count %"; }
echo "</td></tr>";
Your code is a bit garbled, perhaps from moving it around one too many times.
I always find it helpful to separate the display items one-by-one, even put them each on individual lines and away from the "calculation" code for better visuals when editing the code.
I'm not exactly sure if this is what you're looking for, but I think this display will be close (and/or easily modifiable):
while ($line = mysql_fetch_array($result)) {
$values[$line[1]] = $line[0];
$total += $line[0];
}
foreach($values as $key => $value) {
$pct[$key] = $value/$total ;
$count2 = $pct[$key] * 100;
$count = number_format($count2, 2);
echo '<tr>';
echo '<td>' . $key . '</td>';
echo '<td>' . $value . '</td>';
echo '<td>' . $count . '%</td>';
echo '</tr>';
}
Side Note (not answer specific)
It is recommended that you do not develop with the deprecated mysql extension in PHP. Instead, you should use the alternative and maintained mysqli or PDO extensions. Both are far more secure to use and provide beneficial features such as prepared statements!

PHP loop to sort table

I'm querying a database for names that are numbered 1-26 alphabetically. I have the following code, but since HTML is structured tr then td, the table appears alphabetically by row as opposed to by column. How can I make it appear in order by column?
$query = mysql_query("SELECT name FROM people WHERE main=1 ORDER BY id");
$i = 0;
while($result = mysql_fetch_array($query)) {
$name = $result['name'];
if ($i % 5 == 0) echo "<tr>\n";
echo "<td width=\"150\">";
echo "".$name."<br />";
echo "</td>\n";
$i++;
if ($i % 5 == 0) echo "</tr>\n";
};
alpha beta charlie
delta echo foxtrot
vs.
alpha charlie echo
beta delta foxtrot
Also, I'm open to reworking the code if there's a more efficient way.
You could just access the output array in strides. Compute how many rows you need as the number of results divided by 5, and use the row count as the stride.
$ncols = 5;
$nrows = $nresults / $ncols + ($nresults % $ncols == 0 ? 0 : 1);
for ($i = 0; $i < $nrows; $i++)
{
// start row
for ($j = 0; $k < $ncols; $j++)
{
// print $results[$nrows * $j + $i]
}
// end row
}
You'll have to transfer your query results into an array $results first. Since you'll have to know the total number of results, this is sort of mandatory, though I'd be curious if anyone has a solution that can work while fetching the results.
Update: See Justin's answer for a cool solution that grows the output while fetching the query results line by line. Since it's currently being worked on, here's a summary (credits to Justin):
$nresults = mysql_num_rows($query);
$ncols = 5;
$nrows = (int) ceil($nresults / $ncols);
$i = 0; $cols = array_fill(0, $nrows, "");
while ($result = mysql_fetch_array($query))
$cols[$i++ % $nrows] .= "<td>$result['name']</td>";
echo "<tr>" . implode("</tr><tr>", $cols) . "</tr>";
Edit:
After the discussion in the comments between myself, Kerrek SB and the OP bswinnerton, the following code seems to be the most effective:
$columns = 3;
$rowcount = mysql_num_rows($query);
$rows = ceil($rowcount / $columns);
$rowdata = array_fill(0, $rows, "");
$ctr = 0;
while ($result = mysql_fetch_array($query))
$rowdata[$ctr++ % $rows] .= '<td>'.$result['name'].'</td>';
echo '<tr>'.implode('</tr><tr>',$rowdata).'</tr>';
This will create three columns, filled vertically (my original answer would create three rows). It also properly initializes the array (preventing PHP warnings), yields a correct row count for result counts that aren't divisible by the column count, and incorporates Kerrek's clever "calc-row-in-the-subscript" trick.
Original Post:
You could use arrays and implode() This way, you only have to make one pass through your results:
$row = 0;
$rows = 3;
$rowdata = array();
while($result = mysql_fetch_array($query))
{
if ($row >= $rows) $row = 0;
$rowdata[$row++] .= '<td>'.$result['name'].'</td>';
}
echo '<tr>'.implode('</tr><tr>',$rowdata).'</tr>';

PHP while loop find last row

$sql = mysql_query("SELECT * FROM comments WHERE user = 1");
$i = 1;
while ($row = mysql_fetch_assoc($sql)) {
<p>$i. <?php echo $row['comment'] ?></p>
<div class="border"></div>
$i++;
}
How could I do to not output <div class="border"></div> under the last comment?
$sql = mysql_query("SELECT * FROM comments WHERE user = 1");
$number = mysql_num_rows($sql);
$i = 1;
while ($row = mysql_fetch_assoc($sql)) {
echo '<p>' . $i . $row['comment'] . '</p>';
if ($i < $number)
{
echo '<div class="border"></div>';
}
$i ++;
}
Using WebDevHobo's suggestion.
$sql = mysql_query("SELECT * FROM comments WHERE user = 1");
$output = array ();
while ($row = mysql_fetch_assoc($sql)) {
$output[] = $row['comment'];
}
echo join('<div class="border"></div>', $output);
$number = mysql_num_rows($sql);
This will tell you how many rows will be returned. Based on that, you can make sure that the last on does not have the DIV.
$sql = mysql_query("SELECT * FROM comments WHERE user = 1");
$i = 1;
while ($row = mysql_fetch_assoc($sql)) {
$out_data[] = "<p>$i {$row['comment']} </p>";
$i++;
}
$divider = '<div class="border"></div>';
$output = implode ($divider, $out_data);
echo $output;
$rslt = mysql_query("SELECT * FROM comments WHERE user = 1");
$i = 1;
if ($row = mysql_fetch_assoc($rslt)) {
echo '<p>'. $i . ' '. $row['comment'] . '</p>';
$i++;
while ($row = mysql_fetch_assoc($rslt)){
echo '<div class="border"></div>';
echo '<p>'. $i . ' ' . $row['comment'] . '</p>';
$i++;
} // end while
} // end if
Avoids needing to know the number of rows.
Executes the if statement only once instead of each loop.
The HTML and php were kind of messy and inconsistent, so I just assumed the whole block was within php tags. Obviously, open and close the php tag as you see fit.
This is largely a style issue, but I decided that the variable name $sql was a bit misleading, as it is often and commonly used to hold the string of the sql statement to be executed, I therefore changed the variable name to $rslt.
A general answer to this type of problem, and using Javascript because it's easy to throw in a console and play with:
var count = 0;
var foo = 3;
while( count < 3 ) {
console.log("Header - " + count);
console.log("Body - "+ count);
console.log("Footer - " + count);
count++;
}
This will print:
Header - 0
Body - 0
Footer - 0
Header - 1
Body - 1
Footer - 1
Header - 2
Body - 2
Footer - 2
The case being requested is basically saying "Print a footer on all but the last element."
If you consider the second loop iteration as simply a continuation of the first you can see how to do this without needing to find the total number of records - e.g. no need to do a second query for count. More succinctly: when you're stuck trying to figure out how to do something using a loop (or recursion) you should try actually writing out what your loop does, but without actually looping - e.g. copy and paste the loop block at least three times.
Rather than do that here, I'm just going to finish with the answer, and leave the derivation to the reader :~)
var count = 0;
var foo = 3;
while( count < 3 ) {
if( count > 0 ) {
console.log("Footer - " + (count - 1));
}
console.log("Header - " + count);
console.log("Body - "+ count);
count++;
}

Categories