PHP: Creating big HTML-table efficiently - php

I'm making a HTML table based on certain information in my MySQL database. The tables I need from the database hold the data for rows (rowid, rowname), columns (columnid, columnname) and cell data. A table, that links IDs from rows and columns together (cellid, rowid, columnid, somedata).
The table looks something like this:
__________| column1 | column2 | column3 | ...
row1 | somedata | somedata | |
----------|----------|----------|----------|-----
row2 | somedata | | somedata |
----------|----------|----------|----------|-----
... | | | |
My approach was to use several nested foreach loops, something like this:
$rows = new Rows(); //These objects are containers for objects
$columns = new Columns(); //that hold some of the database data.
$alldata = new Alldata(); //MySQL queries within these objects are irrelevant, I think. They already get the relevant data
$count = count($alldata);
echo "<table>";
echo "<tr>";
echo "<td> </td>";
foreach ($columns->getColumns() as $column) {
echo "<td>".$column->getColumnname()."</td>";
}
echo "</tr>";
foreach ($rows->getRows() as $row) {
echo "<tr>";
echo "<td>".$row->getRowname()."</td>";
foreach ($columns->getColumns() as $column) {
$last = 1;
foreach ($alldata->getAlldata() as $data) {
if ($data->getCID() == $column->getID() & $data->getRID() == $row->getID()) { //If the column has data the related to the row
echo "<td>".$data->getSomedata()."</td>";
break;
}
if ($last == $count) { //if loop couldn't find any entries, it prints an empty cell
echo "<td> <td>";
}
$last++
}
}
echo "</tr>";
}
echo "</table>";
Bruteforcing, obviously this is not very efficient method when there are several hundred rows of data on any table in the database and I don't like this. Any ideas how to make this more efficient? Is there better way of creating a table like I need?
EDIT:
Pondering about this problem for a week has finally given me some answers. It was so simple!
I did a slight modification to my Column object class. Previously, my code went through all possible entries on celldata table in the database. Now Column object gets an array of celldata where columnid's match and I can do the comparison using only that data.
$rows = new Rows();
$columns = new Columns();
echo "<table>";
echo "<tr>";
echo "<td> </td>";
foreach ($columns->getColumns() as $column) {
echo "<td>".$column->getColumnname()."</td>";
}
echo "</tr>";
foreach ($rows->getRows() as $row) {
echo "<tr>";
echo "<td>".$row->getRowname()."</td>";
foreach ($columns->getColumns() as $column) {
$last = 1;
$count = count($column->getAlldata());
foreach ($column->getAlldata() as $data) {
if ($data->getCID() == $column->getID() & $data->getRID() == $row->getID()) {
echo "<td>".$data->getSomedata()."</td>";
break;
}
if ($last == $count) {
echo "<td> <td>";
}
$last++
}
}
echo "</tr>";
}
echo "</table>";
Much faster, although still bruteforcing but there's less amount of data to go through. Of course, now the problem is that Column objects may do quite a lot of MySQL queries, depending on how many Columns there are.

If you ensure that the data fetched from MySQL is correctly ordered in $alldata by joining the tables and specifying an ORDER BY clause in your query:
SELECT data.*
FROM data RIGHT JOIN rows USING (rowid) RIGHT JOIN columns USING (columnid)
ORDER BY rowname, columnname;
Then you only need to output each cell in order:
echo '<table>';
echo '<thead>'
echo '<tr>';
echo '<th> </th>';
foreach ($columns->getColumns() as $column) {
echo '<th scope="col">', htmlentities($column->getColumnname()), '</th>';
}
echo '</tr>';
echo '</thead>';
echo '<tbody>';
$data = $alldata->getAlldata();
foreach ($rows->getRows() as $row) {
echo '<tr>';
echo '<th scope="row">', htmlentities($row->getRowname()), '</th>';
foreach ($columns->getColumns() as $column) {
$d = each($data);
echo '<td>', ($d ? htmlentities($d[1]->getSomedata()) : ' '), '</td>';
}
echo '</tr>';
}
echo '</tbody>';
echo '</table>';

The best way to solve this would be to rewrite the query for $alldata so that it is in the order you want like eggyal suggested. If you can't do that for some reason, you could iterate through $alldata in the beginning and create a properly indexed array from it. Something like this:
$ordereddata = array();
foreach($alldata as $d) {
$ordereddata[$d->getCID()][$d->getRID()] = $d->getSomedata();
}
Now you can replace your foreach($alldata) loop with this:
if(isset($ordereddata[$column->getID()][$row->getID()])) {
echo "<td>{$ordereddata[$column->getID()][$row->getID()]}</td>";
} else {
echo "<td> </td>";
}

