Create a 'pivot' table from array [duplicate] - php

This question already has answers here:
Pivot a mysql result set and create html table/matrix
(4 answers)
Closed 1 year ago.
I have an array that looks like this:
Array (
Array ( [date] => 04/2021 [name] => Fred [value] => 12.00 )
Array ( [date] => 04/2021 [name] => Tom [value] => 160.00 )
Array ( [date] => 04/2021 [name] => Mike [value] => 9.00 )
Array ( [date] => 07/2021 [name] => Tony [value] => 200.00 )
Array ( [date] => 07/2021 [name] => Fred [value] => 43.00 )
Array ( [date] => 07/2021 [name] => Tom [value] => 114.00 )
Array ( [date] => 07/2021 [name] => Mike [value] => 28.00 )
)
I am trying to get the data into a simple HTML table where the name goes on the x axis, the date on the y axis and the values where they intersect.
For example:
Fred Tom Mike Tony
04/2021 12.00 160.00 9.00 0
07/2021 43.00 114.00 28.00 200.00
I do not know if I am over thinking this but I cannot get this to work - I can get the x axis to work by pulling out the unique values for name but then when it comes to the y axis and the intersections I cannot get the data to display how I need.
I either end up with repetition of columns or a single column and so on. This is where I have gotten up to but still scratching my head how to do this:
<?php
$unique_names = array_unique(array_map(function($elem){
return $elem['name'];
}, $data));
?>
<thead>
<tr>
<th> </th>
<?php foreach ($unique_names as $i) { ?>
<th><?php print $i;?></th>
<?php } ?>
</tr>
</thead>
<tbody>
<?php
foreach ($data as $row) {
for ($i=0; $i<=count($unique_names);$i++) {
if ($i==0) {
print "<tr><td>".$row['date']."<td>";
} else {
print "<td>".$row['value']."<td>";
}
if ($i==count($unique_dates)) {
print "</tr>";
}
}
}
?>
</tbody>

First, reorganize your data into an array that uses the date as key on the first level, and the name on the second. Collect the names at the same time:
$input = [
['date' => '04/2021', 'name' => 'Fred', 'value' => '12.00'],
['date' => '04/2021', 'name' => 'Tom', 'value' => '160.00'],
['date' => '04/2021', 'name' => 'Mike', 'value' => '9.00'],
['date' => '07/2021', 'name' => 'Tony', 'value' => '200.00'],
['date' => '07/2021', 'name' => 'Fred', 'value' => '43.00'],
['date' => '07/2021', 'name' => 'Tom', 'value' => '114.00'],
['date' => '07/2021', 'name' => 'Mike', 'value' => '28.00'],
];
$data = $names = [];
foreach($input as $item) {
$data[$item['date']][$item['name']] = $item['value'];
$names[] = $item['name'];
}
$names = array_unique($names);
Then create your table. Loop over the names to create the header row first.
Then loop over the reorganized data array (to create one row for each date), and inside that loop over your names again - if you find an entry matching the name in the data array, then output the value, otherwise nothing.
<table>
<tr>
<th></th>
<?php foreach($names as $name): ?>
<th><?php echo $name; ?></th>
<?php endforeach; ?>
</tr>
<?php foreach($data as $date => $userData): ?>
<tr>
<td><?php echo $date; ?></td>
<?php foreach($names as $name): ?>
<td><?php echo $userData[$name]??'-'; ?></td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</table>
Result:
<table>
<tr>
<th></th>
<th>Fred</th>
<th>Tom</th>
<th>Mike</th>
<th>Tony</th>
</tr>
<tr>
<td>04/2021</td>
<td>12.00</td>
<td>160.00</td>
<td>9.00</td>
<td>-</td>
</tr>
<tr>
<td>07/2021</td>
<td>43.00</td>
<td>114.00</td>
<td>28.00</td>
<td>200.00</td>
</tr>
</table>

