Reputation: 1020
I've been struggling with this for a while and would love some fresh ideas.
I have an events calendar that has recurring events. I've run into some problems when I try to update recurring events.
I have a simple form where I ask the user for a day of the week and a start date.
I want to get the next day of the week after the start date (no problem here) and update the exiting event that week to the new starting day(still no problem). Then I want to increment all the other events after that to be 7 days after the event before it. (<--problem)
<?php
session_start();
require_once '../../../config/db-config.php';
$weekday = $_POST['weekday']; // day of the week the event should take place on
$start_date = $_POST['start-date']; //new starting date of the event
if (date('N', strtotime($start_date)) == $weekday)
{
$start_date = $_POST['start-date'];
}
else
{
$start_date = date('Y-m-d', strtotime("next $weekday", strtotime($start_date))); //gets the first day of the week after the starting date. First event should start on this day.
}
$start_time = $_POST['start-time'];
$end_time = $_POST['end-time'];
$start = $start_date . " " . $start_time; //'yyyy-dd-mm hh:mm:ii' format
$end = $start_date . " " . $end_time;
$repeats = $_POST['repeats']; // 1 for repeats 0 for no repeats
$repeat_freq = $_POST['repeat-freq']; //7 for 7 days, 14 for 14 days etc
$parent_id = $_POST['parent-id']; //common parent_id to the event group
$stmt = $dbh->prepare("
UPDATE events
SET start = :start, end = :end
WHERE parent_id = :parent_id AND WEEK(start) =WEEK(:start)"); //This updates the existing event of that week to the new starting date
$stmt->bindParam(':start', $start);
$stmt->bindParam(':end', $end);
$stmt->bindParam(':parent_id', $parent_id);
$stmt->execute();
}
Now I need to loop through every event (with the same parent_id) after this one and increment it by 7 days (or whatever my repeat_freq is). I've tried using
UPDATE events
SET start = :start + INTERVAL 7 DAY, end = :end + INTERVAL 7 DAY
but this just updates all the events to 7 days after the new start date and not from 7 days from the last event. If I could put this in a loop without having to reference the specific event id and just go sequentially, that'd be great. I'm open to any solutions though. Thanks for reading.
UPDATE FOR SCHEMA
My parent_events table has
parent_id (auto increment) | start_date | repeats | repeat_freq |
My events table has the following
event_id (auto increment) | parent_id | start | end |
When a new recurring event is created I insert a row into the parent_events table. I get the new parent_id using lastInsertId() and use it when I insert all of the recurring instances (of that parent event) into the events table. Basically, the events table holds all of the instances of a specific (parent) event.
UPDATE FOR WORKING CODE
$stmt = $dbh->prepare("
SELECT event_id
FROM events
WHERE parent_id = :parent_id AND WEEK(start) >=WEEK(:start)");
$stmt->bindParam(':start', $start_date);
$stmt->bindParam(':parent_id', $parent_id);
$stmt->execute();
$updateArray = array();
$last_class = 0;
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
if ($last_event != $row['event_id']) {
$last_event = $row['event_id'];
$updateArray[$last_event] = array('event_id' => $row['event_id']);
}
}
foreach($updateArray as $update){
$event_id = $update['event_id'];
$stmt = $dbh->prepare("
UPDATE events
SET title = start = :start, end=:end
WHERE event_id = :event_id");
$stmt->bindParam(':start', $start);
$stmt->bindParam(':end', $end);
$stmt->bindParam(':event_id', $event_id);
$stmt->execute();
$new_start = strtotime($start . '+' . $repeat_freq . 'DAYS');
$new_end = strtotime($end . '+' . $repeat_freq . 'DAYS');
$start = gmdate("Y-m-d H:i", $new_start);
$end = gmdate("Y-m-d H:i", $new_end);
}
Upvotes: 1
Views: 885
Reputation: 2981
I think the easiest way is loop through the SET of events via PHP.
I will write below the important pieces of code:
$sql='SELECT event_id AS id from events WHERE parent_id=:parent_id AND start=:start
Running this Query will get an array with all IDs that required update
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$row_date=array();
$row_date[0]=$start //get start date
foreach ($rows as $row)
$sql_date="SELECT TIMESTAMPADD(week,1,$row_date[0])"; //increment start date by 1 week
$date = $mysqli->query($sql_date);
$row_date = $result->fetch_array(MYSQLI_NUM); //Set the start date as Start date + 1 week to reflect in the next loop.
$sql_update="UPDATE events SET start=$row_date[0] WHERE event_id=$row['id']";
$mysqli->query($sql_update);
end foreach
The code my need some adjustment, but I think it helps outlay the idea.
Upvotes: 1