loop array values - php

Here I access 'date' key values from rows of DB table. And I can echo these values, no problem.
$res = $mysqli->query("SELECT * FROM alfred ORDER BY id ASC");
$row = $res->fetch_all(MYSQLI_ASSOC);
foreach ($row as $key => $value){
$availDate = $value['date'];
echo $availDate.'<br />';
}
This loop above shows all 'date' values from DB, in this case there are 3 dates- "2012-09-25" "2012-09-27" and "2012-09-29".
But then I need to compare each of these 'date' values against values of $date->format('Y-m-d') from the code below and display each date with corresponding "busy" or "available" status into separate <td> of the table. My following version compares only the "last" value of 'date' key - "2012-09-29", but I need to compare each 'date' value from the array above, it means also "2012-09-25" and "2012-09-27". I have tried many versions but still unsuccessful. Any ideas?
$date = new DateTime();
$endDate = new DateTime('+10 day');
for($date->format('Y-m-d'); $date->format('Y-m-d') < $endDate->format('Y-m-d'); $date->modify('+1 day')){
if ($date->format('Y-m-d') == $availDate){
echo '<td>'.$date->format('Y-m-d/D').' busy</td>';
} else {
echo '<td>'.$date->format('Y-m-d/D').' available</td>';
}
}
Here is the result I am getting now:
2012-09-21/Fri available 2012-09-22/Sat available 2012-09-23/Sun available 2012-09-24/Mon available 2012-09-25/Tue available 2012-09-26/Wed available 2012-09-27/Thu available 2012-09-28/Fri available 2012-09-29/Sat busy 2012-09-30/Sun available
But in fact I need to show "busy" status also into <td> of "2012-09-25" and <td> of "2012-09-27" as these also are 'date' values that are existing in $row array. Unfortunately I can not post any images here to show, but I hope my result above gives you the idea.
SOLVED with the help of in_array below:
$aAvailDate = array();
foreach ($row as $key => $value){
$aAvailDate[] = $value['date'];
}
$date = new DateTime();
$endDate = new DateTime('+10 day');
for($date->format('Y-m-d'); $date->format('Y-m-d') < $endDate->format('Y-m-d'); $date->modify('+1 day')){
if (in_array($date->format('Y-m-d'), $aAvailDate)){
echo '<td>'.$date->format('Y-m-d/D').' busy</td>';
} else {
echo '<td>'.$date->format('Y-m-d/D').' available</td>';
}
}

I haven't tested your code, but I think you are running ->format('Y-m-d') unnecessarily here, and this is messing up your logic.
Every time you run that, PHP is turning your object into a string, which you are then comparing against other strings. This won't do anything useful.
Instead, you should be using the features of the DateTime class to compare the objects themselves. The only time you should need to use the format() method is when outputting to the browser, into an SQL query, etc

Although your Question is Unclear but AFAIK
you want to display "Busy" if available date occurs between given date upto 3 Weeks
otherwise display "free"
I would like to suggest you to do this with MySQL (Not tested)
SELECT *,
IF( `DateCol` BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 3 WEEK), 'Busy','Free')
AS status
FROM TableName

Try a while loop instead of a foreach. Also, compare the DateTime objects directly, not the formatted strings.
$date = new DateTime();
$endDate = new DateTime('+3 week');
while( $date < $endDate) {
if ($date->format('Y-m-d') == $availDate){
echo '<td class="busy">busy</td>';
} else {
echo '<td>free</td>';
}
$date->modify("+1 day");
}

