Use PHP to Display MySQL Results in HTML Table - php

Update for CodingBiz:
I'm putting this in my code:
for($i=1;$i<=$numRows;$i++) {
$output .= '<tr>';
$row = $this->fetchAssoc($result);
$colRow = $this->fetchAssoc($colResult);
foreach($colRow as $colName) {
$output .= "<td>".$row[$colName]."</td>";
}
$output .= '</tr>';
}
in place of
for($i=1;$i<=$numRows;$i++) {
$output .= '<tr>';
$row = $this->fetchAssoc($result);
for($j=1;$j<=$colNumRows;$j++) {
$colRow = $this->fetchAssoc($colResult);
$output .= "<td>".$row[$colRow["COLUMN_NAME"]]."</td>";
}
$output .= '</tr>';
}
Is there anything wrong with this?
Original Post:
I'm writing a function in a PHP class to display the results of a query in a table. I'm not structuring any of the table myself, I want it everything to be done using PHP. Here is my code so far:
function allResults($table,$cols) {
if(isset($cols)) {
$query = "SELECT $cols FROM $table";
}
else {
$query = "SELECT * FROM $table";
}
$result = $this->query($query);
$numRows = $this->numRows($result);
$colQuery ="SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='shareride' AND TABLE_NAME='$table'";
$colResult = $this->query($colQuery);
$colNumRows = $this->numRows($colResult);
$output = '<table class="allResults">';
$output .= '<tr>';
for($i=1;$i<=$colNumRows;$i++) {
$colRow = $this->fetchAssoc($colResult);
$output .= "<td>".$colRow["COLUMN_NAME"]."</td>";
}
$output .= '</tr>';
for($i=1;$i<=$numRows;$i++) {
$output .= '<tr>';
$row = $this->fetchAssoc($result);
for($j=1;$j<=$colNumRows;$j++) {
$colRow = $this->fetchAssoc($colResult);
$output .= "<td>".$row[$colRow["COLUMN_NAME"]]."</td>";
}
$output .= '</tr>';
}
$output .= '</table>';
return $output;
}
In case it is unclear, query refers to mysqli_query, numRows refers to mysqli_num_rows, and fetchAssoc refers to mysqli_fetch_assoc. The database name is "shareride."
I know I am missing something in this line:
$output .= "<td>".$row[$colRow["COLUMN_NAME"]]."</td>";
but I just don't know what it is. Right now, I get all the table column titles displayed correctly, and I get the correct number of content rows, but I just can't populate those rows with the actual data from the database.
What am I missing? Any help would be GREATLY appreciated!

Get the data and column names from the same result set
<?php
$i = 0;
$colNames = array();
$data = array();
while($row = ***_fetch_assoc($res)) //where $res is from the main query result not schema information
{
//get the column names into an array $colNames
if($i == 0) //make sure this is done once
{
foreach($row as $colname => $val)
$colNames[] = $colname;
}
//get the data into an array
$data[] = $row;
$i++;
}
?>
UPDATE: Suggested by #YourCommonSense to replace the above code and it worked, simple and shorter - A WAY TO GET THE COLUMN NAMES/ARRAY KEYS WITHOUT LOOPING THROUGH LIKE I DID
$data = array();
while($row = mysql_fetch_assoc($res))
{
$data[] = $row;
}
$colNames = array_keys(reset($data))
Continued as before: Print the table
<table border="1">
<tr>
<?php
//print the header
foreach($colNames as $colName)
{
echo "<th>$colName</th>";
}
?>
</tr>
<?php
//print the rows
foreach($data as $row)
{
echo "<tr>";
foreach($colNames as $colName)
{
echo "<td>".$row[$colName]."</td>";
}
echo "</tr>";
}
?>
</table>
Test Result
You can see how I separated the data retrieval from table generation. They are dependent of each other now and you can test your table generation without the database by populating the arrays with static data
You can also make them into separate functions.

Never mix your database handling code with HTML output code. These are 2 totally different matters. Make your allResults function only return array with data, and then you can make another function to print in fancy way (and not in the database handler class).
You don't need information schema to get column name - you already have it in the returned array keys.
You don't need numRows either - use while() and foreach()
NEVER insert anything into query directly like you do with $cols - eventually it will lead to errors and injections.
Such a function, without accepting some parameters for the query, makes absolutely no sense especially in the context of migrating from mysql to mysqli - you are going yo use it as an old school mysql query inserting variables, not placeholders. So, it makes migration totally useless.
To know "Is there anything wrong with code", one have to run it, not watch. Run and debug your code, outputting key variables and making sure you can see errors occurred.