Here is your answer, great exercise.
<html>
<head>
<style>
table, th, td {
border: 1px solid black;
}
</style>
</head>
<body>
<?php
$data = Array (
Array ( 'date' => '04/2021' ,'name' => 'Fred' ,'value' => '12.00' ),
Array ( 'date' => '04/2021' ,'name' => 'Tom' ,'value' => '160.00' ),
Array ( 'date' => '04/2021' ,'name' => 'Mike', 'value' => '9.00' ),
Array ( 'date' => '07/2021' ,'name' => 'Tony' ,'value' => '200.00' ),
Array ( 'date' => '07/2021' ,'name' => 'Fred' ,'value' => '43.00' ),
Array ( 'date' => '07/2021' ,'name' => 'Tom' ,'value' => '114.00' ),
Array ( 'date' => '07/2021' ,'name' => 'Mike' ,'value' => '28.00' )
);
foreach ($data as $key => $value) {
$tmp[$value['name']][$value['date']] = $value;
}
$unique_names = array_unique(array_map(function($elem){
return $elem['name'];
}, $data));
$unique_dates = array_unique(array_map(function($elem){
return $elem['date'];
}, $data));
?>
<table>
<thead>
<tr>
<th>Dates</th>
<?php foreach ($unique_names as $i) { ?>
<th><?php print $i;?></th>
<?php } ?>
</tr>
</thead>
<?php
foreach ($unique_dates as $date)
{
echo "<tr>";
echo "<td>".$date."</td>";
foreach ($unique_names as $name) {
if(array_key_exists($date,$tmp[$name]))
echo "<td>".$tmp[$name][$date]['value']."</td>";
else
echo "<td>0</td>";
}
echo "</tr>";
}
?>
<tbody>
</tbody>
</table>
</body>
</html>

Related

How do I add <tr> and complete </tr> tag in PHP foreach loop

