Using rowspan with array output to table in php - php

I'm looking to modify a table on a page to include merged rows.
Here is the php code that deals with the output from a mysql db:
######## PRINT OUT TABLE WITH YEARS AND OFFICES PLUS NAMES IN CELLS ########
for ($y = $year_max; $y >=$year_min; $y--){
echo '<tr><th>'.$y.'</th>';
for ($i = 0; $i<count($offices_used); $i++){
if (isset($data[$y][$offices_used[$i]])){
echo '<td>'.$data[$y][$offices_used[$i]].'</td>';
} // END IF
else {
echo '<td></td>';
} // END ELSE
} echo '</tr>';
} // END FOR
The table further below is generated from a multidimensional array such as immediately below;
array (
[2013] => Array
(
[President] => John Mills
[Internal VP] => Virgil Bagdonas
[External VP] => Reid Gilmore
[Treasurer] => Todd Heino
[Secretary] => Eric Holmquist
[Newsletter] => Art Bodwell
[Webmaster] => Dave Eaton
[Photographer] => Rick Angus
[Video Librarian] => Mike Peters
[Store Manager] => Kevin Nee
)
[2012] => Array
(
[President] => Dave Eaton
[Internal VP] => Jim Metcalf
[External VP] => Reid Gilmore
[Treasurer] => Mike Peters
[Secretary] => Eric Holmquist
[Newsletter] => Art Bodwell
[Webmaster] => Dave Eaton
[Photographer] => Peter Wilcox
[Video Librarian] => Ray Asselin
[Store Manager] => Joe Giroux
)
[2011] => Array
(
[President] => Charlie Croteau
[Internal VP] => Reid Gilmore
[External VP] => Rick Angus
[Treasurer] => Mike Peters
[Secretary] => Eric Holmquist
[Newsletter] => Ron Rocheleau
[Webmaster] => Dave Eaton
[Photographer] => Peter Wilcox
[Video Librarian] => Ray Asselin
[Book Librarian] => Roger Boisvert
[Store Manager] => Mike Smith
)
...etc
My php code NOW generates this table from mysql db:
<tr>
<th>Year</th>
<th>President</th>
<th>Internal VP</th>
<th>External VP</th>
<th>Treasurer</th>
<th>Secretary</th>
<th>Webmaster</th>
<th>Newsletter</th>
<th>Photographer</th>
<th>Video Librarian</th>
<th>Book Librarian</th>
<th>Store Manager</th>
</tr>
<tr>
<th>2013</th>
<td>John Mills</td>
<td>Virgil Bagdonas</td>
<td>Reid Gilmore</td>
<td>Todd Heino</td>
<td>Eric Holmquist</td>
<td>Dave Eaton</td>
<td>Art Bodwell</td>
<td>Rick Angus</td>
<td>Mike Peters</td>
<td></td>
<td>Kevin Nee</td>
</tr>
<tr>
<th>2012</th>
<td>Dave Eaton</td>
<td>Jim Metcalf</td>
<td>Reid Gilmore</td>
<td>Mike Peters</td>
<td>Eric Holmquist</td>
<td>Dave Eaton</td>
<td>Art Bodwell</td>
<td>Peter Wilcox</td>
<td>Ray Asselin</td>
<td></td>
<td>Joe Giroux</td>
</tr>
<tr>
<th>2011</th>
<td>Charlie Croteau</td>
<td>Reid Gilmore</td>
<td>Rick Angus</td>
<td>Mike Peters</td>
<td>Eric Holmquist</td>
<td>Dave Eaton</td>
<td>Ron Rocheleau</td>
<td>Peter Wilcox</td>
<td>Ray Asselin</td>
<td>Roger Boisvert</td>
<td>Mike Smith</td>
</tr>
But I WOULD LIKE to modify the array handling output to get the following:
<tr>
<th>Year</th>
<th>President</th>
<th>Internal VP</th>
<th>External VP</th>
<th>Treasurer</th>
<th>Secretary</th>
<th>Webmaster</th>
<th>Newsletter</th>
<th>Photographer</th>
<th>Video Librarian</th>
<th>Book Librarian</th>
<th>Store Manager</th>
</tr>
<tr>
<th>2013</th>
<td>John Mills</td>
<td>Virgil Bagdonas</td>
<td rowspan= "3">Reid Gilmore</td>
<td>Todd Heino</td>
<td rowspan="3">Eric Holmquist</td>
<td rowspan="9">Dave Eaton</td>
<td rowspan="2">Art Bodwell</td>
<td>Rick Angus</td>
<td>Mike Peters</td>
<td></td>
<td>Kevin Nee</td>
</tr>
<tr>
<th>2012</th>
<td>Dave Eaton</td>
<td>Jim Metcalf</td>
<td rowspan="2">Mike Peters</td>
<td>Peter Wilcox</td>
<td rowspan="3">Ray Asselin</td>
<td></td>
<td>Joe Giroux</td>
</tr>
<tr>
<th>2011</th>
<td>Charlie Croteau</td>
<td>Rick Angus</td>
<td>Ron Rocheleau</td>
<td>Peter Wilcox</td>
<td>Roger Boisvert</td>
<td>Mike Smith</td>
</tr>
Any leads on how to add a flag or counter to accomplish this is welcome. Thanks!

try this hope to work.(because I have not run it but think should work).
CODE for colspan:
for ($y = $year_max; $y >=$year_min; $y--){
echo '<tr><th>'.$y.'</th>';
$lastVal='';
$buf=array();
for ($i = 0; $i<count($offices_used); $i++){
(!isset($data[$y][$offices_used[$i]])?($data[$y][$offices_used[$i]]=''):'');// Im not sure that is really needed
if($lastVal==$data[$y][$offices_used[$i]]){
$buf[count($buf)-1]['rep']++;
}else{
$lastVal=$data[$y][$offices_used[$i]];
$buf[]=array('data'=>$lastVal,'rep'=>1);
}
foreach($buf as $arr){
echo '<td'.($arr['rep']>1?' colspan="'.$arr['rep'].'"':'') . '>'.$arr['data'].'</td>';
}
} echo '</tr>';
} // END FOR
NOTICE: error of code corrected
CODE for rowspan:(I think it can be down easier than this. bur I have tried to be good).
$buf=array();
for ($i = 0; $i<count($offices_used); $i++){// this loop makes fill $buf
$lastVal='';
for ($y = $year_max; $y >=$year_min; $y--){
(!isset($data[$y][$offices_used[$i]])?($data[$y][$offices_used[$i]]=''):'');// Im not sure that is really needed
if($lastVal==$data[$y][$offices_used[$i]]){
$buf[$i][count($buf[$i])-1]['rep']++;
}else{
$lastVal=$data[$y][$offices_used[$i]];
$buf[$i][$year_max-$y]=array('data'=>$lastVal,'rep'=>1);
}
}
}
$mtemp=$year_max;
foreach($buf as $row){
echo '<tr><th>'.$mtemp.'</th>';
foreach($row as $rec){
echo '<td'.($rec['rep']>1?' rowspan="'.$rec['rep'].'"':'') . '>'.$rec['data'].'</td>';
}
$mtemp--;
echo '</tr>';
}
really hope to work.
NOTICE: corrected

Solved by using:
############################################################################
######## PRINT OUT TABLE WITH YEARS AND OFFICES PLUS NAMES IN CELLS ########
for ($y = $year_max; $y >=$year_min; $y--){ // Loop through years
echo '<tr><th>'.$y.'</th>';
for ($i = 0; $i<count($offices_used); $i++){
if (isset($data[$y][$offices_used[$i]])){
$rowz =1;
if(!($data[$y][$offices_used[$i]] == $data[($y+1)][$offices_used[$i]])){
while ($data[$y][$offices_used[$i]] == $data[($y-$rowz)][$offices_used[$i]]) $rowz ++;
echo '<td rowspan = "'.$rowz.'">'.$data[$y][$offices_used[$i]].'</td>';
}
} // END IF
else {
echo '<td align = "center"> - </td>';
} // END ELSE
} echo '</tr>'; // End row of current year
} // END FOR Loop through years
echo '</table>';
See http://jsfiddle.net/eaton9999/8gMVK/ for resultant output page.
Thanks again to imsiso and other who helped!

I wrote a library a few days ago that can handle this stuff..
Have a look at https://github.com/donquixote/cellbrush
The benefit of the library is that you don't need to think about the order of cells in html, and which cells need to be skipped due to rowspan or colspan. Instead, you can just "paint" a cell anywhere in the grid, with whichever rowspan or colspan you want. And instead of specifying a number for rowspan or colspan, you simply specify the first and last row and column names of the rospan/colspan region.
E.g.
$table->td(['2011', '2013'], 'Secretary', 'Eric Holmquist');
Below is some code that creates the table you were asking for, with the help of this library. You still need some logic to calculate the intervals, but at least you don't need to worry about the integrity of the table html.
(This question is quite old, but there might still be people running into it from Google. So I hope it might be useful.)
<?php
require_once __DIR__ . '/vendor/autoload.php';
$data = array(
'2013' => array(
'President' => 'John Mills',
'Internal VP' => 'Virgil Bagdonas',
'External VP' => 'Reid Gilmore',
'Treasurer' => 'Todd Heino',
'Secretary' => 'Eric Holmquist',
'Newsletter' => 'Art Bodwell',
'Webmaster' => 'Dave Eaton',
'Photographer' => 'Rick Angus',
'Video Librarian' => 'Mike Peters',
'Store Manager' => 'Kevin Nee',
),
'2012' => array(
'President' => 'Dave Eaton',
'Internal VP' => 'Jim Metcalf',
'External VP' => 'Reid Gilmore',
'Treasurer' => 'Mike Peters',
'Secretary' => 'Eric Holmquist',
'Newsletter' => 'Art Bodwell',
'Webmaster' => 'Dave Eaton',
'Photographer' => 'Peter Wilcox',
'Video Librarian' => 'Ray Asselin',
'Store Manager' => 'Joe Giroux',
),
'2011' => array(
'President' => 'Charlie Croteau',
'Internal VP' => 'Reid Gilmore',
'External VP' => 'Rick Angus',
'Treasurer' => 'Mike Peters',
'Secretary' => 'Eric Holmquist',
'Newsletter' => 'Ron Rocheleau',
'Webmaster' => 'Dave Eaton',
'Photographer' => 'Peter Wilcox',
'Video Librarian' => 'Ray Asselin',
'Book Librarian' => 'Roger Boisvert',
'Store Manager' => 'Mike Smith',
),
);
// Collect positions to build table columns.
$positions = [];
foreach ($data as $year => $yearData) {
foreach ($yearData as $position => $person) {
$positions[$position] = TRUE;
}
}
$positions = array_keys($positions);
// Define table columns.
$table = (new \Donquixote\Cellbrush\Table())
->addColName('year')
->addColNames($positions)
;
// Create thead section.
$headRow = $table->thead()->addRow('head');
$headRow->th('year', 'Year');
foreach ($positions as $position) {
$headRow->th($position, $position);
}
// Create table rows with labels based on year.
$years = array_keys($data);
$table->addRowNames($years);
foreach ($years as $year) {
$table->th($year, 'year', $year);
}
// Fill table cells in each column.
foreach ($positions as $position) {
$periodPerson = NULL;
$periodFirstYear = NULL;
$periodLastYear = NULL;
$column = $table->colHandle($position);
foreach ($years as $year) {
$person = isset($data[$year][$position])
? $data[$year][$position]
: '-';
if (!isset($periodFirstYear)) {
// First year.
$periodFirstYear = $year;
}
elseif ($person !== $periodPerson) {
// Add a table cell with rowspan.
$column->td([$periodFirstYear, $periodLastYear], $periodPerson);
$periodFirstYear = $year;
}
$periodPerson = $person;
$periodLastYear = $year;
}
if (isset($periodFirstYear)) {
// Add a table cell with rowspan.
$column->td([$periodFirstYear, $periodLastYear], $periodPerson);
}
}
print $table->render();

Related

PHP: Words are repeating in while loop and group by is not working?

I am trying to display my data group by keyregion and then group by key_region currently it is working fine for key_region but for group by keyregion is not working headings are repeating, if headings are same it has to comes only one for keyregion see here output
Code:
Working of While loop is -
First it sort data with keyregion
After sorting with keyregion, it sort with key_region and year and group together.
var_export for $Zeile
array (
0 =>
(object) array(
'reisenr' => '2191302',
'beginn' => '2021-10-02',
'ende' => '2021-10-25',
'airline' => 'AI',
'status' => '4',
'price' => '4998',
'keywords' => 'indien24',
'keyregion' => 'Himalaya',
'key_region' => 'Indien & Himalaya',
'Shortlink' => 'die-indienreise.de/intensiv',
'keycountry' => 'India',
'tourname' => 'Indien Intensiv',
'jahr' => '2021',
'month' => '10',
'beginn_f' => 'Sa, 2. Okt',
'ende_f' => 'Mo, 25. Okt 2021',
'comment_de' => '',
'tage' => '23',
)
<?php
function ausgabe_einfach($zeile)
{
$i=0;
while(count($zeile) - 1 > $i){
global $status;
$keywords = $zeile[$i]->keywords;
$jahr = $zeile[$i]->jahr;
$key_region = $zeile[$i]->key_region;
$keyregion = $zeile[$i]->keyregion;
$beginn = $zeile[$i]->beginn;
?>
<table class="termine">
// Here is heading for $keyregion & $keycountry
<div class="date" style="color:#fc453e"><b><?php echo $keyregion; ?> <?php echo $jahr;?></b><br></div><b><caption class="date1"><?php echo $key_region; ?> </b></caption>
<?php
$j=$i+1;
//printing some values here
while((count($zeile) - 1 > $i) && (count($zeile) - 1 > $j) && ($j > $i) && ($jahr == $zeile[$j]->jahr) && (strtolower($key_region) == strtolower($zeile[$j]->key_region)) && (date("Y", strtotime($zeile[$i]->beginn)) == date("Y", strtotime($zeile[$j]->beginn))) && (strtolower($keyregion) == strtolower($zeile[$j]->keyregion))){
"";
//Printing output values here
like ReiseNR
$i++;
$j++;
}
$i++;
}
?>
<?php
}
If there any help in resolving my issue that will be much helpful for me and appreciated.

How to draw a table with data from Mysql?

I have obtained the following data through Mysql.
idx item_name parent_id
44 'A' -1
46 'B' -1
47 'C' 44
48 'D' 44
49 'E' 44
50 'F' 46
51 'G' 47
52 'H' 47
53 'I' 48
I want to draw a table using this data.
I've searched for information, but it's very difficult.
Is there anyone who can help me?
Example
<table>
<thead>
<tr>
<th>item1</th>
<th>item2</th>
<th>item3</th>
<th>value</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="4">A</td>
<td rowspan="2">C</td>
<td>G</td>
<td>-</td>
</tr>
<tr>
<td>H</td>
<td>-</td>
</tr>
<tr>
<td>D</td>
<td>I</td>
<td>-</td>
</tr>
<tr>
<td>E</td>
<td>-</td>
<td>-</td>
</tr>
<tr>
<td>B</td>
<td>F</td>
<td>-</td>
<td>-</td>
</tr>
</tbody>
Is there a PHP library related to this?
=========================================
The values in the database consist of a passenger structure. (Parent ID Existence)
I want to make this data into a table using PHP.
"Rowspan" will be used to accommodate the number of children.
However, this method of HTML coding is very difficult.
I need a library or a related example code.
Here you go, the code that I made to solve your problem.
It is not perfect but I hope you got the idea.
Your problem cannot be solved by a simple array loop, because your data is not a simple table but a tree. Therefore, using recursive loop to walk through the data is one of the solutions.
<?php
// the data, should be obtained from your database
// to simplify the code, I made them into an array of objects
$rows[] = (object) array( 'idx' => 44, 'name' => 'A', 'pid' => -1 );
$rows[] = (object) array( 'idx' => 46, 'name' => 'B', 'pid' => -1 );
$rows[] = (object) array( 'idx' => 47, 'name' => 'C', 'pid' => 44 );
$rows[] = (object) array( 'idx' => 48, 'name' => 'D', 'pid' => 44 );
$rows[] = (object) array( 'idx' => 49, 'name' => 'E', 'pid' => 44 );
$rows[] = (object) array( 'idx' => 50, 'name' => 'F', 'pid' => 46 );
$rows[] = (object) array( 'idx' => 51, 'name' => 'G', 'pid' => 47 );
$rows[] = (object) array( 'idx' => 52, 'name' => 'H', 'pid' => 47 );
$rows[] = (object) array( 'idx' => 53, 'name' => 'I', 'pid' => 48 );
// Build Tree
foreach($rows as $r) {
$r->child = [];
foreach($rows as $c) {
if($r->idx == $c->idx) continue;
if($c->pid == $r->idx)
$r->child[] = $c;
}
}
// recursive walk through the trees to set maxLevel and nodeLevel
function cLeaves($node, $level, &$maxLevel) {
$count = 0;
if(count($node->child) == 0) {
$node->span = 1;
$node->level = $level;
$maxLevel = $maxLevel < $level ? $level : $maxLevel;
return 1;
} else {
$node->level = $level;
$level++;
foreach($node->child as $c) {
$count += cLeaves($c, $level, $maxLevel);
}
$node->span = $count;
return $count;
}
}
// recursive walk through the trees to draw table
function drawTable($cnode, $maxLevel) {
echo '<td rowspan="'.$cnode->span.'">'.$cnode->name.'</td>';
if(count($cnode->child) == 0) {
if($cnode->level < $maxLevel) {
for($i = $cnode->level; $i<$maxLevel; $i++)
echo '<td>-</td>';
}
echo '<td>-</td>'; // for the value column
echo '</tr>';
return;
}
foreach($cnode->child as $c) {
drawTable($c, $maxLevel);
}
}
// update the data structure
$maxLevel = 0;
foreach($rows as $r) {
if($r->pid == -1) {
$level = 0;
$r->span = cLeaves($r, $level, $maxLevel);
$r->level = $level;
}
}
echo '<table border="1">';
echo '<tr>';
// draw table's title row
for($i = 0; $i <= $maxLevel; $i++) {
echo '<td>item'.($i+1).'</td>';
if($i == $maxLevel) echo '<td>value</td>';
}
echo '</tr>';
// draw tree on table format
foreach($rows as $r) {
if($r->pid == -1) {
echo '<tr>';
drawTable($r, $maxLevel);
}
}
echo '</table>';
?>
If you run the code, the result would be something like below:
What I still remember from PHP is, you can use for loop and put one of these rows into the php <tag>. Then use your SELECT query to get each tuple from MySql into each tuple's cells in this tag:
<tr>
<td> Cell value using Sql Select statement</td>
<td> Cell value using Sql Select statement</td>
<td> Cell value using Sql Select statement</td>
</tr>
You can do this process n of times depend on the No. Of rows you want to insert into the table.
Then, close your **PHP <tag>.
you can use mysqli_fetch_assoc to fetch your data from the database and run a loop to format it using html table:
<table border=1>
<thead>
<tr>
<th>idx</th>
<th>item_name</th>
<th>parent_id</th>
</tr>
</thead>
<tbody>
<?php
$con = mysqli_connect("localhost", "root", "", "yourdatabase");
$table = mysqli_query($con, "SELECT idx, item_name, parent_id FROM mytable");
while ($record = mysqli_fetch_assoc($table)) {
echo "<tr>";
echo "<td>" . $record["idx"] . "</td>";
echo "<td>" . $record["item_name"] . "</td>";
echo "<td>" . $record["parent_id"] . "</td>";
echo "</tr>";
}
?>
</tbody>
If you want to use a library, you can check codeigniter (PHP framework)'s table helper.
https://codeigniter.com/userguide3/libraries/table.html
$this->table->generate($table);

Slicing PHP Array Into Table

Not sure if "slice" is the right word.. however I have the following array stored in a variable.
Array (
[0] => Design|1-cylinder 4-stroke engine, water-cooled
[1] => Displacement|373.2 cm³
[2] => Bore|89 mm
[3] => Stroke|60 mm
[4] => Performance|32 kW (43 hp)
[5] => Starting aid|Electric starter
[6] => Transmission|6 speed, claw shifted
[7] => Engine lubrication|Wet sump
) 1
Note the "|"'s that are separating the content. This content should be in a table like this.
<table>
<thead>
<tr>
<td>Title</td>
<td>Details</td>
</tr>
</thead>
<tbody>
<tr>
<td>Engine Displacement</td>
<td>373.2 cm³</td>
</tr>
<tr>
<td>Transmission</td>
<td>6 speed, claw shifted</td>
</tr>
</tbody>
</table>
How can I write a foreach statement that would do this? I am not even sure where to start? Should I separate the arrays? Not sure.
Thanks in advance!
$aData = array(
'Design|1-cylinder 4-stroke engine, water-cooled',
'Displacement|373.2 cm³',
'Bore|89 mm',
'Stroke|60 mm',
'Performance|32 kW (43 hp)',
'Starting aid|Electric starter',
'Transmission|6 speed, claw shifted',
'Engine lubrication|Wet sump'
);
?>
<table>
<thead>
<tr>
<th>Title</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<?php
$iCountData = count( $aData );
for( $i = 0; $i < $iCountData; ++$i )
{
$aTmp = explode( '|', $aData[ $i ] );
echo '<tr>';
echo '<td>';
echo $aTmp[ 0 ];
echo '</td>';
echo '<td>';
echo $aTmp[ 1 ];
echo '</td>';
echo '</tr>';
}
?>
</tbody>
</table>

How to merge table row with PHP array?

I want to merge the table row if the date have an same id's. I have some array data like this :
Array
(
[0] => Array
(
[id] => 2
[date] => 05/13/2014
[content] => some contents 1
[act] => act1 act2 act3
)
[1] => Array
(
[id] => 2
[date] => 05/28/2014
[content] => some contents 1
[act] => act1 act2 act3
)
[2] => Array
(
[id] => 7
[date] => 06/04/2014
[content] => some contents 2
[act] => act1 act2 act3
)
)
Then I tried to group its data into the same id by :
if($queryx = $this->mymodel->myfunction($par)){
$datax = $queryx;
}
$i = 0;
foreach ($datax as $idx => $val) {
$dates[$val['id']][$i] = $val['date'].",".$val['id'];
$contn[$val['id']][$i] = $val['content'];
$i++;
}
then :
$j = 0; $y = 0;
echo "<table border='1'>\r\n";
foreach ($dates as $idx => $val) {
$tmpexp = explode(',', $val[$j]);
echo "<tr>\r\n";
echo "<td rowspan='".count($val)."'>".$tmpexp[0]."</td>\r\n";
foreach ($val as $idx1 => $val1) {
if($idx1 > 0)
{
echo "<tr>\r\n";
}
echo "<td>".$dates[$tmpexp[1]][$y]."</td>\r\n";
if($idx1 < 1)
{
echo "<td rowspan='".count($val)."'>".$contn[$tmpexp[1]][$y]."</td>\r\n";
echo "<td rowspan='".count($val)."'>act1 act2 act3</td>";
echo "</tr>\r\n";
}
$y++;
}
$j++;
}
echo "</table>";
There is no problem if the data have at least two child, but if the date only have one child (see data with id's 7) there is show an error because Undefined offset. So how I add some handler if there is only one child on the data. There is my desired result:
Please see this image:
I use the 'read ahead' technique for processing nested loops. It does mean that 'foreach' loops cannot be used as the next record must be read as soon as the current one has been processed. Basically, the last action you do in the loop is read the next record as you are setting it up for the next iteration. Note, you never test when to print a record as that is decided by the structure of the groups. The code loops are the same as the structure of the groups in the data
A 'group' is all the records with the same id.
I assume that the 'content' and 'act' are identical for each entry in the group.
Edited to add 'rowspan' attributes to the appropriate 'td' tags. I suspect css may be easier at this point.
The issue is that the group cannot be displayed until it is known how many entries are in it.
So, i 'buffer' all the records belonging to a group in an array. at the end of the group, it is displayed with the appropriate 'rowspan' attributes in the html.
It is tested on PHP 5.3.18. It includes test data.
<?php /* Q24028866 */
$testData = array(array('id' => 2, 'date' => '05/13/2014', 'content' => 'some contents 2', 'act' => 'act1 act2 act3'),
array('id' => 2, 'date' => '05/28/2014', 'content' => 'some contents 2', 'act' => 'act1 act2 act3'),
array('id' => 7, 'date' => '06/04/2014', 'content' => 'some contents 7', 'act' => 'act1 act2 act3'),
array('id' => 8, 'date' => '06/08/2014', 'content' => 'some contents 8', 'act' => 'act1 act2 act3'),
array('id' => 8, 'date' => '06/09/2014', 'content' => 'some contents 8', 'act' => 'act1 act2 act3'));
?>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<table border='1'>
<thead><th>Date</th><th>Content</th><th>Act</th></thead>
<?php
// use 'read ahead' so there is always a 'previous' record to compare against...
$iterContents = new \ArrayIterator($testData);
$curEntry = $iterContents->current();
while ($iterContents->valid()) { // there are entries to process
$curId = $curEntry['id'];
// buffer the group to find out how many entries it has...
$buffer = array();
$buffer[] = $curEntry;
$iterContents->next(); // next entry - may be same or different id...
$curEntry = $iterContents->current();
while ($iterContents->valid() && $curEntry['id'] == $curId) { // process the group...
$buffer[] = $curEntry; // store all records for a group in the buffer
$iterContents->next(); // next entry - may be same or different id...
$curEntry = $iterContents->current();
}
// display the current group in the buffer...
echo '<tr>';
echo '<td>', $buffer[0]['date'], '</td>';
$rowspan = count($buffer) > 1 ? ' rowspan="'. count($buffer) .'"' : '';
echo '<td', $rowspan, '>', $buffer[0]['content'], '</td>',
'<td', $rowspan, '>', $buffer[0]['act'], '</td>';
echo '</tr>';
for($i = 1; $i < count($buffer); $i++) {
echo '<tr><td>', $buffer[$i]['date'], '</td>';
echo '</tr>';
}
} ?>
</table>
</body>
</html>
The following code will give you a clue what you should do,
$newArray = array();
$counter=0;
foreach($datax as $key=>$val){
$newArray[$val['id']][$counter]['date'] = $val['date'];
$newArray[$val['id']][$counter]['content'] = $val['content'];
$newArray[$val['id']][$counter]['act'] = $val['act'];
$counter++;
}
$newArray = array_map('array_values', $newArray);

Display PHP multidimensional array in html table with each subarray in a column

I'm sure there's a fairly easy way to do this. I have an the following data in an array:
Array
(
[ActivityDiaryEntry] => Array
(
[date] => 2011-03-03
[type] => Walking
[minutes] => 60
)
)
Array
(
[ActivityDiaryEntry] => Array
(
[date] => 2011-03-02
[type] => Walking
[minutes] => 22
)
)
Array
(
[ActivityDiaryEntry] => Array
(
[date] => 2011-03-01
[type] => Biking
[minutes] => 45
)
)
I'm not too skilled at PHP, but I know how to display this data by row to display as <tr><td>[date]</td><td>[type]</td><td>[minutes]</td></tr>. But I'd like to have the data display in columns like this:
2011-03-01 | 2011-03-02 | 2011-03-03
------------------------------------
Biking | Walking | Walking
------------------------------------
45 | 22 | 60
I didn't test this, but it should work. It should serve as an example of what needs to be done. I tried to write this to limit the number of foreach loops used. If I reordered the data first and then performed the takes, I'd of needed 4 foreach loops. The benefit to this method is that you don't need to update the code if more columns are added, so long as all records have the same number of columns.
<?php
// Your list of records
$records = array(
array( "key1" => "value", "key2" => "value", "key3" => "value" ),
array( "key1" => "value", "key2" => "value", "key3" => "value" ),
array( "key1" => "value", "key2" => "value", "key3" => "value" )
);
// Create an array to store the values of each row based on number of columns in first value
$rows = array_fill( 0, count( $records[0] ), "" );
$keys = array_keys( $records[0] );
// Create a column for each record in it's respective row.
foreach( $records as $k => $record )
for( $i=0, $max=count( $rows ); $i < $max; $i++ )
$rows[ $i ] .= "<td>".$record[ $keys[ $i ] ]."</td>";
// Turn each row in our array into an html table row.
print "<tr>".implode( "</tr><tr>", $rows )."</tr>";
Here's the code test: http://codepad.org/SSS8S2eU
A little ugly but works :')
$a[0] = array('ActivityDiaryEntry' => array("date" => "2011-03-03", "type"=> "Walking", "minutes" => 60));
$a[1] = array('ActivityDiaryEntry' => array("date" => "2011-03-03", "type"=> "Walking", "minutes" => 22));
$a[2] = array('ActivityDiaryEntry' => array("date" => "2011-03-03", "type"=> "Biking", "minutes" => 42));
$keys = array_keys($a[0]["ActivityDiaryEntry"]);
echo '<table>';
for($c = 0; $c < count($a); $c++) {
echo '<tr>';
for($i = 0; $i < count($a[$c]['ActivityDiaryEntry']); $i++) {
echo '<td>' . $a[$i]['ActivityDiaryEntry'][$keys[$c]] . '</td>';
}
echo '</tr>';
}
echo '</table>';
http://codepad.org/5Tuk8x3Q
This code works if i am not wrong defining the array, but i suggest you play with all the options provided here and find a better solution.
$data = array (
array (
'ActivityDiaryEntry' => array
(
'date' => "2011-03-03",
'type' => "Walking",
'minutes' => 60
)
),
array (
'ActivityDiaryEntry' => array
(
'date' => "2011-03-02",
'type' => Walking,
'minutes' => 22
) ),
array (
'ActivityDiaryEntry' => array
(
'date' => "2011-03-01",
'type' => Biking,
'minutes' => 45
)
)
);
echo "<table>";
$i = 0;
foreach ($data as $key => $val) {
echo "<tr>";
foreach ($data as $kk => $vv){
if ($i==0) {
echo "<td>". $vv['ActivityDiaryEntry']['date'] ."</td>";
}else if ($i == 1){
echo "<td>". $vv['ActivityDiaryEntry']['type'] ."</td>";
}else if ($i == 2){
echo "<td>". $vv['ActivityDiaryEntry']['minutes'] ."</td>";
}
}
echo "</tr>";
$i++;
}
echo "</table>";
This would be a great candidate for DataTables, which is actually Javascript that I use to display my results generated on the back end by PHP. It's a full-blown javascript grid system that adds a ton of features to standard HTML table outputs. To make it work you would:
Get your results as shown and output as a json_encoded string (i.e, echo json_encode($array) I do this in a separate file so it outputs clean text to the screen.
On the page to display the table, setup a "dummy table"
Setup Datatables in the same page as the dummy table like this:
$(document).ready(function() {
$('#replace').dataTable( {
"bProcessing": true,
"sAjaxSource": 'file.php'
} );
} );
Set values for sorting, filtering, paging, etc. per the tutorial.
Datatables gives you so much more power than just a standard HTML table, and you're already 90% of the way there with the data. It's so much more user friendly than just jamming stuff on the screen.
Before transposing your data (converting columns to rows), you must reduce the depth/complexity by removing the unusable first level and generate an indexed array of what is left.
Then iterate the first array in the new, simplified data structure and extract column data. Each column (there are three) will be displayed in its own table row using a flexible implode()ing technique.
Code: (Demo)
$subarrays = array_column($array, "ActivityDiaryEntry");
echo '<table>';
foreach ($subarrays[0] as $column => $notUsed) {
echo '<tr><td>' , implode('</td><td>', array_column($subarrays, $column)) , '</td></tr>';
}
echo '</table>';
Output:
<table>
<tr>
<td>2011-03-03</td>
<td>2011-03-03</td>
<td>2011-03-03</td>
</tr>
<tr>
<td>Walking</td>
<td>Walking</td>
<td>Biking</td>
</tr>
<tr>
<td>60</td>
<td>22</td>
<td>42</td>
</tr>
</table>
You could write a for loop for each field, displaying one row in each loop.
The Javascript answer below might be a good way to do it, but I would suggest using PHP and tables if you are not completely comfortable using Javascript in your applications. It is also good PHP practice.
If I were you, I'd use code like this, and css properties to format the table how you'd like.
echo '<table>';
echo '<tr><td>Date</td><td>Type</td><td>Minutes</td></tr>';
foreach ($array as $entry){
echo '<tr>';
echo '<td>'.$entry['date'].'</td>';
echo '<td>'.$entry['type'].'</td>';
echo '<td>'.$entry['minutes'].'</td>';
echo '</tr>';
}
echo '</table>';
You can use stuff like this to edit your tables display, also check out http://www.w3schools.com/css/css_table.asp
echo '<tr style="border-bottom: 1px solid black;"></tr>';
cheers

Categories