Show closest release date titles using foreach-array in PHP - php

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

Related

How to take out the index of an array in a select tag?

I'm trying to add a year feature in my code.
Here, I push the years in an array, which can be selected after, using a select
$years = 2020;
$years_array = array();
// up-to-date years in array, starting from year 2020
while ($years <= date('Y'))
{
$to_push = array(strval($years)=>$years);
array_push($years_array, $to_push);
$years++;
}
$choices = array_values($years_array);
Then, I add them to the builder (I also show you the months, this has been developed by someone before me)
->add('mois', ChoiceType::class, [
'choices' => [
'Janvier' => 1,
'Février' => 2,
'Mars' => 3,
'Avril' => 4,
'Mai' => 5,
'Juin' => 6,
'Juillet' => 7,
'Aout' => 8,
'Septembre' => 9,
'Octobre' => 10,
'Novembre' => 11,
'Décembre' => 12
],
'data' => date('n')
])
->add('annee', ChoiceType::class, [
'choices' => $choices,
'data' => date('Y')
It works fine, I get the year afterwards, and the text shows up in the Select tag.
But I see the indexes of the array, as shown in this picture, which looks terrible.
How could I take these off?
You're nesting the associative arrays into an indexed array. You should just assign directly to indexes of $years_array.
for ($year = $years; $year < date('Y'); $year++) {
$years_array[$year] = $year;
}
You don't need to use array_values() afterward.

Grouping data to get reports by intervals

I posted a question some time ago on representing data per date horizontally on a datatable.
See here: datatables dates at the top and data cells going from left to right
With the help of that thread I was able to get the data to display how I wanted it. With the dates showing at the top, the service provided on the left and all data associated with any date between the 2 date paramters inside the main body. (If there is no data in a particular date then the < td > will display 0. See here:
http://www.phpwin.org/s/ewbAS6
After manipulating this code further I made the dates of the search dynamic by proving a form with a start date and an end date, and a dropdown with the options of:
Daily
Weekly
Monthly
Quaterly
Yearly
this allows the interval of dates at the top to become dynamic. Of course all this is doing is changing the value of the 2nd parameter inside the date while loop.
WHILE (strtotime($date) <= strtotime($end_date)) {
echo '<th>' . $date . '</th>';
$date = date('Y-m-d', strtotime($date . ' +1day'));
}
with the parameter set at Weekly, the value of +1day becomes +1week, at Monthly; the value becomes +1month and so on.
MY ISSUE:
When the interval is set to daily, the dates with their corresponding attendance counts are displayed correctly but once you try to increase the interval to +1week and above the data does not round up to the week shown. Check this:
[LINK1]Per day: http://www.phpwin.org/s/ewbAS6
[LINK2]Per month: http://www.phpwin.org/s/xRo3I6
Looking at the array (modified on the LINK2)
$result[] = array('Service Name' => 'Health', 'date' => '2017-04-04', 'Attendance' => 5);
$result[] = array('Service Name' => 'Payroll', 'date' => '2017-04-16', 'Attendance' => 5);
$result[] = array('Service Name' => 'Saturday Youth Meeting', 'date' => '2017-04-03', 'Attendance' => 1);
$result[] = array('Service Name' => 'Saturday Youth Meeting', 'date' => '2017-05-03', 'Attendance' => 3);
$result[] = array('Service Name' => 'Payroll', 'date' => '2017-05-03', 'Attendance' => 2);
$result[] = array('Service Name' => 'Payroll', 'date' => '2017-04-11', 'Attendance' => 3);
$result[] = array('Service Name' => 'Payroll', 'date' => '2018-04-03', 'Attendance' => 10);
You can see in the array that there are multiple attendance entries in April, totaling 14 Attendances in that month however during LINK2 where the interval is increased to a month instead of showing 14 for April (which would be the sum of all the dates in that particular month) it shows the value 1.
My live version takes the array from a database so I used the YEAR(), MONTH(), WEEK() and DAY() function on the date and used group by. The query executes how I want it but having issues working on the PHP end.

Calculate a year from a set of dates

I am given an array containing periods for a year as following.
$year = '2016';
$periods = [
[
'name' => "Name One",
'startDate' => '01/01/2016',
'endDate' => '03/31/2016'
],
[
'name' => "Name Two",
'startDate' => '04/01/2016',
'endDate' => '12/31/2016'
]
];
The number of periods may vary, hence, the array periods may have any number of elements (say 5 elements, meaning 5 periods for the given year). Now I need to make sure that the periods do really make up a year, that is, two periods cannot overlap and the periods collectively do sum up to be the specified year.
I've tried many different ways, but failed to come up with any efficient solution at all.
I am using Laravel 5, hence Carbon package. But I'll be glad to get this done even in Basic PHP. So all suggestions are welcome
Give this a try - there may be a more elegant solution but I think this works. I've used Carbon, as it's a got some very useful helper methods.
I've assumed your $periods array will be in date order. If it's not, you could just usort it.
$year = '2016';
$periods = [
[
'name' => "Name One",
'startDate' => '01/01/2016',
'endDate' => '03/31/2016'
],
[
'name' => "Name Two",
'startDate' => '04/01/2016',
'endDate' => '12/31/2016'
]
];
// set a start position
$currentPosition = Carbon::create($year, 1, 1)->startOfDay();
// and the end of the year
$endOfYear = Carbon::create($year, 1, 1)->addYear()->startOfDay();
// iterate periods
foreach ($periods as $period) {
$start = Carbon::createFromFormat('m/d/Y', $period['startDate'])->startOfDay();
$end = Carbon::createFromFormat('m/d/Y', $period['endDate'])->endOfDay();
// start of this period should follow the last (??)
if ($start < $currentPosition) {
throw new Exception("$start is earlier than $currentPosition");
}
// must follow on from the current position
if ($currentPosition->diffInDays($start) > 0) {
throw new Exception("$start doesn't follow $currentPosition");
}
// check it doesn't go over the end of the year
if ($currentPosition->addDays($start->diffInDays($end)) > $endOfYear) {
throw new Exception("$end takes us over the end of the year!");
}
$currentPosition = clone $end;
}
// did we reach the end?
if ($currentPosition->addDay()->startOfDay() != $endOfYear) {
throw new Exception("Full year not accounted for");
}
// we're done
echo 'Full year accounted for'.PHP_EOL;

3 Dimensional Associative Array to HTML table

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.

html output logic from array

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>

Categories