i'd try replacing the data part with something like:
while($row = $this->fetchAssoc($colResult))
{
echo "<tr>";
foreach($row as $value)
{
echo sprintf("<td>%s</td>",$value)
}
echo "</tr>";
}
i know it's not a proper answer, but it's really hard to read that code imho

Related

identifying column number in PHP mysqli_fetch_row() WHILE loop

I'm trying to identify whether I am looking at the first column in the array.
I haven't tried anything, but googled plenty and cannot find a solution.
while($row = mysqli_fetch_row($sql)) {
echo '<tr>';
foreach ($row as $col) {
if () //NEED CODE HERE
echo "<td><a href = 'https://whatismyipaddress.com/ip-lookup' target = '_blank'>$col</a></td>";
}
echo '</tr>';
}
mysqli_fetch_row fetches "one row of data from the result set and returns it as an enumerated array, where each column is stored in an array offset starting from 0 (zero)." So the key of the column is the same as column order.
So you can do this:
while($row = mysqli_fetch_row($sql)) {
echo '<tr>';
foreach ($row as $key => $col) {
if ($key === 0) {
echo "<td><a href = 'https://whatismyipaddress.com/ip-lookup' target = '_blank'>$col</a></td>";
}
}
echo '</tr>';
}
But column is subjected to changes in database structure and SQL query changes. I would personally prefer mysqli_fetch_assoc or mysqli_fetch_object so I can use the column by name instead of order number. Its less error prone. For example,
while($row = mysqli_fetch_assoc($sql)) {
echo '<tr>';
foreach ($row as $key => $col) {
if ($key === 'ip_address') {
echo "<td><a href = 'https://whatismyipaddress.com/ip-lookup' target = '_blank'>$col</a></td>";
}
}
echo '</tr>';
}
Note: $sql here should be a mysqli_query result instead of the actual SQL string.

MYSQLi Multiple Records Outputs Duplicates

Issue:
I've continuously looked over my code and cannot find why the array is duplicating the data. A single entry into the database has a correct output, however if there is more than one it will duplicate those before it as well as the next one.
My Code:
global $connection;
//Query database & retrieve results.
$search = $connection->query('SELECT * FROM users WHERE country= "'.$country.'"');
echo '<table><tr><th>Username</th><th>Email</th><th>Country</th></tr>';
while ($result = $search->fetch_assoc())
{
$total[] = $result;
foreach ($total as $rows)
{
echo '<tr>';
echo '<td>'.stripslashes($rows['username']).'</td>';
echo '<td>'.stripslashes($rows['email']).'</td>';
echo '<td>'.stripslashes($rows['country']).'</td>';
echo '</tr>';
}
}
echo '</table>';
Output:
This will return the following form -
Username Email Country
exampleUser1 exampleEmail1#example.com United States
exampleUser1 exampleEmail1#example.com United States
exampleUser2 exampleEmail2#example.com United States
You can see the first line is repeated then the new entry is there, it will continue on from this the more it goes on.
Additional Info:
This is placed inside of a function and is executed when $_POST['country'] is submitted - $country is just $_POST['country'] with a real_escape_string.
$connection is just a new mysqli(localhost, user, pass, database) referenced in the script - it is globalised because this is wrapped inside a function.
Any help would be appreciated.
<?php
//... Your code
while ($rows = $search->fetch_assoc()) {
$rows = array_map('stripslashes', $rows);
echo '<tr>';
echo '<td>'.$rows['username'].'</td>';
echo '<td>'.$rows['email'].'</td>';
echo '<td>'.$rows['country'].'</td>';
echo '</tr>';
}
//... Your code
if you need to save and return from function this rows just create array $total and add $total[] = $rows; after echo '</tr>';
As mentioned in my comment, put the foreach outside your while loop like this:
echo '<table><tr><th>Username</th><th>Email</th><th>Country</th></tr>';
while ($result = $search->fetch_assoc()) {
$total[] = $result;
}
foreach ($total as $rows) {
echo '<tr>';
echo '<td>'.stripslashes($rows['username']).'</td>';
echo '<td>'.stripslashes($rows['email']).'</td>';
echo '<td>'.stripslashes($rows['country']).'</td>';
echo '</tr>';
}
echo '</table>';
Another solution is to just redeclare your $total all the time.. Just keep your code then and do:
$total = $result;