Something like this? (If I understand what you're trying to do correctly)
<?php
$avail_dates = array();
$res = $mysqli->query("SELECT DATE_FORMAT(date, '%Y-%m-%d') AS availDate FROM alfred ORDER BY id ASC");
$row = $res->fetch_all(MYSQLI_ASSOC);
foreach ($row as $key => $value){
$avail_dates[] = $value['availDate'];
}
$startDate = date('Y-m-d');
$endDate = date('Y-m-d', strtotime(date("Y-m-d", strtotime($startDate)) . " +3 week"));
?>
<table>
<?php
foreach ($avail_dates as $availDate){
echo "<tr><td>$availDate</td>";
if (($startDate <= $availDate) && ($endDate >= $availDate)){
echo "<td class='busy'>busy</td>";
}else{
echo "<td>free</td>";
}
echo "</tr>";
}
?>
Instead of printing values, I would add them to the array, and then run a loop on that array, comparing the values to the given start and end dates. I also wouldn't fetch all from the table if you nly need a date.

May be like this?
$date = new DateTime();
$endDate = new DateTime('+3 week');
for($date->format('Y-m-d'); $date->format('Y-m-d') < $endDate->format('Y-m-d'); $date->modify('+1 day')){
$tempDate = $date->format('Y-m-d');
if ($tempDate === $availDate){
echo '<td class="busy">busy</td>';
} else {
echo '<td>free</td>';
}
}

Related

How to loop 2 dates to output like this?

Here's my code that display date with for loop.
Topic: Im creating a script to generate payment due(from to start).
$y = 1;
$period = 3;
$start = date('m/15/Y');
echo "<table>";
echo '<thead><th>From</th>';
echo '<th>To</th></thead>';
for ($y; $y <= $period; $y++) {
$month_mid = date("m/15/Y", strtotime($start));
$month_last = date("m/t/Y", strtotime($start));
echo '<td>'.$month_mid = date("m/t/Y", strtotime($start)).'</td>';
echo '<td>'.$month_last = date("m/15/Y", strtotime($start)).'</td></tr>';
$start = date("m/d/Y",strtotime($start." +1month"));
}
echo '</table>';
output I get:
09/15/2017 09/30/2017
10/15/2017 10/31/2017
11/15/2017 11/31/2017
I want to appear like this:
09/15/2017 09/30/2017
09/30/2017 10/15/2017
10/15/2017 10/31/2017
Im new in date php hope you can help me with this thanks.
Here you go:
$y = 1;
$period = 5;
$start = date('m/15/Y');
echo "<table>";
echo '<thead><th>From</th>';
echo '<th>To</th></thead>';
for ($y; $y <= $period; $y++) {
$month_mid = date("m/15/Y", strtotime($start));
$month_last = date("m/t/Y", strtotime($start));
echo '<tr><td>'.$month_mid = date("m/t/Y", strtotime($start)).'</td>';
echo '<td>'.$month_last = date("m/15/Y", strtotime($start)).'</td></tr>';
$start = date("m/d/Y",strtotime($start." +1month"));
}
echo "</table>";
You missed the opening and clousure of table and <tr>.
You don't want to be skipping ahead by a month in your loop. Well, not the way you are doing it here.
You should use DatePeriod::getEndDate and DatePeriod::getStartDate, along with DateTime::add to skip by semi-monthly amounts. The idea is that you only get to the next month by letting the datetime API add 15 days to a given start date, and use that to figure out the mid-month and end-month dates.
Keep everything in these date objects until you need to format and print them, and save the second one in the pair as input for the next round of the loop at the end where you just have to calculate the new second value.
I feel like you could write a function that gets the "next" date from any other first or last date of the month to simplify the loop.
(Since this is semi-monthly and not bi-weekly, you can actually just walk the months in your period, hard-coding the 15th for one value and using your end-of-month function for the second. It depends on your requirements and how complicated the API gets.)
Or
For each month in your period, calculated the mid-month (i.e., exactly 15 days from the start of the month) and end-month dates. Save them in a Collection of couplets of some sort.
Write a display routine that takes this Collection and outputs the dates, but saves the previous formatted string made from the second item in the couplet as the first item to be printed (after the first line.)
I actually prefer this one because it separates the presentation from the data abstraction, allowing you freedom to display and format the date how you see fit.
But, at the end of the day (pun not intended, but what a great pun), stop using date strings as input to figure out other dates when you have access to normalized epoch representations. This will only lead to madness.
$y = 1;
$period = 3;
$start = date('m/d/Y');
$end = date('m/t/Y');
echo "<table>";
echo '<thead><th>From</th>';
echo '<th>To</th></thead>';
for ($y; $y <= $period; $y++) {
echo '<tr><td>'.$start.'</td>';
echo '<td>'.$end.'</td></tr>';
$getLast = date('d',strtotime($end));
if($getLast >= 28) {
$start = date("m/t/Y", strtotime($start));
$end = date("m/d/Y", strtotime("+15 day", strtotime($end)));
}else {
$start = date("m/d/Y", strtotime("+15 day", strtotime($start)));
$end = date("m/t/Y",strtotime($end));
}
}
echo "</table>";
Result:
From To
09/15/2017 09/30/2017
09/30/2017 10/15/2017
10/15/2017 10/31/2017

Create a cumulative comparison table in PHP and MySql

I have a database table called payments which contains date,amount fields. I want to take values from amount field and SUM up all amounts by date and take the results to html table then output them like on the image.
I have created dates dynamically so that they will be equal nomatter which months example January its 1-31 and February its 1-31. Where there is a weekend or the date is invalid i want the value to be zero. What i want is like this table [table][1] [1]: http://i.stack.imgur.com/iMOl3.jpg
This is what i am getting [output][1][1]: http://i.stack.imgur.com/MJpyT.jpg
******NOTE***** I THINK MY SOLUTION IS NOT THE BEST SOLUTION TO MY PROBLEM. IF POSSIBLE JUST TAKE I VIEW ON THE PICTURE WHICH I WANT AND FIND ME THE BEST SOLUTION. I WANT TO BE HELPED IN EITHER STEPS TO ACHIEVE IT OR A SOLUTION
I know that i am using a depricated mysql synthax please ignore that and help on my problem.
<table border="1" align="center">
<?php
session_start();
include("connection/db_con.php");
$sym='-';
$d=array();
///Insert values of month for period selected into an array
$a = $_POST['dat'];
$b = $_POST['dat2'];
$mnth=array();
$m_nam=array();
$m_nm=array();
$m_nam[]="Day";
//////New way of getting months in format Y-m
$start = new DateTime($a);
$start->modify('first day of this month');
$end = new DateTime($b);
$end->modify('first day of next month');
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
$mnth[]=$dt->format("Y-m");
$m_nam[]=date('F-Y', strtotime($dt->format("Y-m")));
$m_nm[]=date('M', strtotime($dt->format("Y-m")));
}
///////End of New way
echo "<tr bgcolor='#999999'>";
foreach ($m_nam as $m)
{
echo"<td>".$m."</td>";
}
echo"</tr>";
/////////End insert////////////////////////
$day=0;
for($x=1; $x<=31; $x++)
{
$day=$day+1;
echo"<tr>";
echo"<td>".$day."</td>";
$d=$sym.$x;
foreach($mnth as $mon)
{
$dat=$mon.$d;
$qry=mysql_query("SELECT SUM(amount) AS total_disb FROM payments where dat='$dat'")or die(mysql_error());
$row=mysql_fetch_assoc($qry);
$sum = $row['total_disb']+0;
echo"<td>".$sum."</td>";
}
echo"</tr>";
}
?>
</table>
Here's a rewrite of the code you provided, it's using dummy random data instead of DB and there is no logic for POST variables, but that you can replace with your code.
<?php
// session start, db connection goes here
echo '<table border="1" align="center">';
// Example of post vars
$start = new DateTime('2015-11-10');
$end = new DateTime('2016-02-28');
// Note: not sure why OP used modify here
$interval = new DateInterval('P1M');
$daterange = new DatePeriod($start, $interval, $end);
// Table Header row 1
echo '<tr><th>Day</th>';
foreach ($daterange as $date) {
echo '<th colspan="2">'.$date->format("F Y").'</th>';
}
echo '</tr>';
// Temporary month store
$months = array();
// Table Header row 2
echo '<tr style="background-color:#22bb22;"><th></th>';
foreach ($daterange as $date) {
$months[] = $date->format("F");
echo '<th>Daily</th>';
echo '<th>Cumulative</th>';
}
echo '</tr>';
// Table Body
$sumc = array();
for ($d = 1; $d <= 31; $d++) {
echo '<tr><td>'.$d.'</td>';
foreach ($months as $month) {
$db_date = $month.'-'.$d; // used for db query
// dummmy data (replace with db query result)
$sum = mt_rand(0, 999);
echo '<td>'.$sum.'</td>';
if(!array_key_exists($month, $sumc)) {
$sumc[$month] = 0;
}
$sumc[$month] = (int)$sum + $sumc[$month];
echo '<td>'.$sumc[$month].'</td>';
}
echo '</tr>';
}
echo '</table>';
?>
Also the condition:
Where there is a weekend or the date is invalid i want the value to be
zero.
is it correct to assume that these are taken care because the DB query would return 0? Or do you have to check in the code for weekends even if the DB query returns an amount from total_disb that is >0?
You have just messed up a little with dates, if I'm understanding where your problem is you can do it directly from SQL, try something like:
SELECT SUM(amount) AS total_disb , MONTH(DateTime) , DAY(DateTime)
FROM payments
GROUP BY DATE(DateTime), DAY(DateTime)
Change DateTime for your variable or column names.
If you also want to SUM the months totals at the end of the table I'd recommend you to make a new query like:
SELECT SUM(amount) AS total_disb , MONTH(DateTime)
FROM payments
GROUP BY DATE(DateTime), MONTH(DateTime)
Another option would be to increment a variable while you loop to print the values, but in my opinion a new query is more simple.
If this is not what you need leave a comment and I will edit it.
To get to the cumulative you have to store the previous sum result and add it to the current iteration in the loop, something like:
$sumc = array();
foreach($mnth as $mon) {
$dat = $mon . $d;
$qry = mysql_query("SELECT SUM(amount) AS total_disb FROM payments where dat='$dat'") or die(mysql_error());
$row = mysql_fetch_assoc($qry);
$sum = $row['total_disb'];
if(isset($sumc[$mon])) {
$sumc[$mon] = (int)$sum + $sumc[$mon];
} else {
$sumc[$mon] = (int)$sum;
}
echo "<td>" . $sum . "</td>";
echo "<td>" . $sumc[$mon] . "</td>";
}
should probably work.
(Note: that you are missing a second row for 'daily' and 'cumulative' and once you have that row you need to use colspan to span the columns of the Months across). See an example of colspan here.