Related

Splitting Long php generated HTML table?

I use a MySql query to select data from my DB and then print it in the form of a HTML Table. It works perfectly, fine but sometimes the table consists of hundreds of rows and the webpage looks incredibly akward. Is there a way to split the table side by side into 2 or 3 halves.
Present Output
Desired output
PHP
<?php
....
echo "<h3>Classes attended :</h3>";
echo "<table class='dates' border='1'>";
foreach ($results as $dates) {
echo "<tr><td width='50%'>";
echo $dates->db_date;
echo "</td>";
echo "<td width='50%'>";
echo $dates->day_name;
echo "</td>";
echo "</tr>";
}
echo "</table>";
?>
What would be the best way to achieve it?
Help would be appreciated.
You can use PHP to determine in your loop if the loop index is divisible by a certain number using something like this:
echo "<h3>Classes attended :</h3>";
echo "<table class='dates' border='1'>";
$rowCount = 1;
$numRows = count($results);
$maxRows = 12;
foreach ($results as $dates) {
echo "<tr><td width='50%'>";
echo $dates->db_date;
echo "</td>";
echo "<td width='50%'>";
echo $dates->day_name;
echo "</td>";
echo "</tr>";
if($rowCount % $maxRows == 0 && $rowCount != $numRows) {
echo "</table><table class='dates' border='1'>";
}
$rowCount ++;
}
echo "</table>";
That's the basics of doing this. Basically in your loop you're testing each index to see if it's divisible by $maxRows, and if so then you're going to close your table and open a new one. You'll have to add the styling to place the tables side by side.
If you wanted to expand upon this concept you can set $maxRows to be an evaluation of $numRows. For instance if you wanted to split the items as close as possible to half in order to show just two tables, you could do... $numRows = count($results); $maxRows = round($numRows / 2);
Inspired by Robert Wade's answer:
<?php
....
echo "<h3>Classes attended :</h3>";
$i=0;
$maxRows=10;
foreach ($results as $dates) {
$a=$i/$maxRows == 0 ? "<table class='dates' border='1'>":"";
$b=$i/$maxRows == 0 ? "</table>":"";
echo $a;
echo "<tr><td width='50%'>";
echo $dates->db_date;
echo "</td>";
echo "<td width='50%'>";
echo $dates->day_name;
echo "</td>";
echo "</tr>";
echo $b;
$i++;
}
?>
At last, add some css style to the tables.
You can also use array_chunk() for splitting your results. Or instead of displaing a lot of tables next to each other you can make pagination and get only some range in your query. For example:
SELECT * FROM `clients` LIMIT 5, 10
Selects 10 rows beggining from row 5. Now, when you change your page, just change limit values.

Mysql rows to html table using for loop

I tried to print the Mysql fetched rows into html table using php. However, when using the following code, the first fetched row is repeatedly printing. It looks like the $row hold the first fetched value. I found a similar problem here. But I would like to know about working with the for loop. Thanks
for ($j=0;$j<=$len2;$j++)
{
$sql = "SELECT * FROM database_search WHERE gene_id LIKE'%$key%'";
$qry = $dbo->prepare($sql);
$qry->execute();
$row = $qry->fetch(PDO::FETCH_ASSOC);
$val = array_values($row);
echo "<tr>";
for ($k=0;$k<=4;$k++)
{
$x=$val[$k];
echo "<td style=font-size:7.9px>$x</td>";
}
echo "</tr>";
}
<table>
<?php
while($row = $qry->fetch(PDO::FETCH_ASSOC)){
echo '<tr>';
foreach($row as $cell){ echo '<td>'.$cell.'</td>'; }
echo '</tr>';
}
?>
</table>
After fetching the query as $row variable, you need to use the following code instead
foreach($row as $tr) {
echo "<tr>";
echo "<td style=font-size:7.9px>".$tr['col1']."</td>";
echo "<td style=font-size:7.9px>".$tr['col2']."</td>";
echo "</tr>";
}
This is possible that $row only have one record fetching from database and than your for ($k=0;$k<=4;$k++) loop print that only one record 5 time
because you are using print under this loop, this loop will run 5 time.
Try the following code.
foreach($row as $val) {
echo "<tr>";
echo "<td style=font-size:7.9px>".$val['column Name']."</td>";
echo "</tr>";
}

Can I display query results without naming columns?