PHP loop optimization

I have a php method that creates an HTML table with data it retrieves from a property.
My biggest concern is the performance of my application because I deal with a large amount of data.
public function getHTML() {
$phpObj = json_decode($this->data); // array(object, object, object, ....);
$table = "<table><tbody>\n";
if (count($phpObj->query->results->row) > 0) {
$row = $phpObj->query->results->row;
foreach ($row as $value) {
$table .= "<tr>\n";
foreach ($value as $key => $val) { // concerned about loop inside loop
$table .= "<td>" . $value->$key . "</td>";
}
$table .= "\n</tr>\n";
}
$table .= "</tbody></table>";
return $table;
}
else {
return 'HTML table not created.';
}
}
Is there a more efficient way of traversing through the array and objects without creating a loop inside a loop?
Don't concatenate and return the value, echo it immediately instead. Less clean but the performance will be much more interesting since the strings are immediately outputed to the output buffer which is managed more efficiently.
A loop inside a loop is often the best way to traverse a two-dimensional array.
String concatenation is cost-intensive. You could reduce the number of repetitive string concatenations by using arrays:
public function getHTML() {
$phpObj = json_decode($this->data);
if (count($phpObj->query->results->row) > 0) {
$rows = array();
foreach ($phpObj->query->results->row as $row) {
$cells = array();
$rows[] = "<td>" . implode("</td><td>", $row) . "</td>";
}
return "<table><tbody>\n<tr>\n" .
implode("\n<tr>\n<tr>\n", $rows) .
"\n</tr>\n</tbody></table>";
} else {
return 'HTML table not created.';
}
}
You could also use anonymous functions (available since PHP 5.3):
public function getHTML() {
$phpObj = json_decode($this->data);
if (count($phpObj->query->results->row) > 0) {
return "<table><tbody>\n<tr>\n" .
implode("\n<tr>\n<tr>\n", array_map(function($cells) { return "<td>".implode("</td><td>", $cells)."</td>"; }, $phpObj->query->results->row)) .
"\n</tr>\n</tbody></table>";
} else {
return 'HTML table not created.';
}
}
UPDATE
Col. Shrapnel correctly stated that, oddly, string concatenation is actually relatively fast in php.
As Vincent said, don't run a bunch of concatenations, that's killing you. You have two options to speed up your script:
Echo immediately.
Store your lines in a an array, and join the array at the end.
Example of two:
<?php
$mylines = array();
foreach ($row as $value) {
$mylines[] = "<tr>\n";
foreach ($value as $key => $val) { // concerned about loop inside loop
$mylines[] = "<td>" . $value->$key . "</td>";
}
$mylines[] = "\n</tr>\n";
}
return implode('', $mylines);
You could move the HTML building into the frontend and ship the JSON data to the user via AJAX and javascript.
This could also allow your to only ship pieces of the data at a time (depending on your html layout), so they could be dynamically polled when needed (like google/bing image search).
I know I didn't answer the question directly. That is because the code you have is probably the fastest it can be done (in PHP) w/o doing silly little optimizations that would only make the code harder to read/maintain (probably only save a few % anyway).
EDIT: after looking at it again, I bet your code is actually just polling the data from an external source in JSON. You could probably remove this code completely by having the frontend javascript do the HTTP hit and deal with the data there. This removes the need for this PHP code to run at all.
EDIT 2: after reading your comment about this being a fall back for javascript being disabled, I looked at the code your currently doing. It appears to be translatable into implode.
//declared this functions somewhere
function tr_build( $row_value )
{
$tablerow .= "<tr>\n";
if( $row_value ) {
$tablerow .= "<td>".implode( "</td><td>", $row_value )."</td>";
}
$tablerow .= "\n</tr>\n";
return $tablerow;
}
//this replaces the double loop
if( $row ) {
$tablerows = "<tr>\n".implode( "\n</tr>\n<tr>\n", array_map( "tr_build", $row ) )."\n</tr>\n"
} else {
$tablerows = "";
}
Why are you bothering with this?
$table .= "<tr>\n";
foreach ($value as $key => $val) { // concerned about loop inside loop
$table .= "<td>" . $value->$key . "</td>";
}
$table .= "\n</tr>\n";
You never actually use $val so why have this loop at all?
$table .= "<table><td>";
$table .= implode("</td><td>", array_keys($value));
$table .= "</td></table>";

