you have $sesssiondate = $coursedate inside your for loop so it keeps getting reset
Issue adding days in a for loop
Hello all, I am working on a training application. Trainers will need to take attendance for a course. So when generating course(s), admins can select: Start date, number of courses, Interval between courses, Number of session, Interval between sessions.
So each course will have an attendance object. Each attendance object will have one or more sessions. The problem I am having is the sessions and the dates.
$validated = $request->validated()
$no_courses = 0;
$courseDate = new Carbon($validated['start_date']); //Comes from the form
//The course, for loop, works great
for($i = 0; $i < $validated['no_classes'];$i++) {
$course = Course::create([
'course_cat_id' => $coursecat->id,
'name' => $coursecat->name . ' : ' . $courseDate->format('Y-m-d'),
'start_date' => $courseDate->format('Y-m-d'),
'start_time' => $validated['start_time'],
'end_time' => $validated['end_time'],
'summary' => $validated['description'],
]);
$courseDate->add($validated['interval'], 'day');
$no_courses++;
$attendance = Attendance::create([ //One attendance object per course. this works
'course_id' => $course->id,
]);
//So the number of session_date is the problem. Course can span multiple days and attendance will need to be taken every day (session).
for($a = 0; $a < $validated['attendance_sessions'];$a++) {
$sesssionDate = $courseDate;
Attendancesession::create([
'attendances_id' => $attendance->id,
'session_starttime' => $validated['start_time'],
'session_endtime' => $validated['end_time'],
'session_date' => $sesssionDate,
]);
$sesssionDate = $sesssionDate->addDays($validated['session_interval']); //This is not working in this for loop. The number of 'session_interval' in days should be added each iteration.
}
}
So once this runs the Courses are created with the correct number of days between each course. The sessions, on the other hand, all have the same date which is the first course date when they are supposed to start on the first course created date and the session_interval between the rest of the sessions.
I hope I explained it clearly.
Any assistance would be appreciated.
To make the code more readable, you could try to refactor from the inside-out thus first creating a separate method for the inner for() loop:
for($a = 0; $a < $validated['attendance_sessions'];$a++) {
Attendancesession::create([
'attendances_id' => $attendance->id,
'session_starttime' => $validated['start_time'],
'session_endtime' => $validated['end_time'],
'session_date' => $sessionDate,
]);
$sessionDate->add($validated['session_interval'], 'day');
}
// first refactor step:
public function createAttendanceSession($validated, $attendance, $sessionDate)
{
for ($a = 0; $a < $validated['attendance_sessions']; $a++) {
Attendancesession::create([
'attendances_id' => $attendance->id,
'session_starttime' => $validated['start_time'],
'session_endtime' => $validated['end_time'],
'session_date' => $sessionDate,
]);
$sessionDate->add($validated['session_interval'], 'day');
}
return true;
}
$courseDate = new Carbon($validated['start_date']);
for($i = 0; $i < $validated['no_classes'];$i++) {
$course = Course::create([
'course_cat_id' => $coursecat->id,
'name' => $coursecat->name . ' : ' . $courseDate->format('Y-m-d'),
'start_date' => $courseDate->format('Y-m-d'),
'start_time' => $validated['start_time'],
'end_time' => $validated['end_time'],
'summary' => $validated['description'],
]);
$sessionDate = new Carbon($courseDate); // Make a new carbon object and copy it into session date before adding days. This is then used in second iteration. and can be modified independantly of $courseDate
$courseDate->add($validated['interval'], 'day');
$no_courses++;
$attendance = Attendance::create([
'course_id' => $course->id,
]);
// after initial for loop
$this->createAttendanceSessions($validated, $attendance, $sessionDate);
Just to be clear: the refactoring step doesn't stop here, I only show the first step you could take.
Now, after the first refactor step, a lot of things could be cleaned up: doubly used variables, lower the amount of variables we have to pass to the function(s), unclear variable names ($a), what should we return from the function (true, or a collection of created attendance sessions?), maybe we could use a collection instead of a for loop, maybe the whole API should be reworked. These are decisions you'd need to overthink.
Have you checked out Jeffrey's course on refactoring yet? https://laracasts.com/series/whip-monstrous-code-into-shape
Please or to participate in this conversation.