0% found this document useful (0 votes)
2 views4 pages

School Tracking Code Walkthrough

The document provides a comprehensive code reference for a PHP/MySQL multi-role web application designed for a school tracking system. It details the structure and functionality of various components, including database connections, user authentication, role-based access control, and specific pages for admin, teacher, student, and parent functionalities. Key features include SQL injection defense, account lockout mechanisms, and file upload validations, alongside a database schema overview with junction tables for managing relationships.

Uploaded by

sqwala72
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views4 pages

School Tracking Code Walkthrough

The document provides a comprehensive code reference for a PHP/MySQL multi-role web application designed for a school tracking system. It details the structure and functionality of various components, including database connections, user authentication, role-based access control, and specific pages for admin, teacher, student, and parent functionalities. Key features include SQL injection defense, account lockout mechanisms, and file upload validations, alongside a database schema overview with junction tables for managing relationships.

Uploaded by

sqwala72
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

DEFENSE PREP — CODE REFERENCE

School Tracking System — Code Walkthrough


PHP / MySQL Multi-Role Web Application · Almoataz Adnan · 21F22010

1. Foundation Files (used by every page)

config/[Link] — Database Connection

Creates the PDO connection to MySQL. Three options matter most:

PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // throw real errors


PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // rows as assoc arrays
PDO::ATTR_EMULATE_PREPARES => false, // REAL prepared statements

WHY EMULATE_PREPARES = FALSE MATTERS

This forces PHP to send the query and the user's data to MySQL separately — MySQL itself treats the input strictly as data, never as part
of the SQL command. This is the core SQL-injection defense across the whole app.

includes/[Link] — Session & Access Control

isLoggedIn() — checks $_SESSION['user_id'] is set


requireLogin() — redirects to login if not logged in
requireRole('teacher') — calls requireLogin(), then checks session role matches; this is the role-based access control gate on every
protected page
loginUser() / logoutUser() — write / destroy session data

Also sets date_default_timezone_set('Asia/Muscat') globally.

includes/[Link] — Shared Utilities

sanitize() — strips HTML tags + trims input


hashPassword() — wraps password_hash($password, PASSWORD_DEFAULT) (bcrypt)
isValidFileUpload() — checks upload error code, extension, that the file's real MIME type matches its extension, and size ≤ 10MB
getAttendancePercentage() / getStudentGPA() — SQL aggregate helpers for dashboards

2. Login — [Link]

If already logged in, redirects straight to the role dashboard via a lookup map. On POST, the logic order is important:

1. Look up the user row by username


2. Check lockout first — if failed_attempts >= 5 AND the last attempt was within 15 minutes, block login (admin is exempt from
lockout)
3. If the 15-minute window has passed, reset failed_attempts to 0 automatically
4. Only then check password_verify($password, $user['password'])

if ($user['role'] !== 'admin'


&& (int)$user['failed_attempts'] >= MAX_ATTEMPTS
&& $user['login_timestamp'] !== null) {
// check if still within 15-minute lockout window
}

KEY FACT

Lockout state lives in the database ( users.failed_attempts , users.login_timestamp ) — not the session — so it persists even if the
browser is closed and reopened.
3. Admin Pages ADMIN

FILE WHAT IT DOES

admin/[Link] Dashboard — 6 summary cards (students, teachers, classes, assignments, parents, submissions) + 4 live charts
(attendance trend, attendance breakdown, grade distribution, users by role). Counts pulled with simple SELECT
COUNT(*) queries.

admin/manage_users.php Create / edit / delete users. New passwords run through password_hash() before insert. Editing a user without typing a
new password keeps the old hash untouched.

admin/manage_classes.php Create classes; assign teachers and students via checkboxes — this is what writes rows into the class_teachers and
student_classes junction tables.

admin/[Link] Aggregate reporting views across attendance/grades.

admin/[Link] / Admin-side messaging — send to one role or everyone, view received messages.
[Link]

4. Teacher Pages TEACHER

teacher/[Link] — Fixed Bug #1 (duplicate rows)