Displaying an associative array in PHP

I am trying to build a function that extracts information from a database and inserts it into an associative array in PHP using mysql_fetch_assoc, and return the array so another function can display it. I need a way to display the returned assoc array. This should be a different function from the first one
print_r($array) will give nicely formatted (textually, not html) output.
If you just want information about what is in the array (for debugging purposes), you can use print_r($array) or var_dump($array), or var_export($array) to print it in PHP's array format.
If you want nicely formatted output, you might want to do something like:
<table border="1">
<?php
foreach($array as $name => $value) {
echo "<tr><th>".htmlspecialchars($name).
"</th><td>".htmlspecialchars($value)."</th></tr>";
}
?>
</table>
This will, as you might already see, print a nicely formatted table with the names in the left column and the values in the right column.
while ($row = mysql_fetch_assoc($result)) {
foreach ($row as $column => $value) {
//Column name is in $column, value in $value
//do displaying here
}
}
If this is a new program, consider using the mysqli extension instead.
Assuming you've made the call, and got $result back:
$array = new array();
while($row = mysql_fetch_assoc($result)){
$array[] = $row;
}
return $array;
This should get you going:
$rows = mysql_query("select * from whatever");
if ($rows) {
while ($record = mysql_fetch_array($rows)) {
echo $record["column1"];
echo $record["column2"];
// or you could just var_dump($record); to see what came back...
}
}
The following should work:
$rows = mysql_query("select * from whatever");
if ($rows) {
$header = true;
while ($record = mysql_fetch_assoc($rows)) {
if ($header) {
echo '<tr>';
foreach (array_keys($record) AS $col) {
echo '<td>'.htmlspecialchars($col).'</td>';
}
echo '</tr>';
$header = false;
}
echo '<tr>';
foreach (array_values($record) AS $col) {
echo '<td>'.htmlspecialchars($col).'</td>';
}
echo '</tr>';
}
}
(Yes, blatant mod of Fosco's code)
This should print the column headers once, then the contents after that. This would print just whatever columns were retrieved from the DB, regardless of the query.

How can i fetch all data from any table of a test DB and DUMP it on the production db in same tablename(structure)?

How can i fetch all data from any table of a test DB and DUMP it on the production db in same tablename(structure)? in Mysql using PHP code?
Please help me..
EDIT
I need PHP to do this for me using MySQL Queries
Sorry, a little disorganized but these are the functions I use to build the SQL code for table reconstruction and repopulating. This is all within a 'table' object but I'm sure you can piece together what's going on.
The SQL "SHOW CREATE TABLE yourtablename" gives you everything needed to create the table again. All the rest is just looping through all the entries and making INSERT statements.
public function backup() {
$output = "/* - - - Table recovery for $this->tablename - - - */\n\n\n";
$output .= "DROP TABLE IF EXISTS `$this->tablename`;\n\n";
$output .= $this->showcreate().';';
$output .= $this->showrepopulate();
return $output."\n\n\n";
}
final protected function showcreate() {
$result = $this->query("SHOW CREATE TABLE $this->tablename");
return $result[0]['Create Table'];
}
final protected function showrepopulate() {
$result = $this->query("SELECT * FROM $this->tablename");
$output = '';
$count = count($result);
if ($count) {
$output = "\n\nINSERT INTO `$this->tablename` VALUES\n";
for ($i=0; $i<$count; $i++) {
$output .= "(";
$numfields = count($result[$i]);
for ($j=0; $j<$numfields; $j++) {
if ($j>0) $output .= ',';
$output .= $this->Database->escape(array_shift($result[$i]));
}
$output .= ")";
$output .= ($i != $count-1) ? ",\n" : ';';
}
}
return $output;
}
If you mean by dumping creating SQL code to recreate the table, I'd suggesting using existing tools to manage MySQL such as phpMyAdmin or Adminer.

Categories