I'm accessing a database created by another web company to retrieve event information for my current client. My client enters info for events and notes whether the date is recurring or not. I'm trying to display all the recurring dates. So far I have been able to get everything to display, regular dates as well as recurring.
The tables are laid out as follows:
Events
Events_Recurring
Here is part of the Events table BIGGER PICTURE
This is what the Events_Recurring table looks like
When the client checks it as recurring, the events_recurring table creates a row with the Event ID and other information like what day of the week or month the event is recurring on.
I'm just not sure how to display multiples of that certain ID that is recurring. I have a start date, and end date I can access, as well as what day of the week it is recurring on.
So for example: If this event reoccured every thursday. and I knew it started on Jan 1st and ended Jan 31st, can I run through that and spit out 4 different events all with the date of every Thursday in January?
Here is the full code I am working with, it's a little messy while trying to figure this out. I'm checking for the recurrence towards the bottom
// Access external database
$events_db = new wpdb(TOP SECRET CREDENTIALS HERE);
$events_db->show_errors();
if ($events_db) :
// Query Events Database
$events = $events_db->get_results(
"
SELECT ID, RequestDateStart, RequestDateEnd, Ministry, RequestTimeStart, EventName, CoordinatorName, EventDescription, Location
FROM gc_events
WHERE PrivateEvent = 0
AND Ministry = 15
AND date(RequestDateStart)>=date(NOW())
ORDER BY RequestDateStart
"
);
// Create the event data that will be displayed
foreach ($events as $event) :
// Store Event ID in a variable
$masterID = $event->ID;
echo '<div class="col-12">';
echo '<strong>ID:</strong> ' . $event->ID . '<br /><strong>Event Name:</strong> ' . $event->EventName . '<br /><strong>Leader:</strong> ' . $event->CoordinatorName . '<br /><strong>Date:</strong> ' . date('l, F j',strtotime($event->RequestDateStart)) . '<br /><strong>Start Time:</strong> ' . date('g:i a',strtotime($event->RequestTimeStart));
// CHECK IF RECURRING
$recurring_events = $events_db->get_results(
"
SELECT gc_event_id, period, day
FROM gc_event_recurring
WHERE gc_event_id = '$masterID'
"
);
foreach ($recurring_events as $recurring_event) :
if ($recurring_event->period === 'week') {
echo '<div class="col-12"><strong>↑ WEEKLY</strong><br />';
echo $recurring_event->day;
echo '</div>';
}
endforeach;
echo '</div>';
endforeach;
endif;
The result I am getting right now (with recurring events) is
Event: Weekly Prayer
Date: Feb 1, 2013
The result I would like is
Event: Weekly Prayer
Date: Feb 1, 2013
Event: Weekly Prayer
Date: Feb 8, 2013
Event: Weekly Prayer
Date: Feb 15, 2013
Event: Weekly Prayer
Date: Feb 22, 2013
This would be if the start date was Feb 1st and end date was Feb 28th.
A word of advice.
Although designing a database to store the 'description' of the repetition pattern is a very clean approach from a design point-of-view, you may get a lot of problems down the way.
I've done a project with a similar approach a while ago (I will look up the database design and add that to my answer) and, although I was able to reproduce the exact date/times of the recurring events, you will run into problems in the following situations; most originate from this:
the recurring events describe the repetition pattern, so the actual (individual) events are no physical records in your database
If the customer decides to add a new event, how will you check if it overlaps with any existing event? You'll have to calculate all 'events', based on the repetition pattern.
If the customer decides that the scheduled time for an event needs to be changed, how will you have this change apply to all future events and not for events that are in the past (you'll have to duplicate the original event, modify its end-date, and set the duplicated event with a new start-date)
If the customer decides he wants to remove a single day from the repetition pattern (e.g. a single event has ben canceled), you will also have to split the original event into two separate repetitions, or have a 'canceled/blocked' dates/times table
If people need to 'book' for specific events, you won't be able to attach them to a 'real' event-record, because the individual events because they are not physically present in the database. e.g. to check if a single event can be re-scheduled or canceled, you'll need to do this from code as the database cannot make use of foreign-key constraints to automatically update related reservations
Regarding performance; because individual events are not physically stored, they will have to be calculated every time you want to show them. Consider having 1000 recurring events in the database and try to show a 'calendar' of week 23 two years from now. You'll have to analyze all recurring-events patterns and calculate all events that they produce!
All depends of course on the actual usage of your system, but I wanted to warn you for problems we've run into.
Here's the schema for the 'schedules' table (contains recurring events pattern);
CREATE TABLE IF NOT EXISTS `schedules` (
`id` int(11) NOT NULL auto_increment,
`date_start` date NOT NULL,
`time_start` time NOT NULL,
`time_end` time NOT NULL,
`recur_until` date default NULL COMMENT 'end date when recurrence stops',
`recur_freq` varchar(30) default NULL COMMENT 'null, "secondly", "minutely", "hourly", "daily", "weekly", "monthly", "yearly"',
`recur_interval` smallint(5) unsigned default NULL COMMENT 'e.g. 1 for each day/week, 2 for every other day/week',
`recur_byday` smallint(5) unsigned default NULL COMMENT 'BITWISE; monday = 1, sunday = 64',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
How to circumvent the problems described
Fully describing a solution to these problems won't probably be suitable here, but here's some things to consider;
Storing a recurring event as described on itself is not bad practice. It perfectly describes when, and how often, an event should take place. However, the lack of physical records for the actual events is what causes the problem.
When creating or modifying a recurring event, calculate all resulting events and store them as physical records. These records can be queried, 'reservations' can be attached to them and you'll be able to make use of database features, like foreign-key-constraints to handle them properly.
When storing the individual events as described in 1., make sure you're keeping a reference to the 'schedule' that they belong to. If (for example) the customer wants to change the time of a recurring event, you'll be able to update all related (individual) events.
Keep in mind that in situation 2, you'll probably only want to update future events, so the 'recurring event' will still need to be 'split' in two to achieve that. In which case 'future' events need to be attached to the new 'recurring event', old events stay attached to the existing 'recurring event'
invest time in your database/software design, properly investigate if the design will 'work' for the thing you're trying to achieve. Test it, try things and if they don't work, don't hesitate to 'throw it away', often it's easier to start from scratch than try to 'fix' things. A proper design will take time and may take several 'redesigns' to get it right, but it will save you time and money in the end.
Hope this helps, good luck!
foreach ($events as $event) :
// Store Event ID in a variable
$masterID = $event->ID;
echo '<div class="col-12">';
echo '<strong>ID:</strong> ' . $event->ID . '<br /><strong>Event Name:</strong> ' . $event->EventName . '<br /><strong>Leader:</strong> ' . $event->CoordinatorName . '<br /><strong>Date:</strong> ' . date('l, F j',strtotime($event->RequestDateStart)) . '<br /><strong>Start Time:</strong> ' . date('g:i a',strtotime($event->RequestTimeStart));
// CHECK IF RECURRING
$recurring_events = $events_db->get_results(
"
SELECT gc_event_id, period, day
FROM gc_event_recurring
WHERE gc_event_id = '$masterID'
"
);
foreach ($recurring_events as $recurring_event) :
if ($recurring_event->period == 'week') {
$StartDate = strtotime($event->RequestDateStart);
$EndDate = strtotime($event->RequestDateEnd);
$TotalDays = round(($EndDate-$StartDate)/(60*60*24*7));
for($i = 0 ;$i<($TotalDays-1);$i++)
{
$StartDate += (60*60*24*7);
echo '<div class="col-12">';
echo '<strong>ID:</strong> ' . $event->ID . '<br /><strong>Event Name:</strong> ' . $event->EventName . '<br /><strong>Leader:</strong> ' . $event->CoordinatorName . '<br /><strong>Date:</strong> ' . date('l, F j',$StartDate) . '<br /><strong>Start Time:</strong> ' . date('g:i a',strtotime($event->RequestTimeStart));
}
}
endforeach;
echo '</div>';
endforeach;
try this and tell me if it works
Related
I want to show user that he has vaccinated his goat after successfully payment confirmation.
Here is what I tried:
<?php
$treatperiod1=$product_row['treat1'];
$currentDate = date("Y-m-d");
$totalDays = $treatperiod1;
$usedDays = round(abs(strtotime($currentDate)-strtotime($orderdate))/60/60/24);
$remainingDays = $totalDays-$usedDays;
if($remainingDays==0) {
echo "<a target = '_blank' href ='product_addon.php?treatp=$treatperiod1' class='btn btn-success'><i class='fa fa-pencil'></i>Vaccinate Gaoat</a>";
} elseif($remainingDays==$treatperiod1) {
echo 'Vaccinated';
} else {
echo $remainingDays.' Days Left';
}
?>
I have displayed remaining days for vaccination intervals I want to also display 'Vaccinated' if user payment for vaccination is confirmed. $product_row['treat1']; is a column where the number of days for vaccination is specified. order_details is a table for orders with column confirm for confirmed orders.
Goat Vaccination:
Because Goats don't get Autism
Please read how to use PHP DateTime objects because they will make your life a lot easier on this project.
I will rewrite your code and then tell you what the new code does:
//establish DateTime objects.
$currentDate = new DateTime(); //now.
$orderDate = new DateTime($orderdate); //$orderdate format Y-m-d
//Establish how may days since order date and today.
$difference = $orderDate->diff($currentDate);
$usedDays = $difference->days;
/***
Total Period paid for,
in days, integer.
$product_row['treat1'];
***/
$remainingDays = $product_row['treat1'] - $usedDays;
//Returns an integer value of remaining days.
if($remainingDays < 1) {
echo "<a target = '_blank'
href ='product_addon.php?treatp=".$treatperiod1."'>
Vaccinate Goat</a>";
} elseif($remainingDays==$product_row['treat1']) {
//This will only fire if the goat was vaccinated TODAY.
echo 'Vaccinated';
} else {
echo 'Vaccinated:' .$remainingDays.' Days Left';
}
Hopefully with the help of the link above you should be able to see the basics of what I wrote out for you.
Some notes:
Stop making variables that are simply copies of other variables, it's inefficient and confusing.
(Try to) Stop sending data to new PHP pages as GET URL values such as /newpage.php?treatp=".$var.". This is very probably very insecure.
A more specific answer will need a full explanation from you of your MySQL tables, if nessecary please edit your question and add them.
Try and move away from using timestamps and treating timestamp variables as mathematical entities, and use the DateTime object instead.
Really, to determine if a payment is made you should have a payment date value in your database (set when a payment is successful) and simply compare this date to the value of the integer of the number of days payment covers, using the ->diff() method illustrated above.
Further information on Goat Vaccinations
i have this code:
<tr><td>Data expirare:</td><td><?=date_chooser("date",date("Y-m-d"),0)?></td></tr>
It is working properly, but at the moment I look from 1920 until 2050 and I want to show me only of certain pending and the next five years.
I assume you are using the date_chooser() algorithm from this SO post: How to jump to anchor on submit - not to top of page or this internet page: http://ideone.com/Ab0cLD
I adapted a small part of the code by adding two variables: $from_year and $to_year. They do now define the range of the years in your drop down. You can the adapt the value of the variables to your needs.
$chooser.="<select name='".$name."year'>";
$from_year = 1950
$to_year = date("Y") + 5
for($i=$from_year;$i<=$to_year;$i++)
{
if($i==$year) $selected='selected';
else $selected='';
$chooser.="<option $selected>$i</option>";
}
I am using Google calendar api V3 with PHP and am trying to get event's summary, description and start date. My issue is with the last element: Start date. When events in the calendar are set as "All day" events, the response from the following code gives me today's date and the exact time when the query was made:
echo "<div id=Activite class=titre>", $event->getSummary(), "</div>\n";
$event_date = (new DateTime($event->getStart()->getDateTime()))->format('d/m/Y H:i');
echo "<div class=date_start><span style=color:yellow;>Start: </span>", $event_date, "</div>\n";
Here is an example of what is returned:
prise de photos des élèves
Start: 22/11/2014 18:30
Reading the same output from the "Google APIs Explorer", I get:
start": {
"date": "2013-09-13"
Which is nothing like what I am getting in my case. What am I doing wrong?
Well, here goes for the answer. After great advise by "ippi", I got to understand that Google uses 2 different variables for an event: start... "Date" / "DateTime". The code that worked for me is this work around that enabled the code to recognize if it was dealing with an all day event or not:
if (($event->getStart()->getDate())!= NULL) {
$event_date = (new DateTime($event->getStart()->getDate()))->format('d/m/Y');
} else {
$event_date = (new DateTime($event->getStart()->getDateTime()))->format('d/m/Y H:i');
}
I'm using a Calendar plugin and there's one thing I would like to change
There's a php function that adds the event name:
include/Calendar/Calendar.class.php
$tab .= '<div class="namevent"> '.$event['event'].'</div>';
Output: My event name
I would like to add a TIME in the event title, after looking for a while I found the time functions in
public/events.php
if(!empty($custom['stime'][0]))
echo '<br /><strong>'.$home[16].':</strong> '.$custom['stime'][0].' ';
if(!empty($custom['etime'][0]))
echo '<strong>'.$home[17].'</strong> '.$custom['etime'][0];
Output: 10:00 to 11:00 (supposing your event time are these)
So then I tried this:
$tab .= '<div class="namevent"> '.$custom['stime'][0].' - '.$custom['etime'][0].' '.$event['event'].'</div>';
Expeting the output to be: 10:00 - 11:00 My event name
But it didn't work;
What i'm doing wrong?
Thanks a lot!
Make sure $custom['stime'][0] and $custom['etime'][0] exist, with a var_dump() or print_r() on each.
Add the following code just before your line which causes the error :
var_dump($custom['stime']); // Be sure the var is not undefined and [0] exists
var_dump($custom['etime']);
I set the users timezone in the header of my page, in my setting area though where a user can pick a timezone, I am trying to show the actual time in my dropdown list of time zones.
the current time is already changed from me setting the pages timezone above, so the already changed time is getting changed again
<?PHP
date_default_timezone_set($_SESSION['time_zone']);
?>
Above set the time zone, below is my code that runs through an array of time zones and builds a form dropdown list, it will have all my time zones and show which one I currently have saved into the session variable. It also shows the current time next to the name to each time zone in my list.
The problem is, I think the previous set time zone for the page, the code above, I think it is messing the times in my dropdown list, If I show the current time on the page, it is correct to my time zone, if I look at times in the dropdown list, they are hours off, any idea how I can do this?
<?PHP
// the time zone array would be here
echo '<select name="time_zone_list" id="time_zone_list"/>';
$_SESSION['time_zone'] = (isset($_SESSION['time_zone'])) ? $_SESSION['time_zone'] : '';
// the current time is already changed from me setting the pages timezone above, so the already changed time is getting changed again
$current_date = date("h:i:s A");
foreach ($time_zone_array as $tz_id => $tz_name) {
$selected = "";
if ($tz_id == $_SESSION['time_zone']) $selected = ' selected="selected"';
//build time to show user in dropdown
$dt_obj = new DateTime($current_date." UTC");
$dt_obj->setTimezone(new DateTimeZone($tz_id));
print '<option value=' . $tz_id . $selected . '> ' .date_format($dt_obj, 'h:i:s A'). ' ' . $tz_name . '</option>';
}
echo '</select>';
?>
I was able to get it working correctly by changing date() to gmdate() for my current time