The api.php file handles API requests and determines which action to perform. The focus here is on generating reports using the report action. Below is a breakdown of how the api.php script works.
- Cache Control: The script sets headers to prevent caching.
- Error Reporting: Error reporting is enabled by using
ini_setto display errors during development.
header("Cache-Control: no-cache, no-store, must-revalidate");
header("Pragma: no-cache");
header("Expires: 0");
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);- The configuration and database connection settings are included via
config.phpanddb.php.
require_once 'config.php';
require_once 'db.php';- The parameters are retrieved using a helper function
getParam()based on the request method (GETorPOST). The action parameter is converted to lowercase for consistency.
$action = strtolower(getParam('action', $requestMethod) ?? '');- The script uses a
switchstatement to check the action requested. In this case, it listens for thereportaction. - It retrieves the necessary parameters:
term_id,student_id,date,absent, andformatusing thegetParams()function. - If all required parameters are available, the script calls
generateReport.phpto process the request.
$result = getParams([], ['term_id', 'student_id', 'date', 'absent', 'format'], $requestMethod);
if (empty($result['missing'])) {
include 'functions/generateReport.php';- If no format is specified, the API defaults to returning a JSON response.
$format = $result['params']['format'] ?? 'json';- If the requested format is
html, the generated report is output directly as HTML. - Otherwise, the report is returned as a JSON response.
if ($format == 'html' && is_string($response)) {
echo $response;
} else {
echo json_encode($response);
}- If parameters are missing, the script returns a JSON error response listing the missing parameters.
} else {
$response = 'Missing parameters: ' . implode(', ', $result['missing']);
echo json_encode(['status' => 'error', 'message' => $response]);
}- If an unrecognized action is sent, a 404 response is returned.
default:
http_response_code(404);
echo json_encode(['error' => 'Invalid action!']);
break;Here's an overview of its functionality:
-
Report Generation Logic:
- The function
generateReportconnects to the database using$pdoto retrieve attendance data based on specific criteria:term_id: The term to filter by.student_id: The specific student to report on.date: The date for the attendance report.absent: If set totrue, it will retrieve students who were absent; otherwise, it will get students who were present.
- The report can be outputted in either HTML or email format.
- The function
-
SQL Query Structure:
- The SQL query is dynamically adjusted based on whether the report is for present or absent students. The query filters students based on their attendance records for the provided
term_idanddate. - The query joins the
students,terms, andleaderstables to fetch student names, leader names, and term information.
- The SQL query is dynamically adjusted based on whether the report is for present or absent students. The query filters students based on their attendance records for the provided
-
HTML Report:
- The
generateHtmlReportfunction builds a clean HTML table to display attendance data, including student ID, name, and group leader. - It uses inline CSS for styling, ensuring a visually clean and formatted report.
- The
-
Error Handling:
- If there is an error during the database operation, it is caught by a
try-catchblock, and an error message is returned.
- If there is an error during the database operation, it is caught by a
- Pagination: If you expect large datasets, you could add pagination to break the results into pages.
- CSV Export: Consider adding an option to export the report as a CSV file, making it easier to share or analyze in spreadsheet software.
- Advanced Filters: You could add filters like
course_idorleader_idto narrow down the report further.
Here’s a step-by-step breakdown of how we build our query using logic to handle the attendance and absent students based on the enrollment in courses ending with "MLC-0000-1":
-
Identify the Correct Term: We’ll use the provided
term_idto fetch the correct term from thetermstable. -
Filter Courses Ending with "MLC-0000-1": We’ll check the
coursestable for courses within the specifiedterm_idthat end with "MLC-0000-1". -
Extract the List of Enrolled Students: Each course contains a JSON array of students in the
studentscolumn. We'll extract this array of students for courses that meet the filtering criteria. -
Compare Enrollment with Attendance Records: Using the provided
date, we will compare the list of enrolled students with the records in theattendancetable.- If
absent=true, we’ll return students who do not have an attendance record for the specified date. - If
absent=false, we’ll return students who do have an attendance record for the specified date.
- If
<?php
function generateReport($pdo, $term_id, $student_id, $date, $absent, $format) {
// Ensure absent is a boolean; default to false if not explicitly true
$absent = isset($absent) ? filter_var($absent, FILTER_VALIDATE_BOOLEAN) : false;
// Fetch courses for the specified term that end with "MLC-0000-1"
$query = "SELECT c.students
FROM courses c
JOIN terms t ON c.term = t.id
WHERE c.term = ? AND c.courseID LIKE '%MLC-0000-1'";
$stmt = $pdo->prepare($query);
$stmt->execute([$term_id]);
$courses = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($courses)) {
return json_encode(['status' => 'error', 'message' => 'No courses found for the specified term.']);
}
// Collect all students from the selected courses
$enrolledStudents = [];
foreach ($courses as $course) {
$students = json_decode($course['students'], true); // Decode the JSON student list
if ($students) {
$enrolledStudents = array_merge($enrolledStudents, $students);
}
}
// If no students are found, return an error
if (empty($enrolledStudents)) {
return json_encode(['status' => 'error', 'message' => 'No students found for the selected courses.']);
}
// Remove duplicate student IDs
$enrolledStudents = array_unique($enrolledStudents);
// Fetch attendance records for the specified date and term
$attendanceQuery = "SELECT a.student_id
FROM attendance a
WHERE a.date = ? AND a.term_id = ?";
$attendanceStmt = $pdo->prepare($attendanceQuery);
$attendanceStmt->execute([$date, $term_id]);
$attendanceRecords = $attendanceStmt->fetchAll(PDO::FETCH_COLUMN);
// Compare enrolled students with attendance records
if ($absent) {
// Return students who are enrolled but do not have an attendance record for the specified date
$absentStudents = array_diff($enrolledStudents, $attendanceRecords);
$attendances = array_values($absentStudents);
} else {
// Return students who are enrolled and have an attendance record for the specified date
$presentStudents = array_intersect($enrolledStudents, $attendanceRecords);
$attendances = array_values($presentStudents);
}
try {
// Fetch term short_name if a term_id is provided
$termShortName = '';
if ($term_id) {
$termQuery = "SELECT short_name FROM terms WHERE id = ?";
$termStmt = $pdo->prepare($termQuery);
$termStmt->execute([$term_id]);
$term = $termStmt->fetch(PDO::FETCH_ASSOC);
$termShortName = $term['short_name'] ?? '';
}
// Format the report date
$formattedDate = ($date) ? (new DateTime($date))->format('m-d-Y') : 'Multiple Dates';
// Return the report in the requested format (default is JSON)
if ($format == 'html') {
$htmlReport = generateHtmlReport($pdo, $attendances, $formattedDate, $termShortName, $absent);
return $htmlReport; // Output HTML directly
} else if ($format == 'email') {
require_once 'sendEmail.php';
return sendEmailReport($pdo, generateHtmlReport($pdo, $attendances, $formattedDate, $termShortName, $absent)); // Pass $pdo here
} else {
return ['status' => 'success', 'data' => $attendances];
}
} catch (PDOException $e) {
return ['status' => 'error', 'message' => $e->getMessage()];
}
}
?>-
Fetch Courses with "MLC-0000-1": The query filters courses based on the
term_idand course names ending with "MLC-0000-1" using theLIKEclause. -
Decode the Student JSON List: For each course that matches the query, we decode the
studentscolumn, which contains a JSON list of enrolled students. -
Compare Enrollment and Attendance: We compare the list of students enrolled in the courses with the records in the
attendancetable for the specified date:- For
absent=true, we return students who are enrolled but do not have a matching attendance record. - For
absent=false, we return students who are enrolled and do have a matching attendance record.
- For
-
Output Formats: The report is returned in either JSON (default), HTML, or email format depending on the
formatparameter.
-
Absent Students Report:
https://localhost/attendance/api.php?action=report&date=2024-08-21&absent=true&format=json&term_id=2This will return all students who do not have an attendance record on
2024-08-21but are enrolled in courses ending in "MLC-0000-1" for the specifiedterm_id. -
Present Students Report (Attendance Report):
https://localhost/attendance/api.php?action=report&date=2024-08-21&absent=false&format=json&term_id=2This will return all students who have an attendance record on
2024-08-21and are enrolled in courses ending in "MLC-0000-1" for the specifiedterm_id.
-
Test with Sample Data: Verify that the API returns the correct list of students (either absent or present) based on the attendance records and course enrollments.
-
Troubleshoot Edge Cases: If some students are missing, check for potential issues such as:
- Incorrect student data in the JSON-encoded
studentscolumn. - Attendance records that are not properly linked to the correct
term_idor date.
- Incorrect student data in the JSON-encoded