I have this kind of array in $form_all_data variable.
Array
(
[0] => stdClass Object
(
[id] => 111
[form_id] => 1
[entry_id] => 38
[meta_key] => 6
[meta_value] => Student 1
[item_index] =>
)
[1] => stdClass Object
(
[id] => 112
[form_id] => 1
[entry_id] => 38
[meta_key] => 3
[meta_value] => Not sure
[item_index] =>
)
[2] => stdClass Object
(
[id] => 113
[form_id] => 1
[entry_id] => 38
[meta_key] => 5
[meta_value] => 55
[item_index] =>
)
[3] => stdClass Object
(
[id] => 129
[form_id] => 1
[entry_id] => 43
[meta_key] => 6
[meta_value] => Student 3
[item_index] =>
)
[4] => stdClass Object
(
[id] => 130
[form_id] => 1
[entry_id] => 43
[meta_key] => 3
[meta_value] => Yes
[item_index] =>
)
[5] => stdClass Object
(
[id] => 131
[form_id] => 1
[entry_id] => 43
[meta_key] => 5
[meta_value] => 55
[item_index] =>
)
)
I am showing all this data inside <table>. These entries are differentiated as per entry_id.
I want to add <tr> tag when every time new entry_id is there in the loop and want to complete </tr> tag when every time same entry_id is last in the loop.
Something like this. Please check this image
This means I want to show entry_id 38 data in one <tr> and entry_id 43 data in another <tr>
How can I do this ?
In my code , it is adding <tr> with every new iteration
<?php
$i = 1;
foreach ( $form_all_data as $check_form_all_data_key => $check_form_all_data_value ) { ?>
<tr>
<?php
if ( $check_form_all_data_value->form_id == 1 ) {
if ( $check_form_all_data_value->meta_key == 6 ) { ?>
<td class=""><?php echo $check_form_all_data_value->meta_value ?></td>
<?php }
if ( $check_form_all_data_value->meta_key == 3 ) { ?>
<td class=""><?php echo $check_form_all_data_value->meta_value ?></td>
<?php }
} else {
} ?>
</tr>
<?php $i++; } ?>
Here is the working code.
<?php
$form_all_data = [
(object)['entry_id' => 1, 'value' => '1 1', 'type' => '1'],
(object)['entry_id' => 1, 'value' => '1 2', 'type' => '2'],
(object)['entry_id' => 2, 'value' => '2 1', 'type' => '1'],
(object)['entry_id' => 2, 'value' => '2 2', 'type' => '2'],
];
$currentEntryId = null;
$needCloseTr = false;
echo '<table>';
foreach ($form_all_data as $row) {
//is next entry?
if ($currentEntryId !== $row->entry_id) {
//close previous tr
if ($needCloseTr) {
echo '</tr>';
$needCloseTr = false;
} else {
$needCloseTr = true;
}
$currentEntryId = $row->entry_id;
echo '<tr>';
}
echo sprintf('<td>%s</td>', $row->value);
}
//close last tr
if ($needCloseTr) {
echo '</tr>';
}
echo '</table>';
But what you are doing is not correct.
It's better to process the $form_all_data array first and get the data that doesn't need tricky processing, like this:
<?php
$form_all_data = [
(object)['entry_id' => 1, 'value' => '1 1', 'type' => '1'],
(object)['entry_id' => 1, 'value' => '1 2', 'type' => '2'],
(object)['entry_id' => 2, 'value' => '2 1', 'type' => '1'],
(object)['entry_id' => 2, 'value' => '2 2', 'type' => '2'],
];
$result = [];
foreach ($form_all_data as $row) {
$result[$row->entry_id][$row->type] = $row->value;
}
var_dump($result);
Detect entry_id change with as following code
<?php
$i = 1;
$prev_entry_id = 0;
foreach ( $form_all_data as $check_form_all_data_key => $check_form_all_data_value ) { ?>
<?php if($prev_entry_id == 0){
echo "<tr>";
}else if($prev_entry_id != $check_form_all_data_value->entry_id){
echo "</tr><tr>";
} ?>
<?php
if ( $check_form_all_data_value->form_id == 1 ) {
if ( $check_form_all_data_value->meta_key == 6 ) { ?>
<td class=""><?php echo $check_form_all_data_value->meta_value ?></td>
<?php }
if ( $check_form_all_data_value->meta_key == 3 ) { ?>
<td class=""><?php echo $check_form_all_data_value->meta_value ?></td>
<?php }
} else {
} ?>
<? $prev_entry_id = $check_form_all_data_value->entry_id; ?>
<?php $i++; } ?>
</tr> // Don't forget this at the end
Here is working solution as suggested by #Kevin
<?php
$new_data = array();
foreach ( $form_all_data as $k=> $v ) {
$new_data[$v->entry_id][] = $v;
}
foreach ( $new_data as $new_data_key => $new_data_value ) { ?>
<tr>
<?php
foreach ( $new_data_value as $check_form_all_data_key => $check_form_all_data_value ) {
if ( $check_form_all_data_value->form_id == 1 ) {
if ( $check_form_all_data_value->meta_key == 6 ) { ?>
<td class=""><?php echo $check_form_all_data_value->meta_value ?></td>
<?php }
if ( $check_form_all_data_value->meta_key == 3 ) { ?>
<td class=""><?php echo $check_form_all_data_value->meta_value ?></td>
<?php }
} else {
} ?>
<?php } ?>
</tr>
<?php } ?>
$rows = [];
foreach ($form_all_data as $row) {
if (!isset($rows[$row->id])) {
$rows[$row->id] = [];
}
$rows[$row->id][] = $row;
}
$html = '';
foreach ($rows as $row) {
$html .= '<tr>';
foreach ($row as $cell) {
$html .= '<td>'.$cell->meta_value.'</td>';
}
$html .= '</tr>';
}
I think you should use switch case for form_id and if clause for meta_key. For example :
<?php
$row = "";
foreach ($form_all_data as $check_form_all_data_key => $check_form_all_data_value)
{
$row .= "<tr>";
switch ($check_form_all_data_key->form_id)
{
case 1:
if ($check_form_all_data_value->meta_key == 6 || $check_form_all_data_value > meta_key = 3)
$row .="<td>".$check_form_all_data_value->meta_value."</td>";
break;
case 2:
if ($check_form_all_data_value->meta_key == 1 || $check_form_all_data_value > meta_key = 5 || $check_form_all_data_value > meta_key = 2)
$row .="<td>".$check_form_all_data_value->meta_value."</td>";
break;
default:
// more case form_id you want check
break;
}
$row .= "</tr>";
}
echo $row;
?>