Increment date when it should be a new month

I have a PHP script which records things based on the day. So it will have a weekly set of inputs you would enter.
I get the data correctly, but when i do $day ++; it will increment the day, going passed the end of the month without ticking the month.
example:
//12/29
//12/30
//12/31
//12/32
//12/33
Where it should look like
//12/29
//12/30
//12/31
//01/01
//01/02
My script is as follows:
$week = date ("Y-m-d", strtotime("last sunday"));
$day = $week;
$run = array(7); //this is actually defined in the data posted to the script, which is pretty much just getting the value of the array index for the query string.
foreach( $run as $key=>$value)
{
$num = $key + 1;
$items[] = "($num, $user, $value, 'run', '$day')";
echo "".$day;
$day ++;
}
Should I be manipulating the datetime differently for day incrementations?
You can use
$day = date("Y-m-d", strtotime($day . " +1 day"));
instead of
$day++;
See live demo in ideone
You refer to $day as a "datetime" but it is just a string - that is what date() returns. So when you do $day++ you are adding 1 to "2015-12-02". PHP will do everything it can to make "2015-12-02" into a number and then add 1 to it, which is not date math. Here is a simple example:
<?php
$name = "Fallenreaper1";
$name++;
echo $name
?>
This will output:
Fallenreaper2
This is how I would do it, using an appropriate data type (DateTime):
<?php
$day = new DateTime('last sunday');
$run = array(7);
foreach ($run as $key => $value) {
$num = $key + 1;
$dayStr = $day->format('Y-m-d');
$items[] = "($num, $user, $value, 'run', '$dayStr')";
echo $dayStr;
$day->modify('+1 day');
}
To increase time you should use strtotime("+1 day");
here is simple example of using it
<?php
$now_time = time();
for($i=1;$i<8;$i++) {
$now_time = strtotime("+1 day", $now_time);
echo date("Y-m-d", $now_time) . "<br>";
}
?>