Teacher selects a class + date; students are loaded via a join through student_classes . On save, each student's radio choice is written with:

INSERT INTO attendance (student_id, teacher_id, class_id, date, status)


VALUES (?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
status = VALUES(status),
teacher_id = VALUES(teacher_id)

WHY THIS FIXES IT

The attendance table has UNIQUE KEY uq_attendance (student_id, class_id, date) — a unique rule across three columns together. If
that exact combination already exists, MySQL doesn't insert a new row — ON DUPLICATE KEY UPDATE tells it to update the existing row's
status instead. This is what stops the same student getting two attendance rows on the same day.

teacher/[Link]

Add / edit / delete grades. Validation before insert:

elseif (!is_numeric($gradeVal) || (float)$gradeVal < 0 || (float)$gradeVal > 100) {


$error = 'Grade value must be a number between 0 and 100.';
}

Delete and edit both filter WHERE teacher_id = ? — a teacher can only touch grades they themselves entered.

teacher/[Link]

Create assignments, optional file attachment, optional deadline. File size limit defined as a named constant: define('MAX_FILE_BYTES', 10 *
1024 * 1024);

teacher/[Link] / [Link]

Send announcements to students/parents in a class; view received messages.


5. Student Pages STUDENT

student/[Link] — Fixed Bug #2 (oversized files not rejected)

On submission, three checks run in order: extension allow-list, real MIME type allow-list, then size:

if (!in_array($ext, $allowed, true) || !in_array($mime, $allowedMimes, true)) {


$error = 'Invalid file type. Allowed: PDF, DOC, DOCX, ZIP.';
} elseif ($fileSize > 10 * 1024 * 1024) {
$error = 'File exceeds 10 MB limit.';
}

WHY THIS FIXES IT


$fileSize comes from PHP as a raw byte count. The fix compares it against 10 * 1024 * 1024 — the real byte value of 10MB
(10,485,760). The earlier broken version compared bytes against a bare 10 , a number that's basically never bigger than a real file's
byte count, so the check never actually triggered.

Duplicate submissions are also blocked at the database level: assignment_submissions has UNIQUE KEY uq_submission (assignment_id,
student_id) . The code catches MySQL's duplicate-key error code directly:

if ($e->getCode() === '23000') {


$error = 'You have already submitted this assignment.';
}

student/view_grades.php / view_attendance.php

Read-only views, always scoped to the logged-in student's own student_id — never accept an ID from the URL for these.

6. Parent Pages PARENT

parent/view_child.php

The parent–child link lives in the parents table ( parent_id , user_id , student_id , relationship ). The page joins parents → students → users
to resolve the child's name and class, then pulls attendance/grade summaries with an optional month filter. If a parent has more than one
child, $_GET['student_id'] switches between them.
7. Database Schema — Junction Tables

TABLE COLUMNS RELATIONSHIP

student_classes student_id, class_id (composite PK) Many-to-many: students ↔ classes

class_teachers class_id, teacher_id (composite PK) Many-to-many: classes ↔ teachers

Both use ON DELETE CASCADE — deleting a class automatically removes its links in these tables.

COMMON SLIP TO AVOID

The second junction table is called class_teachers, not "teacher_classes." Say the exact name.

8. Quick-Fire Facts

TOPIC ANSWER

Password hashing password_hash() / password_verify() — bcrypt via PASSWORD_DEFAULT

SQL injection defense PDO prepared statements, EMULATE_PREPARES => false

Account lockout rule 5 failed attempts → 15-minute lockout (admin exempt), stored in users table

File upload limit 10MB, checked via real byte comparison (10 × 1024 × 1024)

Attendance statuses present , absent , late — ENUM column

Grade range 0–100, stored as DECIMAL(5,2) (e.g. 87.50)

Attendance unique key (student_id, class_id, date) — three columns together

Submission unique key (assignment_id, student_id) — blocks double submission

School Tracking System Web Application · Code reference compiled for final-year defense preparation

You might also like