Is there a php or html code to dynamically generate a table.
query :
"SELECT * FROM table1;
Can I display this grid of info without any specifics.
IF there are 4 rows and 4 columns I want the table to be that size; if 5x5 than that.
It seems like this should be possible, but all code I can find wants me to specify names or columns.
Yes. There are a couple different ways to do this, but for illustration I will assume that the result of your query is stored in a variable called $results, which is simply a multidimensional array that you can loop through using a double foreach to dynamically produce your table.
echo '<table>';
foreach ($results as $row) {
echo '<tr>';
foreach ($row as $col) {
echo '<td>' . $col . '</td>';
}
echo '</tr>';
}
echo '</table>';
OR if you don't have a $results array and are instead getting query results and building the table at the same time, something like this might be more appropriate for your needs:
echo '<table>';
while ($row = mysqli_fetch_array($query)) {
echo '<tr>';
foreach ($row as $col) {
echo '<td>' . $col . '</td>';
}
echo '</tr>';
}
echo '</table>';
echo'<table>';
while($row = mysql_fetch_array($result))
{
echo'<tr>';
echo '<td>'.$row[colname].'</td>';
echo '</tr>';
}
echo'</table>';

Mysql to array not working

Hey Everyone i got a little problem! I know its something simple but for some reason i can not figure it out (arrays are kicking my butt!)
I want the results to display like the following...
title 1 | title 2 | title 3 | title 4 |
Title 5 | title 6 | title 7 | title 8 |
But for some reason when the code runs it shows as the following...
t | i |
It spells out the title 1 and not the whole word for each cell of the table.
What am i doing wrong?
$result = mysqli_query($con,"SELECT title FROM donuts");
$rows = 2;
$cols = ceil(count($result)/$rows);
$row = mysqli_fetch_array($result);
echo $result=$row['title'];
echo "<table border='1'>";
$i=0;
for($tr=1;$tr<=$rows;$tr++) {
echo "<tr>";
for($td=1;$td<=$cols;$td++) {
if (isset($result[$i])) {
echo "<td>".$result[$i]."</td>"; $i++;
}
}
echo "</tr>";
}
echo "</table>";
Note the table has no limit on how many columns there are just rows.
Link to working example http://lakeside.donavonscreativeinnovations.com/
You have to loop through the results. Something like this:
// $numrows = mysqli_num_rows($result); // Count rows if you want to know
while( $row = mysqli_fetch_array($result, MYSQLI_ASSOC) ) { // Loop through rows
echo "<tr>";
foreach($row as $key => $value) { // Loop through columns
echo "<td>" . $value . "</td>";
}
echo "</tr>";
}
At the moment you loop through each character of a column.
You might want to try it like this:
$result = mysqli_query($con, "SELECT title FROM donuts");
echo '<table>';
while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC))
{
echo '<tr>';
foreach ($row as $cell)
{
echo '<td>' . $cell . '</td>';
}
echo '</tr>';
}
echo '</table>';
Here is your problem:
echo $result=$row['title'];
and then you loop through this with the code:
$i=0; for($tr=1;$tr<=$rows;$tr++)
{ echo "<tr>";
for($td=1;$td<=$cols;$td++)
{
if (isset($result[$i])) {
**echo "<td>".$result[$i]."</td>"; $i++;**
Thus you loop through a string outputting each character in that string.

fetching db column names only, for display in dynamic table using php

in the code below Im searching specific columns from a db table and placing them into a html table, inserting &nbsp for empty db fields to maintain uniformed structure. That part works fine, but Im having trouble figuring out the best way to go about getting the column names that are being searched and dynamically displaying them once at the very top of the html table? If my search changes, the column names displayed on the html table will change with it accordingly. Im fairly new to php/mysql and would appreciate any help guys.
$result = mysql_query('SELECT part, ers, make, model, years, oe, core, inlet, outlet FROM parts LIMIT 3');
echo '<table>';
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
echo '<tr>';
foreach ($row as $name => $value) {
if ( $value == "" ) $value=" ";
echo '<td> '.$value.' </td>';
}
echo '</tr>';
}
echo "</table>";
How about something like this:
$result = mysql_query('SELECT part, ers, make, model, years, oe, core, inlet, outlet FROM parts LIMIT 3');
echo '<table>';
$cnt = 0;
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
if ($cnt == 0) {
$columns = array_keys($row);
echo '<tr><th>' . implode('</th><th>', $columns) . '</th></tr>';
}
$cnt++;
echo '<tr>';
foreach ($row as $name => $value) {
if ( $value == "" ) $value=" ";
echo '<td> '.$value.' </td>';
}
echo '</tr>';
}
echo "</table>";

Categories