Creating table from multidimention array

I have multidimensional arrays with which I need to make a table in html. I have a problem with matching catalog numbers with dates in the table.
I created an array (little part of it below):
array cotains date => CatalogNo => [catalogNo],[count],[date]
Array
(
[2019/07/19] => Array
(
[71156] => Array
(
[catalogNo] => 71156
[count] => 22
[date] => 2019/07/19
)
[71157] => Array
(
[catalogNo] => 71157
[count] => 21
[date] => 2019/07/19
)
[71221] => Array
(
[catalogNo] => 71221
[count] => 217
[date] => 2019/07/19
)
)
[2019/07/18] => Array
(
[71156] => Array
(
[catalogNo] => 71156
[count] => 26
[date] => 2019/07/18
)
[71157] => Array
(
[catalogNo] => 71157
[count] => 25
[date] => 2019/07/19
)
[71221] => Array
(
[catalogNo] => 71221
[count] => 281
[date] => 2019/07/19
)
[71222] => Array
(
[catalogNo] => 71221
[count] => 173
[date] => 2019/07/19
)
...
I did something like this but this is just bad. I dont know how to do it actually.
$dane_arr <- this is the whole array
<table>
<tr>
<th>CatalogNo</th>
<?php
foreach( $dane_arr as $k => $v )
{
?>
<th><?php echo $k ?></th>
<?php
}
?>
</tr>
<?php
foreach( $dane_arr as $k_date => $date_ )
{
foreach( $date_ as $k_nrArt_ => $nrArt_ )
{ ?>
<tr>
<td><?php echo $nrArt_['catalogNo'] ?></td>
<td><?php echo $nrArt_['count'] ?></td>
</tr>
<?php
}
}
?>
`
There are duplicates in CatalogNo and of course dates doesn't fit.
I want to create table, something like that:
CatalogNo | 2019/07/18 | 2019/07/19 | ...
71156 26 22 ...
71157 25 21 ...
71221 281 217 ...
71222 173 0 ...
(Of course without duplicates in 'CatalogNo')
You would first need to rearrange your array. Then you get all dates, and create the table:
<?php
$catalogUsage = [];
foreach ($dane_arr as $date => $catalogs) {
foreach( $catalogs as $catalogNo => $catalog) {
$catalogUsage[$catalogNo][$date] = $catalog['count'];
}
}
$allDates = array_keys($dane_arr);
?>
<table>
<tr>
<th>CatalogNo</th>
<?php
foreach ($allDates as $date) {
echo "<th>$date</th>"
}
?>
</tr>
<?php
foreach($catalogUsage as $catalogNo => $counts)
{
echo "<tr><td>$catalogNo</td>";
foreach ($allDates as $date) {
echo "<td>" . (isset($counts[$date]) ? $counts[$date] : 0) . "</td>";
}
echo "</tr>";
}
?>
</table>
Code is untested, since I haven't got the original array, so bugs might exist. I just hope this gives you some new inspiration.

Associative Array within Associative Array

I am new to PHP and am trying to apply a named array within a named array. I have been able to apply each rope name (i.e. "Poly Soak") along with img, title, blurb, desc, etc. but am having a difficult time trying to apply $specTable into a table. I am also trying to apply $applications and $benefits with no luck.
I am using the using the GET command to generate each page. Pages populate as follows:
water-rescue-ropes.php?value=aqua-d
water-rescue-ropes.php?value=poly-soak... etc
function strip_bad_chars( $input ) {
$output = preg_replace( "/[^a-zA-Z0-9_-]/", "", $input );
return $output; }
if (isset($_GET['value'])) {
$waterRescueRope = strip_bad_chars( $_GET['value'] );
$rope = $waterRescueRopes[$waterRescueRope];}
Here is the edited array info:
$waterRescueRopes = array(
"poly-soak" => array(
'img' => "3P",
'title' => "Poly Soak™",
'blurb' => "Pelican’s 16 strand kernmantle construction is a...",
'desc' => "Polypropylene Water Rescue Rope",
'construction' => "16 Strand",
'cover' => "Polypropylene",
'core' => "Polypropylene",
array(
array(
'sku' => "3P-12Y",
'diameter' => "3/8"",
'tensile' => 3000,
'weight' => 3.4,
),
array(
'sku' => "3P-14Y",
'diameter' => "7/16"",
'tensile' => 3380,
'weight' => 4.7,
),
),
array("Water Rescue", "Canyoneering"),
array("Lightweight", "Buoyant", "High Visibility"),
),
"poly-soak-economy" => array(
'img' => "FQK",
'title' => "Poly Soak™ Economy",
'blurb' => "All the great benefits and features of our Poly Soak rope but at a lower cost.",
'desc' => "Polypropylene Economy Water Rescue Rope",
'construction' => "16 Strand",
'cover' => "Polypropylene",
'core' => "Polypropylene",
array(
array(
'sku' => "FQK-502",
'diameter' => "1/8"",
'tensile' => 2000,
'weight' => 1.5,
),
),
array("Water Rescue"),
array("Economical", "Lightweight", "Buoyant"),
),
"poly-soak-2" => array(
'img' => "3PN",
'title' => "Poly Soak™",
'blurb' => "This UL certified polypropylene rope is approved for...",
'desc' => "NFPA® Water Rescue Rope",
'construction' => "24 Strand",
'cover' => "Polypropylene",
'core' => "Polypropylene",
array(
array(
'sku' => "3PN-12Y",
'diameter' => "3/8"",
'tensile' => 4200,
'weight' => 3.05,
),
),
array("Water Rescue", "Canyoneering", "Mooring"),
array("Bright Colors for Greater Visibility", "Supple for Compact Storage", "Certified to the Highest Standard", "Buoyant"),
),
"aqua-d" => array(
'img' => "3q",
'title' => "Aqua-D™",
'blurb' => "This water rescue rope has a blended Dyneema® and polypropylene core. With a multifilament polypropylene cover, this rope floats and has near zero water retention. It is extremely strong, light 'weight', and has a no-stretch braid that meets the needs of coastal and river rescue professionals worldwide.",
'desc' => "Dyneema® Polypropylene Water Rescue Rope",
'construction' => "16 Strand",
'cover' => "Polypropylene",
'core' => "Dyneema®",
array(
array(
'sku' => "3Q-08Y",
'diameter' => "1/4"",
'tensile' => "3200",
'weight' => "1.7",
),
array(
'sku' => "3Q-10Y",
'diameter' => "5/16"",
'tensile' => "3400",
'weight' => "2.3",
),
array(
'sku' => "3Q-12Y",
'diameter' => "3/8"",
'tensile' => "4950",
'weight' => "3.4",
),
),
array("Minimal Water Retention", "Strong & Lightweight", "Buoyant"),
array("Water Rescue"),
), );
Additional included functions:
function get_specs($array = false)
{
if (!is_array($array))
return array();
elseif(empty($array))
return array();
foreach($array as $polytype => $polydata) {
$new[$polytype]['specs'] = (!empty($polydata[0]))? $polydata[0]:array();
$new[$polytype]['applications'] = (!empty($polydata[1]))? $polydata[1]:array();
$new[$polytype]['benefits'] = (!empty($polydata[2]))? $polydata[2]:array();
}
return $new;
}
Here is the edited specTable:
<?php function display_specs($spec = array(),$name = false)
{
if(!empty($spec[$name]['specs'])) {
ob_start();
foreach($spec[$name]['specs'] as $specs) {
?>
<tr>
<td><?php echo $specs['sku']; ?></td>
<td><?php echo $specs['diameter']; ?></td>
<td><?php echo $specs['tensile']; ?></td>
<td><?php echo $specs['weight']; ?></td>
</tr>
<?php
}
$data = ob_get_contents();
}
} ?>
// Isolates the specs from the main array
$specs = get_specs($waterRescueRopes);
// Alternately, you can loop through the main array and get all
<?php foreach($specs as $polytype => $spec) {
echo display_specs($specs,$_GET['value']);
}
?>
Edited Applications (Benefits is in similar list):
<?php function display_applications($spec = array(),$name = false)
{
if(!empty($spec[$name]['applications'])) {
ob_start();
foreach($spec[$name]['applications'] as $apps) {
?>
<li><?php echo $apps; ?></li>
<?php
}
$data = ob_get_contents();
return $data;
}
}
?>
<tr valign='top'>
<td class="td-item-cell"><article>
<div class="rel_product_wrapper">
<h3>Applications</h3>
<ul>
<li>
<?php
foreach($specs as $polytype => $spec) {
echo display_applications($specs,$_GET['value']);
}
?>
</li>
</ul>
</div>
</article></td>
</tr>
I currently have them populating what I need but multiple times ( four times for the four types of rope, I am assuming).
Thank you for your time! I appreciate it! :)
Remove the variables in your array, then create a function to extract just those aspects you need separately. The reason what you are doing does not work is because each time you write $specTable on each array, you re-assign/overwrite the previously-assigned $specTable to the current array until finally it is assigned the last array in the main array. That is why only one shows up. You need to save out those aspects to new arrays:
FUNCTIONS: Place functions at the top of the page OR in a different file that you include on this page for use. It is better to include using something like include("function.specs.php") because then you can reuse the functions on different pages if you want.
function get_specs($array = false)
{
if (!is_array($array))
return array();
elseif(empty($array))
return array();
foreach($array as $polytype => $polydata) {
$new[$polytype]['specs'] = (!empty($polydata[0]))? $polydata[0]:array();
$new[$polytype]['applications'] = (!empty($polydata[1]))? $polydata[1]:array();
$new[$polytype]['benefits'] = (!empty($polydata[2]))? $polydata[2]:array();
}
return $new;
}
function display_specs($spec = array(),$name = false)
{
if(!empty($spec[$name]['specs'])) {
ob_start();
foreach($spec[$name]['specs'] as $specs) {
?>
<tr>
<td><?php echo $specs['sku']; ?></td>
<td><?php echo $specs['diameter']; ?></td>
<td><?php echo $specs['tensile']; ?></td>
<td><?php echo $specs['weight']; ?></td>
</tr>
<?php
}
$data = ob_get_contents();
return $data;
}
}
// For sake of ease, you can do an application one by itself,
// Normally, you could just do one class/method that handles all the
// the different arrays
function display_applications($spec = array(),$name = false)
{
if(!empty($spec[$name]['applications'])) {
ob_start();
foreach($spec[$name]['applications'] as $apps) {
?>
<tr>
<td><?php echo $apps; ?></td>
</tr>
<?php
}
$data = ob_get_contents();
return $data;
}
}
Using the functions on your page:
// Isolates the specs from the main array
$specs = get_specs($waterRescueRopes);
// To select one product out of the bunch, just use the name from the array.
// Note, you need the $specs array as the first argument
echo display_specs($specs,"poly-soak");
echo display_applications($specs,"poly-soak");
// Alternately, you can loop through the main array and get all: ?>
<table>
<?php
foreach($specs as $polytype => $spec) {
echo display_specs($specs,$polytype);
echo display_applications($specs,$polytype);
}
?>
</table>
Applications Part: Because the function already does the loop for you, you just need to echo it:
<tr valign='top'>
<td class="td-item-cell"><article>
<div class="rel_product_wrapper">
<h3>Applications</h3>
<ul>
<li>
<?php echo display_applications($specs,$_GET['value']); ?>
</li>
</ul>
</div>
</article></td>
</tr>
The RAW print_r($specs) gives you:
Array
(
[poly-soak] => Array
(
[specs] => Array
(
[0] => Array
(
[sku] => 3P-12Y
[diameter] => 3/8"
[tensile] => 3000
[weight] => 3.4
)
[1] => Array
(
[sku] => 3P-14Y
[diameter] => 7/16"
[tensile] => 3380
[weight] => 4.7
)
)
[applications] => Array
(
[0] => Water Rescue
[1] => Canyoneering
)
[benefits] => Array
(
[0] => Lightweight
[1] => Buoyant
[2] => High Visibility
)
)
[poly-soak-economy] => Array
(
[specs] => Array
(
[0] => Array
(
[sku] => FQK-502
[diameter] => 1/8"
[tensile] => 2000
[weight] => 1.5
)
)
[applications] => Array
(
[0] => Water Rescue
)
[benefits] => Array
(
[0] => Economical
[1] => Lightweight
[2] => Buoyant
)
)
[poly-soak-2] => Array
(
[specs] => Array
(
[0] => Array
(
[sku] => 3PN-12Y
[diameter] => 3/8"
[tensile] => 4200
[weight] => 3.05
)
)
[applications] => Array
(
[0] => Water Rescue
[1] => Canyoneering
[2] => Mooring
)
[benefits] => Array
(
[0] => Bright Colors for Greater Visibility
[1] => Supple for Compact Storage
[2] => Certified to the Highest Standard
[3] => Buoyant
)
)
[aqua-d] => Array
(
[specs] => Array
(
[0] => Array
(
[sku] => 3Q-08Y
[diameter] => 1/4"
[tensile] => 3200
[weight] => 1.7
)
[1] => Array
(
[sku] => 3Q-10Y
[diameter] => 5/16"
[tensile] => 3400
[weight] => 2.3
)
[2] => Array
(
[sku] => 3Q-12Y
[diameter] => 3/8"
[tensile] => 4950
[weight] => 3.4
)
)
[applications] => Array
(
[0] => Minimal Water Retention
[1] => Strong & Lightweight
[2] => Buoyant
)
[benefits] => Array
(
[0] => Water Rescue
)
)
)

If all of a specific PHP array element are null, don't display table column

I have the following array of client data:
Array
(
[0] => Array
(
[client_id] => 3680
[firstname] => Brian
[surname] => May
[company] =>
)
[1] => Array
(
[client_id] => 3688
[firstname] => Freddie
[surname] => Mercury
[company] =>
)
[2] => Array
(
[client_id] => 3694
[firstname] => Roger
[surname] => Taylor
[company] =>
)
)
I want to display this in a table however if any element is null in ALL cases (such as "company" in this example) I don't want to show that column in the table.
Can anyone suggest how this may be done without first looping through the whole array?
You cant avoid doing loopings in this case, so the best approach I can think about your case is:
<?php
$test = array
(
array
(
client_id => 3680,
firstname => 'Brian',
surname => 'May',
company => null
),
array
(
client_id => 3688,
firstname => 'FreddieFreddie',
surname => 'Mercury',
company => null
),
array
(
client_id => 3694,
firstname => 'Roger',
surname => 'Taylor',
company => null
)
);
$empty_columns = false;
foreach ($test as $item) {
$keys = array_keys($item, null, true);
if (count($keys) == 0)
{
$empty_columns = null;
break;
}
if ($empty_columns===false)
$empty_columns = $keys;
$empty_columns= array_intersect($empty_columns, $keys);
}
print_r($empty_columns);
?>
The $empty_columns will return one array with the columns where all the values are NULL;
In this example:
Array
(
[0] => company
)
Just check this array before print your columns.
You can use
$array = array(
array('client_id' => 3680,'firstname' => 'Brian','surname' => 'May','company' => NULL),
array('client_id' => 3688,'firstname' => 'Freddie','surname' => 'Mercury','company' => ''),
array('client_id' => 3694,'firstname' => 'Roger','surname' => 'Taylor','company' => 'Hello World'));
print("<table>");
foreach ( $array as $list ) {
print("<tr>");
$col = array();
foreach ( $list as $value ) {
empty($value) or $col[] = $value;
}
if (count($col) != count($list)) {
$ele = array_pop($col);
foreach ( $col as $td ) {
printf("<td>%s</td>", $td);
}
printf("<td colspan=\"2\">%s</td>", $ele);
} else {
foreach ( $col as $td ) {
printf("<td>%s</td>", $td);
}
}
print("</tr>");
}
print("</table>");
Output
<table>
<tr>
<td>3680</td>
<td>Brian</td>
<td colspan="2">May</td>
</tr>
<tr>
<td>3688</td>
<td>Freddie</td>
<td colspan="2">Mercury</td>
</tr>
<tr>
<td>3694</td>
<td>Roger</td>
<td>Taylor</td>
<td>Hello World</td>
</tr>
</table>
code to check for all nulls
$company=1;
foreach($yoyrary as $ary)
{
if($ary[company]==null)
{
$company++
}
}
now code to for display table
<table>
<th>client_id</th>
<th>firstname</th>
<th>surname</th>
<?php if($company!=count($yourary)){?><th>company</th><?php }?>
foreach($yoyrary as $ary)
{
<td>client_id data</td>
<td>firstname data</td>
<td>surname data</td>
<?php if($company!=count($yourary)){?><td>company data</td><?php }?>
}?>
</table>
$array >> your array
foreach($array as $arr){
if( !empty($arr['client_id']) && !empty($arr['firstname']) && !empty($arr['surname']) & !empty($arr['company']) ){
//show that column
}else{
//Don't show
}
}

Suggested design for submitting a table of data in PHP

Hi I'm looking for suggestions on how best to handle the submission of a database table.
So far, I've generated the repeating rows data like so:
<table border=1>
<tr>
<th>Phone Number</th>
<th>Prefix CallerID with</th>
<th>Seconds to ring before<br/>reaching voicemail</th>
<th>Voice mailbox<br/>extension number</th>
<th>Notes</th>
</tr>
<?php
$id = 1;
foreach ( $line_detail as $line ){
echo '<tr>';
echo '<td>'.form::input($id.'_did', $line->did).'</td>';
echo '<td>'.form::input($id.'_cid_prefix', $line->cid_prefix).'</td>';
echo '<td>'.form::input(array($id.'_dial_timeput', 'size'=>15, 'maxlength'=>3), $line->dial_timeout).'</td>';
echo '<td>'.form::dropdown($id.'_extension', $phones, $line->voicemail).'</td>';
echo '<td>'.form::input($id.'_notes', $line->notes).'</td>';
echo "</tr>";
$id++;
}
?>
</table>
And when I submit this I have repeating data like this:
(array) Array
(
[1_did] => 64123456789
[1_cid_prefix] => DDI-
[1_extension] => 800
[1_notes] =>
[2_did] => 645678903
[2_cid_prefix] => TEST-
[2_extension] => 820
[2_notes] =>
[submit] => Save
)
Ok, so now I can group them by id and submit an update to the database.
But, I'm wondering if there is a better way of doing this.
PHP's array notation for input names is the way to go.
<input name="data[<?php echo $id;?>]['did'] />
<input name="data[<?php echo $id;?>]['cid_prefix'] />
<input name="data[<?php echo $id;?>]['extension']"/>
...
You'll end up, once the data are posted, with a nice two-dimensional associative array.
you can build form like this:
foreach ( $line_detail as $line ){
echo '<tr>';
echo '<td>'.form::input('did['.$id.']', $line->did).'</td>';
echo '<td>'.form::input('cid_prefix['.$id.']', $line->cid_prefix).'</td>';
echo '<td>'.form::input(array('dial_timeput['.$id.']', 'size'=>15, 'maxlength'=>3), $line->dial_timeout).'</td>';
echo '<td>'.form::dropdown('extension['.$id.']', $phones, $line->voicemail).'</td>';
echo '<td>'.form::input('notes['.$id.']', $line->notes).'</td>';
echo "</tr>";
$id++;
}
it will give you the following array:
(array) Array
(
[did] => array(
[1] => 64123456789,
[2] => 645678903,
)
[cid_prefix] => array(
[1] => 'DDI-',
[2] => 'TEST-',
)
[extension] => array(
[1] => 800,
[2] => 820,
)
[notes] => array(
[1] => '',
[2] => '',
)
[submit] => Save
)
it might be a little more convinient

Categories