Comparing Date from PHP to MYSQL, strtotime not working

I have a DATE field on my MySQL table. Let's say the value is 2015-05-05.
I would like to check if the current time is before or after that.
This is my code:
foreach ($row as $row)
{
$ExpDate = strtotime($row['exp_date']);
$Today = strtotime(date("Y-m-d"));
echo $Today . ' - ' . $ExpDate;
if ($Today > $ExpDate)
{
exit('<M>LicenseExpired<M>');
}
}
The problem is that it's not working. The value of exp without strtotime is 2015-05-05. It I add the strtotime, the value becomes an empty string.
How am I able to solve this problem or what would be a good way to compare dates in PHP?
When comparing dates in MySQL there is no reason to take the extra step and use string_to_time(). The below example should work just fine. The format of MySQL DATE is designed in such a way that comparisons of this nature work naturally without any extra steps needed.
foreach ($row as $row)
{
$ExpDate = $row['exp_date'];
$Today = date("Y-m-d");
echo $Today . ' - ' . $ExpDate;
if ($Today > $ExpDate)
{
exit('<M>LicenseExpired<M>');
}
}
try this
foreach ($row as $row)
{
$ExpDate = new DateTime($row['exp_date']);
$Today = new DateTime(date("Y-m-d"));
$interval = $ExpDate->diff($Today);
//echo $interval->format('%R%a days'); <--- to diffenernce by days.
if ($interval > 0)
{
exit('<M>LicenseExpired<M>');
}
}

Getting the next date of a day in MySQL database (PHP)

I have a series of weekly events in a database along with the day they happen on (in full form, so: 'Monday', 'Tuesday' etc). I've successfully printed the events in a while loop ordered by today, tomorrow, etc, but I'd like to put the date in brackets next to each one.
I thought it might be a case of (mock code):
$today = date("l");
$todays_date = date("j M");
if (day == $today) {
$date = $todays_date;
}
else if (day == $today + 1) {
$date = $todays_date + 1;
}
else if (day == $today + 2) {
$date = $todays_date + 2;
}
etc...
But I'm not so sure. It'd be ideal if I could just have the date in the database, but this seems to go against the grain of what MySQL is about.
Also, I'd like to ideally format the date as: 11 Jun.
EDIT
Presumably it's also got to fit into my while loop somehow:
if($result && mysql_num_rows($result) > 0) {
while ($row = mysql_fetch_array($result)) {
$items[] = array($row[0]);
echo "<option>" . $row[0] . "</option>";
}
}
You can use strtotime?
echo "Today: ".date("j M");
echo "Tomorrow: ".date("j M", strotime("+1 day"));
You can use strtotime:
echo strtotime("+1 day");

Categories