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>';
Related
I'm stuck trying to use nested loops to make a reflective pattern from numbers.
I've already tried, but the output looks like this:
|0|1|2|
|0|1|2|
|0|1|2|
This is my code:
<?php
echo "<table border =\"1\" style='border-collapse: collapse'>";
for ($row=1; $row <= 3; $row++) {
echo "<tr> \n";
for ($col=1; $col <= 3; $col++) {
$p = $col-1;
echo "<td>$p</td> \n";
}
echo "</tr>";
}
echo "</table>";
?>
I expected this result:
|0|1|0|
|1|2|1|
|0|1|0|
Each columns' and rows' cell values must increment to a given amount then decrement to form a mirror / palindromic sequence.
First declare the square root of the of the table cell count. In other words, if you want a 5-by-5 celled table (25 cells), declare $size = 5
Since your numbers are starting from zero, the highest integer displayed should be $size - 1 -- I'll call that $max.
I support your nested loop design and variables are appropriately named $row and $col.
Inside of those loops, you merely need to make the distinction between your "counters" as being higher or lower than half of the $max value. If it is higher than $max / 2, you subtract the "counter" (e.g. $row or $col) from $max.
By summing the two potentially adjusted "counters" and printing them within your inner loop, you generate the desired pattern (or at least the pattern I think you desire). This solution will work for $size values from 0 and higher -- have a play with my demo link.
Code: (Demo)
$size = 5;
$max = $size - 1;
echo "<table>\n";
for ($row = 0; $row < $size; ++$row) {
echo "\t<tr>";
for ($col = 0; $col < $size; ++$col) {
echo "<td>" . (($row >= $max / 2 ? $max - $row : $row) + ($col >= $max / 2 ? $max - $col : $col)) . "</td>";
}
echo "</tr>\n";
}
echo "</table>";
Output:
<table>
<tr><td>0</td><td>1</td><td>2</td><td>1</td><td>0</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>2</td><td>1</td></tr>
<tr><td>2</td><td>3</td><td>4</td><td>3</td><td>2</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>2</td><td>1</td></tr>
<tr><td>0</td><td>1</td><td>2</td><td>1</td><td>0</td></tr>
</table>
There are a lot of ways to achive that.
An easy way to do that is;
<?php
$baseNumber = 0;
echo "<table border='1' style='border-collapse: collapse'>";
for ($row = 0; $row < 3; $row++) {
echo "<tr>";
if ($row % 2 !== 0) {
$baseNumber++;
} else {
$baseNumber = 0;
}
for ($col = 0; $col < 3; $col++) {
echo "<td>" . ($col % 2 === 0 ? $baseNumber : $baseNumber + 1) . "</td>";
}
echo "</tr>";
}
echo "</table>";
this code will do what you want just call the patternGenerator function with the number of distinct numbers you want for your example these numbers are 3 (0,1,2).
the idea in this code is to use two for loops one that starts from the minimum number to the maximum one and the other one that starts after the maximum number decreasing to the minimum.
for example:
if min = 0 and max = 5
the first loop will print 0,1,2,3,4,5
and the second will print 4,3,2,1,0
and that's it.
at first, I created a function that creates just on row called rowGenerator it takes $min and $max as parameters and prints one row
so if we want to print a row like this: |0|1|0| then we will call this function with min = 0 and max = 1 and
if we want to print a row like this: |1|2|1| then we will call it with min = 1 and max = 2.
function rowGenerator($min, $max)
{
echo '<tr>';
for($i = $min; $i<=$max;$i++)
echo '<td>'.$i.'</td>';
for($i = $max-1; $i>=$min;$i--)
echo '<td>'.$i.'</td>';
echo '</tr>';
}
for now, we can print each row independently. now we want to print whole the table if we look at the calls we do for the rowGenerator function it will looks as follow:
(min = 0, max = 1),
(min = 1, max = 2) and
(min = 0, max = 1).
minimums are (0,1,0).
yes, it's the same pattern again. then we need two loops again one to start from 0 and increase the number until reach 1 and the other one to loop from 0 to 0.
and that's what happened in the patternGenerator function. when you call it with the number of distinct numbers the function just get the min that will always be 0 in your case and the max.
function patternGenerator($numberOfDistinct )
{
echo "<table border =\"1\" style='border-collapse: collapse'>";
$min = 0;
$max = $numberOfDistinct - 2;
for($i = $min;$i<=$max; $i++)
{
rowGenerator($i,$i+1);
}
for($i = $max-1;$i>=$min;$i--)
{
rowGenerator($i,$i+1);
}
echo '</table>';
}
this is the output of calling patternGenerator(3):
the output of calling patternGenerator(5):
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;";
}
This question already has answers here:
Transposing multidimensional arrays in PHP
(12 answers)
Closed 1 year ago.
I have a mysql query that returns an array of rows. How would i populate my html table using php vertically? there is no limit to how many columns i my HTML table allowed.
My MYSQL query returns about 40 columns per row.
MYSQL row1 => 10|11|12|13|14|15|16|17|18|19
row2 => 20|21|22|23|24|25|26|27|28|29
row3 => 30|31|32|33|34|35|36|37|38|39
HTML output should look like this
10 | 20 | 30
11 | 21 | 31
12 | 22 | 32
13 | 23 | 33
14 | 24 | 34
15 | 25 | 35
16 | 26 | 36
17 | 27 | 37
18 | 28 | 38
19 | 29 | 39
this is my code, and it's displaying nothing.
$values = array();
$sql = "SELECT * FROM `TABLE_NAME` ORDER BY `id` ASC LIMIT 0,12";
$result = $_db->query($sql);
$numrows = $_db->num_rows($result);
$c = 1;
while ($c <= $numrows)
{
$values['col_'.$c] = array();
$c++;
}
$r = 1;
while ($row = $_db->fetch_array($result))
{
$values['col_'.$c][$r] = $row;
$r++;
}
echo "<table border='1'>";
for ($r = 1; $r <= $numrows; $r++)
{
echo "<tr>";
for ($c = 1; $c <= sizeof($values['col_1']); $c++)
{
echo "<td>".$values['col_'.$c][$r]."</td>";
}
echo "</tr>" ;
}
echo "</table>" ;
Any idea what i'm doing wrong? or how to make it simpler? (i think there are too many while loops)
I think what you want is creating the php array from the mysql query, transposing the array (like you would transpose a matrix) and display it.
Transposing an array is a solved problem (transposing multidimentional arrays in php)
For the rest, it is pretty simple ... here is my code:
$res = mysqli_query(...);
$anarr = array();
while ($row = mysqli_fetch_array($res,$result_type=MYSQLI_ASSOC)){
$anarr[] = $row;
}
// here is the transpose part
array_unshift($anarr, null);
$transposedarr = call_user_func_array('array_map', $anarr);
// end of the transpose part
echo '<table>';
foreach ($transposedarr as $r){
echo '<tr>';
foreach ($r as $c){
echo '<td>'.$c.'</td>';
}
echo '</tr>';
}
echo '</table>';
?>
You are assigning only one row in your while loop. Change that with below code:
while ($row = $_db->fetch_assoc($result))
{
$values['col_'.$c][$r] = $row;
$c++;
$r++;
}
Here you are assigning the value to $value['col_1'][$r] and not increasing the value of $c. So at the end it override the values.
You can simplify the problem by just saying
$values[$rowIndex] = $columnArray
So in this case
$values[0] = array( 10, 20, 30 );
$values[1] = array( 11, 21, 31 );
And then loop across each array
echo "<table border='1'>";
foreach( $values as $row )
{
echo "<tr>";
foreach( $row as $columnValue )
{
echo ..whatever..
}
echo "<tr>";
}
echo "</table>" ;
Or something along these lines. I just basically psuedo coded this though, I have no access to php interpreter right now.
//while and foreach loop can do this
<?php
$values = array();
$sql = "SELECT * FROM `TABLE_NAME` ORDER BY `id` ASC LIMIT 0,12";
$result = $_db->query($sql);
$numrows = $_db->num_rows($result);
//check here
if($numrows>0)
{
//1 row
$r = 1;
//column
$c=0;
while ($row = $_db->fetch_assoc($result))
{
//value row column
$values[$r][$c] = $row;
//column == 3
if($c==2)
{
//increase row
$r++;
//reset column
$c = 0;
}else{
$c++;
}
}
echo "<table border='1'>";
//display row and columns
foreach($values as $row)
{
echo "<tr>";
echo "<td>".$values[0]."</td>";
echo "<td>".$values[1]."</td>";
echo "<td>".$values[2]."</td>";
echo "</tr>" ;
}
echo "</table>" ;
}
You can do everything in a single loop. Additionally, at least for your purposes in this example, I don't understand why you're putting everything in an array and then echo, instead of echoing it directly.
e.g. (tested):
$sql = "SELECT * FROM `TABLE_NAME` ORDER BY `id` ASC LIMIT 0,12";
$result = $_db->query($sql);
echo "<table border='1'>";
$tab = array();
while ($row = $result->fetch_row())
{
$tab[] = $row;
}
for( $i = 0, $l = count($tab[$i]); $i < $l; $i++){
echo "<tr>";
for( $j = 0, $m = count($tab); $j < $m; $j++){
echo "<td>".$tab[$j][$i]."</td>";
}
echo "</tr>" ;
}
echo "</table>";
UPDATE: I completely changed my code. I didn't get initially what you needed.
Does this code help you?
This is how I would tackle it. The most difficult part is preparing the structure in which you prepare the table. It uses the following syntax: $somearray[] = $x, which appends $x to array $somearray. implode() concats an array together with a string you define. Last but not least, you were using mysql_fetch_assoc, which returns an associative array (Array( [column1] => "val1" ); etc). You want a numbered array instead for these kind of operations. This can be accomplished with mysql_fetch_array with a second argument of MYSQL_NUM.
$arrayOfRows = Array();
$sql = "SELECT * FROM `TABLE_NAME` ORDER BY `id` ASC LIMIT 0,12";
$result = $_db->query($sql);
$firstrun = true;
while( $row = $_db->fetch_array($result, MYSQL_NUM) ) {
#Setup structure on first run
if( $firstrun ) {
$firstrun = false;
for( $i = 0; $i < count( $row ); $i++ ) {
$arrayOfRows[$i] = Array();
}
}
#Each field in this mysql row needs to be in a different html row
foreach( $row as $k => $v ) {
$arrayOfRows[$k][] = $v;
}
}
#Now simply print it
echo '<table>';
foreach( $arrayOfRows as $k => $row ) {
echo '<tr>';
echo '<td>' . implode( '</td><td>', $row ) . '</td>';
echo '</tr>';
}
echo '</table>';
<?php
$arr = array(array(1,2,3,4,5,6,7,8,9), array(10,11 etc . . .
for($i = 0; $i < 9; ++ $i){
for($x = 0; $x < $num_rows; ++ $x){
echo $arr[$x][$i];
}
echo '<br/>';
}
?>
U may replace 9 with number of columns in tables
I not shure what it this code correct (can't test now), but i think it can help you
Sorry if i do something wrong, i just try to help
I have a MySQL query that I am saving to a variable to output on the page. I have the data in an unordered list, but I am trying to split the data into three columns using 3 unordered lists floated left. Here is my current code:
$sqlCommand =
"SELECT list_specialty.id, list_specialty.specialty FROM list_specialty
ORDER BY list_specialty.specialty ASC";
$query = mysqli_query($myConnection,$sqlCommand) or die (mysqli_error($myConnection));
$specialtyDisplay = '';
$num = mysqli_num_rows($query);
$split = intval($num/3); //number of items in every column
$i = 0;
while ($row = mysqli_fetch_array($query)) {
$specialtyid = $row["id"];
$specialtyname = $row["specialty"];
$specialtyDisplay .=
'<li>' . $specialtyname . '</li>';
$i++;
if ($i == $split) {
$specialtyDisplay .= '</ul> <ul>';
$i = 0;
}
}
This code works GREAT as long as my data is exactly divisible by 3 (equal columns).
However, when my total number of rows is not divisible by 3, the above code won't work.
I need a solution that will balance the columns, so I can have either 3 equal columns, one extra element in the first column, or one extra element in the first and second column.
What do I need to change in my code to account for that?
This will work:
set $split to the length of the longest column
rows have 0, 1 or 2 columns that are longer by one element. -> $longcols = $num % 3
substract 1 from $split when column number $longcols is printed (unless all columns have equal length)
Implemented in the code:
$num = mysqli_num_rows($query);
$split = ceil($num/3); // 1.
$i = 0;
$col = 1; //for counting columns
$longcols = $num % 3; // 2.
while ($row = mysqli_fetch_array($query)) {
$specialtyid = $row["id"];
$specialtyname = $row["specialty"];
$specialtyDisplay .=
'<li>' . $specialtyname . '</li>';
$i++;
if ($i == $split) {
$specialtyDisplay .= '</ul> <ul>';
if( $longcols != 0 && $longcols == $col ) { $split--; } // 3.
$i = 0;
$col++; //increase columns count
}
}
The lines with comments are those that I have changed/inserted.
If you are going to support better browsers, you can use CSS 3 Multicolumns. It doesn't require you to split. Just CSS does the magic.
div#multicolumn {
-moz-column-count: 3;
-moz-column-gap: 20px;
-webkit-column-count: 3;
-webkit-column-gap: 20px;
column-count: 3;
column-gap: 20px;
}
Screenshot:
CSS3 MultiColumn http://css.flepstudio.org/images/css3/css3-multi-column.jpg
I need to create 3 HTML columns in PHP with data returned from MySQL. I would like the data split evenly between all 3 columns... How would I go about doing this?
You could try doing something like this:
$result = mysql_query("SELECT value FROM table");
$i = 0;
echo '<table><tr>';
while ($row = mysql_fetch_row($result)){
echo '<td>' . $row[0] . '</td>';
if ($i++ == 2) echo '</tr><tr>'
}
echo '</tr></table>';
note this table has the values ordered like
1 2 3
4 5 6
7 8 9
If you wanted it vertically like
1 4 7
2 5 8
3 6 9
Then you should do something like
$result = mysql_query("SELECT value FROM table");
$data = Array();
while ($row = mysql_fetch_row($result)) $data[] = $row;
for ($i = 0; $i < count($data) / 3; $i++){
echo '<table><tr>';
for ($j = 0; $j < 3; $j++){
echo '<td>' . $data[ $i + $j * 3] . '</td>';
}
echo '</tr><tr>'
}
echo '</tr></table>';
You can create an HTML table and then use a PHP foreach loop to loop through the MySQL result set and put each field in its own table. At the end of each record returned by the MySQL query, end the table row and start a new one.
A small detail, if return more entries than the "fetch_row" use "break", based on the answer from #Robbie: Spliting mysql data in 3 columns error -3-columns-error