/**
* Generates a multi-column table from an array
*
* @param array Array to process
* @param columns Number of columns to return
* @param id (Optional) ID attribute to attach to the table
* @param class (Optional) CSS class attribute to attach to the table
*/
function generate_table($array, $columns, $table_id='', $table_class='') {
$array_size = count($array);
$col_size = ceil($array_size / $columns);
$table = "<table";
$table .= !empty($table_id) ? " id='".$table_id."'" : '';
$table .= !empty($table_class) ? " class='".$table_class."'" : '';
$table .= ">\n";
for ($i = 0; $i < $col_size; $i++) {
$table .= "\t<tr>";
for ($j = 0; $j < $columns; $j++) {
$table .= (($i+$j*$col_size) < $array_size) ? '<td>'.$array[$i+$j*$col_size].'</td>' : '<td> </td>';
}
$table .= "</tr>\n";
}
$table .= "</table>\n";
return $table;
}
Refactorings
No refactoring yet !
Eineki
July 24, 2009, July 24, 2009 12:36, permalink
Just for exercise, I've rewritten the two loops. The function become.
I don't know if it is more efficient, you should try (I can't do it now).
<?
/**
* Generates a multi-column table from an array
*
* @param array Array to process
* @param columns Number of columns to return
* @param id (Optional) ID attribute to attach to the table
* @param class (Optional) CSS class attribute to attach to the table
*/
function generate_table($array, $columns, $table_id='', $table_class='') {
$table = "<table";
$table .= !empty($table_id) ? " id='$table_id'" : '';
$table .= !empty($table_class) ? " class='$table_class'" : '';
$table .= ">\n";
while (count($array)) {
$row=array_pad(array_splice($array,0,$columns),$columns,' ');
$table .='<tr><td>'.join($row,'</td><td>')."</td></tr>\n";
}
$table .= "</table>\n";
return $table;
}
?>
gwrtheyrn
July 24, 2009, July 24, 2009 19:20, permalink
eineki, your code looks great, and it works perfectly except that the ordering of the array output is horizontal, while the one in my solution returns vertically ordered columns. (i hope you understand, it's difficult to explain in english :)) but that doesn't really matter to me, so thanks.
Tj Holowaychuk
July 27, 2009, July 27, 2009 05:32, permalink
You shouldnt use count() in while, very inefficient. You should use a for loop and cache the length
Jelle
January 16, 2011, January 16, 2011 15:14, permalink
Not really an improvement on this code, but I'm writing a database class (extending PDO) that returns a statement object (extending PDOStatement). In the statement class I wrote a fetchTable() method that returns a html table based on the resultset. Since this is the first result in google when you search for "generate table from array" I thought I'd share that code here.
<?php
class db extends PDO {
//too much code to show here.
}
class dbStatement extends PDOStatement {
/**
* Fetches the next row from a result set as an associative array.
* @return array
* An associative array with the row data.
*/
public function fetchAssoc() {
return $this->fetch(PDO::FETCH_ASSOC);
}
public function fetchTable($attributes = array()){
$table = "<table";
$table .= !empty($table_id) ? " id='$table_id'" : '';
$table .= !empty($table_class) ? " class='$table_class'" : '';
foreach($attributes as $attribute => $value){
if(is_array($value)){
//support multiple classes (e.g. class = "class1 class2").
$value = implode(" ", $value);
}
$table .= " " . $attribute . "=\"" . $value . "\"";
}
$table .= ">\n";
$tableheaders = "";
$rows = "";
$header = "";
while($row = $this->fetchAssoc()){
if(empty($tableheaders)){
$header .= "\t<tr>\n";
}
$rows .= "\t<tr>\n";
foreach ($row as $fieldname => $field){
if(empty($tableheaders)){
$header .= "\t\t<th>" . ucfirst(strtolower($fieldname)) . "</th>\n";
}
$rows .= "\t\t<td>" . $field . "</td>\n";
}
$rows .= "\t</tr>\n";
if(empty ($tableheaders)){
$header .= "\t</tr>\n";
$tableheaders .= $header;
}
}
$table .= $tableheaders . $rows . "</table>\n";
return $table;
}
}
/**
* Usage example
*/
require_once '/includes/config.php';
require_once '/scripts/database/class.db.php';
$db = new db("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASSWORD);
$stmt = $db->select('menu')->run(); //returns a dbStatement object.
print $stmt->fetchTable();
/**
* Prints following HTML
* <table>
* <tr>
* <th>Id</th>
* <th>Label</th>
* <th>Page_id</th>
* <th>Weight</th>
* </tr>
* <tr>
* <td>1</td>
* <td>First Page</td>
* <td>1</td>
* <td>1</td>
* </tr>
* <tr>
* <td>2</td>
* <td>Second Page</td>
* <td>2</td>
* <td>100</td>
* </tr>
* </table>
*/
?>
Mike Hoy
May 18, 2011, May 18, 2011 20:26, permalink
einiki, Thank you very much for your code. I was dreading making a TON of tables cells and this script made my life so much easier. I nearly cried at how quickly all my perfect tables were generated. All I had was two td's per row so I just passed in empty values to the function.
echo generate_table($arr, 2, '', '');
This function generates a multi-column table from an array. Any improvements?