My data comes from a database, and has been grouped by day_id, so the array is sorted by day_id.
Code + sample output provided, kind of hard to put in words.
I got my inspiration so far from this accepted answer, but I need a slight adjustment.
$array = array(
0 => array(
'id' => '5',
'day_id' => '1',
'Foo' => array(
'id' => '28',
'name' => 'My day_id is 1'
)
),
1 => array(
'id' => '6',
'day_id' => '1',
'Foo' => array(
'id' => '29',
'name' => 'My day_id is 1'
)
),
2 => array(
'id' => '7',
'day_id' => '2',
'Foo' => array(
'id' => '30',
'name' => 'My day_id is 2'
)
),
3 => array(
'id' => '8',
'day_id' => '3',
'Foo' => array(
'id' => '31',
'name' => 'My day_is 3'
)
)
);
And my code to output it:
$day = 0;
foreach($array as $a) {
// $a['day_id'] = 1, condition is true. output header once.
if($day != $a['day_id']) {
echo '<h3>The Day is ' . $a['day_id'] . '</h3>' . "\n";
}
// output the elements Foo key content.
echo $a['Foo']['name'] . "\n";
// store the current value to compare on the next iteration
// $a['day_id'] will eventually be 2, causing the condition to fire again.
$day = $a['day_id'];
}
This outputs:
<h3>The Day is 1</h3>
My day_id is 1
My day_id is 1
<h3>The Day is 2</h3>
My day_id is 2
<h3>The Day is 3</h3>
My day_is 3
I now want to wrap each "Day" in a DIV, but I cannot figure out the logic. If I replace the <h3> with an open div, I do not know where to put the closing </div>. My attempts thus far have just led to each day having an open div, but not a closed one so they are nested, rather than separate.
I can't put the </div><div class="day-X"> as there will be an extra </div> at the start which would break the layout.
Desired output:
<div class="day-1">
<h3>The Day is 1</h3>
My day_id is 1
My day_id is 1
</div>
<div class="day-2">
<h3>The Day is 2</h3>
My day_id is 2
</div>
<div class="day-3">
<h3>The Day is 3</h3>
My day_is 3
</div>
Hope this makes sense - thanks
You will need to loop twice, one for the days and one for the items that has this day. Without using any other SQL queries you will need to store the days in an array first. then you could loop the days and for each day you will echo the <div> and the day header, at the end you will echo the </div>.
inside the foreach you can loop again using the same array to check each item if it's has the same day or not. if yes then echo the name of the item, otherwise don't do anything.
I have tested this code, you can check it and let me know if you are having any problems with it.
foreach($array as $day){
$days[] = $day['day_id']; // store all the days in an array
}
// now days[] has [1,1,2,3]
$days = array_unique($days); // get unique days only no duplicated
//now days[] has [1,2,3]
foreach($days as $d){ // for each day
echo '<div class = "day-'.$d.'">';
echo '<h3>The Day is ' . $d . '</h3>' . "\n";
foreach($array as $a) { // check all other items if the item has the same day then echo
if($a['day_id'] == $d){
echo $a['Foo']['name'] . "\n";
}
}
echo '</div>';
}
Output:
<div class = "day-1">
<h3>The Day is 1</h3>
My day_id is 1
My day_id is 1
</div>
<div class = "day-2">
<h3>The Day is 2</h3>
My day_id is 2
</div>
<div class = "day-3">
<h3>The Day is 3</h3>
My day_is 3
</div>
Related
I'm working on a game release section, where I display games that are about to release. I only work with game information, and a release date.
My array looks like this (actual array has a lot more info so this is just a replicate):
$arr = [
[
'id' => 'UP0006-CUSA08724_00-BATTLEFIELDV0000',
'attributes' => [
'name' => 'Battlefield V [test1]',
'thumbnail-url-base' => 'https://store.playstation.com/store/api/chihiro/00_09_000/container/US/en/999/UP0006-CUSA08724_00-BATTLEFIELDV0000/1539651459000/image'
'release-date' => '2018-12-14T00:00:00Z'
],
],
[
'id' => 'UP0006-CUSA08724_00-BATTLEFIELDV0000',
'attributes' => [
'name' => 'Battlefield V [test2]',
'thumbnail-url-base' => 'https://store.playstation.com/store/api/chihiro/00_09_000/container/US/en/999/UP0006-CUSA08724_00-BATTLEFIELDV0000/1539651459000/image'
'release-date' => '2018-10-14T00:00:00Z'
],
],
[
'id' => 'UP0006-CUSA08724_00-BATTLEFIELDV0000',
'attributes' => [
'name' => 'Battlefield V [test3]',
'thumbnail-url-base' => 'https://store.playstation.com/store/api/chihiro/00_09_000/container/US/en/999/UP0006-CUSA08724_00-BATTLEFIELDV0000/1539651459000/image'
'release-date' => '2019-10-14T00:00:00Z'
],
],
];
I want to display the game titles that are closest to release to the current date such as [test1], and skip the ones that have been released already such as [test2].
I've tried to skip them using this line:
if (strtotime(date('Y-m-d H:i:s')) > strtotime($title['attributes']['release-date'])) continue;
But for some reason it does not seem to skip them, and just keeps them in.
Also I have no idea where to start when trying to show the game titles that are closest to release to the current date.
My full code:
foreach($json['included'] as $key => $title) {
$cusa = substr(explode('-', $title['id'], 3)[1], 0, -3);
if($title['type'] == 'game' && substr($cusa, 0, 4) == 'CUSA') {
// if the day of release has already passed, skip
if (strtotime(date('Y-m-d H:i:s')) > strtotime($title['attributes']['release-date'])) continue;
?>
<div class="game-banner" style="background:url(<?php echo $title['attributes']['thumbnail-url-base']; ?>)">
<h4 class="psplus-game-name"><?php echo $title['attributes']['name']; ?></h4>
</div>
<?php
if($key >= 4) break; // display only 3
}
}
}
You just need to calculate the seconds left to release date, and if it's a positive number echo it.
foreach($arr as $game){
$timeleft = strtotime($game['attributes']['release-date'])-time();
if($timeleft>0) echo floor($timeleft/86400) ." days left to ".$game['attributes']['name'] ." \n";
}
//58 days left to Battlefield V [test1]
//362 days left to Battlefield V [test3]
https://3v4l.org/OMetR
If your initial array is unsorted and you want then sorted you can add them to an array with key being the timeleft and sort on keys with ksort().
foreach($arr as $game){
$timeleft = strtotime($game['attributes']['release-date'])-time();
if($timeleft>0) $games[$timeleft] = floor($timeleft/86400) ." days left to ".$game['attributes']['name'] ." \n";
}
ksort($games);
echo implode("", $games);
https://3v4l.org/gbLCs
I am facing a problem problem here and need some help.
I have saved in my database a json_aray array with objects.
After decoding and print_r it I get this result.
Array (
[0] => stdClass Object (
[Title] => Image
[Info] => info
[ImageURL] => url.jpg )
[1] => stdClass Object (
[Title] => Image
[Info] => info
[ImageURL] => url.jpg )
[2] => stdClass Object (
[Title] => Accommodation
[Info] => info
[ImageURL] => image.jpg )
[3] => stdClass Object (
[Title] => Accommodation
[Info] => info
[ImageURL] => image.jpg )
[4] => stdClass Object (
[Title] => Accommodation
[Info] => info
[ImageURL] => image.jpg )
[5] => stdClass Object (
[Title] => Image
[Info] => info
[ImageURL] => image.jpg )
[6] => stdClass Object (
[Title] => Location
[Info] => info
[ImageURL] => image.jpg )
)
So here is the CASE:
I am trying to create a div for every different Object->Title e.g
I tried to check that with foreach loop but the result was creating 5 different divs instead of one.
Is there any built-in function in php to get all the $obj->Info if the $obj->Title == 'foo' or somehow check before the foreach loop what data the array has and separate them?
What i did in my code is below
while($row = sqlsrv_fetch_array($get_details)) {
$a = $row['additionalInformation'];
$b = json_decode($a);
$c = $b->AdditonalInfo;
foreach ($c as $d){
echo '<div class="class">';
if(($d->Title !== 'Image')){
echo '<h2>'.$d->Title.'</h2>';
echo '<p>'.$d->Info.'</p>';
}
echo "</div>";
}
}
UPDATE
Change my code with the actual one
This is what I get
But I need to create Accommodation or every same Title just once and all Info that has Title == 'Accommodation' under that div.
IF my question is clear enough please let me know so I can update it.
So to sum up i need to display all [Info] that has same [Title] in one div and create different div for each unique '[Title]'
Thanks In Advance
Requirements: Show 'nested groups' in a sequential stream of records.
Here we have a nested group indicated by a field called 'Title'.
The input records must be sorted so that all the records in each group are together and in the required order.
Now, the first thought is to use a 'foreach' loop. This is not the clearest approach because you cannot detect the end of the group by looking at the current record. Also, the foreach loop reads the next record at the end of the loop. So, you end up trying to work out where you are in the group to know what to do.
I use a technique called 'read ahead'. The idea is to read a record before the loop and the read the next record immediately after you have processed the current one. The 'trick' is that you process all the records in a group inside a loop.
So, the logic is an iteration of:
Process start of group - already has the first record of the group - important.
Process all the detail records belonging to the group - records are read inside this loop.
Process the end of the group - the current record is the first of the next group
repeat for each group.
It results in easier to understand code.
I have split all the separate actions into function so that you easily modify the individual actions.
Notice the code matches the structure of the data. There is always one place in the code to put the required action for that particular data item.
Full working Source Code at eval.in
Run the code
outputAllGroups($src);
exit();
Process All the Groups
function outputAllGroups(&$inputList)
{
reset($inputList);
$currentDetails = current($inputList); // read the first record
while ($currentDetails !== false) { // not end of records
// start the title group
$currentTitle = $currentDetails->Title;
outputGroupHeader($currentDetails);
// process all records in the group
while ( $currentDetails !== false
&& $currentDetails->Title === $currentTitle) {
outputDetails($currentDetails);
$currentDetails = readNextDetails($inputList); // may end group
}
// end the title group
outputGroupFooter($currentTitle);
}
}
Functions for the individual actions
function outputGroupHeader($details)
{
echo '<div class="TitleGroup">'. "<!-- Start Group: {$details->Title} -->". PHP_EOL
. '<div class="Title">'. $details->Title .'</div>' . PHP_EOL;
}
function outputGroupFooter($title)
{
echo '</div>'. "<!-- End Group: {$title} -->". PHP_EOL;
}
function outputDetails($details)
{
echo '<div class="details">'. PHP_EOL,
$details->Info . PHP_EOL,
$details->ImageURL .PHP_EOL,
'</div>' . PHP_EOL;
}
function readNextDetails(&$inputList)
{
$allOk = next($inputList); // advance next
return $allOk !== false ? current($inputList) : $allOk; // advance next
}
Output
<div class="TitleGroup"><!-- Start Group: Image -->
<div class="Title">Image</div>
<div class="details">
info1
url1.jpg
</div>
<div class="details">
info2
url2.jpg
</div>
</div><!-- End Group: Image -->
<div class="TitleGroup"><!-- Start Group: Accommodation -->
<div class="Title">Accommodation</div>
<div class="details">
info3
image3.jpg
</div>
<div class="details">
info4
image4.jpg
</div>
<div class="details">
info5
image5.jpg
</div>
</div><!-- End Group: Accommodation -->
<div class="TitleGroup"><!-- Start Group: Image -->
<div class="Title">Image</div>
<div class="details">
info6
image6.jpg
</div>
</div><!-- End Group: Image -->
<div class="TitleGroup"><!-- Start Group: Location -->
<div class="Title">Location</div>
<div class="details">
info7
image7.jpg
</div>
</div><!-- End Group: Location -->
Data
$src = Array (
'0' => (object) array(
'Title' => 'Image',
'Info' => 'info1',
'ImageURL' => 'url1.jpg', ),
'1' => (object) array(
'Title' => 'Image',
'Info' => 'info2',
'ImageURL' => 'url2.jpg', ),
'2' => (object) array(
'Title' => 'Accommodation',
'Info' => 'info3',
'ImageURL' => 'image3.jpg', ),
'3' => (object) array(
'Title' => 'Accommodation',
'Info' => 'info4',
'ImageURL' => 'image4.jpg', ),
'4' => (object) array(
'Title' => 'Accommodation',
'Info' => 'info5',
'ImageURL' => 'image5.jpg', ),
'5' => (object) array(
'Title' => 'Image',
'Info' => 'info6',
'ImageURL' => 'image6.jpg', ),
'6' => (object) array(
'Title' => 'Location',
'Info' => 'info7',
'ImageURL' => 'image7.jpg', ),
);
Hi please do so to get for each result unique div. For the 2 quetion (Is there any built-in function in php to get all the $obj->Info if the $obj->Title == 'foo' or somehow check before the foreach loop what data the array has and separate them?) I will find some solution late :)
$a = $row['additionalInformation'];
$b = json_decode($a);
$c = $b->AddInfo;
$createDivArray = array();
echo '<div class="style1">';
foreach ($c as $value){
if (in_array($value->Title, $createDivArray)) {
continue;
}
$createDivArray[] = $value->Title;
echo "<h4>$value->Title</h4>";
echo "<p>$value->Info</p>";
}
echo "</div>";
$policyYear =
Array
(
[1] => 1 Year
[2] => 2 Year
[3] => 3 Year
)
<div>
<?php
$options = $policyYear;
$attributes = array('legend' => false);
echo $this->Form->radio('policy_year', $options, $attributes);
?>
</div>
This is my code which is giving three radio button having values '1 Year', '2 Year' , '3 Year'. But I want to set selected initially for value '1 Year'. How can I do that ?. I am new in cakephp. I know it in core php. Please help.
Update your $attributes and add value
$attributes = array('legend' => false,'value' => $foo);
I want to make a nicely structured category with parent tree, but i can't seem to find the right way to get do this properly.
This is the premis:
1 product has many categories.
1 category may have a parent.
this is the array I currently have (the values in these arrays are just an example)
array:4[
1=> array:2 [
2 =>2
4 => 4
]
2=> array:1[
3=>3
]
3=> array:1[
5=>5
]
9=> array:1[
6=>6
]
]
now i want this
array:4[
1=> array:2 [
2 => array:1 [
3=> array:1 [
5=>5
]
]
4 => 4
]
9=> array:1[
6=>6
]
]
how do I convert the first to the second while keeping the array keys, I want to use the keys to call upon an another array with all the relevant objects and data
so i can get this as a result:
http://www.bootply.com/dFeKoQmgb2
What if you try the following code. Note that there must be a better approach without changing the source array inside recursion.
$array = array(
1 => array(
2 => 2,
4 => 4
),
2 => array(
3 => 3
),
3 => array(
5 => 5
),
9 => array(
6 => 6
)
);
//we need the copy to delete there nodes that have been re-atached. Otherwise, we end up changing the array itself within recursion, which is not good
$arrayCopy = $array;
function recursive(&$array, &$arrayCopy) {
foreach($array as $key => &$value) {
//if we found the leaf node
if(!is_array($value)) {
// and there is something in the array copy with this index
if(array_key_exists($key, $arrayCopy)) {
// re-attach it to the initial array. $value is passed by reference. BTW, not a good approach as I stated above, but it works on the sample data
$value = $arrayCopy[$key];
// remove that node from array copy in order to not double process it.
unset($arrayCopy[$key]);
// call it again for the leaf-node value
recursive($value, $arrayCopy);
}
// here is recursion exit, if we don't find anything in the arracy copy for the fiven leaf node
} else {
//recursive call it for the node
recursive($value, $arrayCopy);
}
}
}
// launch the recursion
recursive($array, $arrayCopy);
// now we need to remove the nodes that have been removed from the array copy, i.e. the ones being re-attached. We could not do this in the recursion
$result = array();
foreach(array_keys($arrayCopy) as $initial_key) {
$result[$initial_key] = $array[$initial_key];
}
var_dump($result);
for now I fixed it using this function, I'm sure there is a more elegant way, since it only works when the parent is also in the array, for this but it works
array (size=5)
0 =>
array (size=3)
'id' => int 2
'parent' => int 1
'name' => string 'voluptatem' (length=10)
1 =>
array (size=3)
'id' => int 3
'parent' => int 2
'name' => string 'qui' (length=3)
2 =>
array (size=3)
'id' => int 4
'parent' => int 1
'name' => string 'qui' (length=3)
3 =>
array (size=3)
'id' => int 5
'parent' => int 3
'name' => string 'voluptate' (length=9)
4 =>
array (size=3)
'id' => int 6
'parent' => int 9
'name' => string 'optio' (length=5)
private function generatePageTree($datas, $parent=0, $limit=0)
{
if ($limit > 100) return '';
$tree='<ul class="list-group">';
foreach ($datas as $data) {
if ($data['parent'] == $parent) {
$tree.='<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="false">
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="heading' . $data['id'] . '">
<h4 class="panel-title" style="height:50px;">
<a class="collapsed" role="button" data-toggle="collapse" data-parent="accordion" href="#collapse' . $data['id'] . '" aria-expanded="false" aria-controls="collapse' . $data['id'] . '">
' . $data['name'] . '
</a>
<i class="fa fa-search"></i>Toon
</h4>
</div>
<div id="collapse' . $data['id'] . '" class="panel-collapse collapse out" role="tabpanel" aria-labelledby="heading' . $data['id'] . '">
<div class="panel-body">';
$tree.=$this->generatePageTree($datas, $data['id'], $limit ++);
$tree.='</div>
</div>
</div>
</div>
';
}
}
$tree.='</ul>';
return $tree;
}
This is what my array looks like.
(int) Year 1 => array(
'Department 1' => array(
'Sales' => '12345'
),
'Department 2' => array(
'Sales' => '12345'
),
),
(int) Year 2 => array(
'Department 1' => array(
'Sales' => '12345'
),
'Department 2' => array(
'Sales' => '12345'
),
)
I want to be able to create a table where the headers are the Years on the X axis.
The Y axis needs to start with the Department name. The adjoining cells need to have sales, revenue, and total in one cell.
It should look like this...
Department____| ___YEAR1_______ | __Year2
Department 1 |Sales [dept 1][year 1] | Sales[dept 1][year 2]
Department 2 |Sales [dept 2][year 1] | Sales [dept 2][year 2]
I used nested foreach loops
foreach($List as $key=>$row) {
echo "<tr><td>".$key."</td>";
foreach($row as $key2=>$col){
echo "<td>" . 'Sales: '.round($col['sales'],2) ."</td>";
}
echo "</tr>";
}
echo "</table>"; ?>
but it printed the table with departments names on top on the x axis and years on the y axis. How do I get years on the x axis and departments on the y axis.
The problem is that the dimensions of your array don't correspond with the order that you want to iterate through them for your table. You need to pull out the keys explicitly to iterate through them in the nested loops.
$years = array_keys($List);
// Print column headings
echo "<table><thead><tr><th>Department</th>";
foreach ($years as $year) {
echo "<th>$year</th>";
}
echo "</tr></thead>";
// Print data rows
echo "<tbody>"
foreach (array_keys($List[$years[0]]) as $dept) {
echo "<tr><th>$dept</th>";
foreach ($years as $year) {
echo "<td>{$List[$year][$dept]['Sales'}]</td>";
}
echo "</tr>";
}
echo "</tbody></table>";
As I mentioned, this depends on all years having the same departments. If you add new departments over time, it won't work. You can fix this by using array_reduce to merge all the department lists, I'll leave that as an exercise for the reader.