Skip to main content

Overview

The School Management Platform follows the Model-View-Controller (MVC) architectural pattern, a design pattern that separates application logic into three interconnected components. This separation promotes organized code, easier maintenance, and scalability.

MVC Pattern Explained

The Three Components

Model

Handles data logic and database interactions using PDO

View

Presents data to users through PHP templates

Controller

Processes requests and coordinates Model-View interaction

Folder Structure

The application follows a clean, organized directory structure:
school_management/
├── app/
│   ├── controllers/      # Controller classes
│   │   ├── AuthController.php
│   │   ├── StudentController.php
│   │   ├── TeacherController.php
│   │   ├── SubjectController.php
│   │   ├── CourseController.php
│   │   ├── EnrollmentController.php
│   │   ├── GradeController.php
│   │   ├── BulletinController.php
│   │   └── TimetableController.php
│   ├── models/           # Model classes
│   │   ├── User.php
│   │   ├── Student.php
│   │   ├── Teacher.php
│   │   ├── Subject.php
│   │   ├── Course.php
│   │   ├── Enrollment.php
│   │   ├── Grade.php
│   │   └── Timetable.php
│   ├── views/            # View templates
│   │   ├── auth/
│   │   ├── dashboard/
│   │   ├── students/
│   │   ├── teachers/
│   │   ├── subjects/
│   │   ├── courses/
│   │   ├── enrollments/
│   │   ├── grades/
│   │   ├── bulletin/
│   │   └── timetable/
│   └── core/             # Core utilities
│       └── Auth.php      # Authentication & authorization
└── public/               # Publicly accessible files
    ├── index.php         # Front controller (router)
    └── assets/           # CSS, JS, images
        ├── css/
        └── js/

Front Controller: index.php

The public/index.php file serves as the front controller and routing mechanism for the entire application.

Routing Implementation

All requests are routed through a single entry point:
<?php
// Session configuration with security settings
session_set_cookie_params([
    'httponly' => true,
    'secure' => false,      // Set to true in production with HTTPS
    'samesite' => 'Strict'
]);
session_start();

// Parse the request URI
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

// Clean the URI
$uri = str_replace('/school_management/public/index.php', '', $uri);
$uri = str_replace('/school_management/public', '', $uri);

// Initialize controllers
$auth = new AuthController();
$studentController = new StudentController();
$teacherController = new TeacherController();
// ... other controllers

// Route matching
if ($uri === '/login' && $_SERVER['REQUEST_METHOD'] === 'GET') {
    $auth->login();
} elseif ($uri === '/login' && $_SERVER['REQUEST_METHOD'] === 'POST') {
    $auth->authenticate();
}
// ... more routes

Route Categories

Routes are organized by functionality:
/login (GET)     AuthController::login()
/login (POST)    AuthController::authenticate()
/logout AuthController::logout()
/dashboard/admin Display admin dashboard
/dashboard/teacher Display teacher dashboard
/dashboard/student Display student dashboard
/students StudentController::index()
/students/create StudentController::create()
/students/delete StudentController::delete()
/students/search StudentController::search()
/grades GradeController::myCourses()
/grades/course GradeController::students($course_id)
/grades/save GradeController::save()
/timetable TimetableController::index()
/timetable/create TimetableController::create()
/timetable/delete TimetableController::delete()
/timetable/student TimetableController::student()
/timetable/teacher TimetableController::teacher()

Controllers

Controllers handle HTTP requests and coordinate between models and views.

Controller Example

app/controllers/StudentController.php
<?php
require_once __DIR__ . '/../models/Student.php';
require_once __DIR__ . '/../core/Auth.php';

class StudentController
{
    private $model;

    public function __construct()
    {
        $this->model = new Student();
    }

    // Display all students (admin only)
    public function index()
    {
        Auth::admin();  // Role-based access control
        
        $students = $this->model->getAll();
        require __DIR__ . '/../views/students/index.php';
    }

    // Create new student
    public function create()
    {
        Auth::admin();
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $this->model->create(
                $_POST['name'],
                $_POST['email'],
                $_POST['password']
            );
            
            header("Location: /school_management/public/students");
            exit;
        }
        
        require __DIR__ . '/../views/students/create.php';
    }

    // Delete student
    public function delete()
    {
        Auth::admin();
        
        $this->model->delete($_GET['id']);
        header("Location: /school_management/public/students");
        exit;
    }
}

Key Controller Responsibilities

  1. Authentication checking via Auth::admin(), Auth::teacher(), or Auth::student()
  2. Request validation and data extraction from $_POST and $_GET
  3. Model interaction to fetch or persist data
  4. View rendering by including the appropriate view file
  5. Redirects after successful operations

Models

Models encapsulate database logic and business rules.

Model Example

app/models/Student.php
<?php
require_once __DIR__ . '/../../config/database.php';

class Student
{
    private $db;

    public function __construct()
    {
        $this->db = Database::getInstance()->getConnection();
    }

    // Retrieve all students
    public function getAll()
    {
        $sql = "SELECT users.id, users.name, users.email 
                FROM users 
                JOIN students ON users.id = students.id
                ORDER BY users.name";
        
        return $this->db->query($sql)->fetchAll(PDO::FETCH_ASSOC);
    }

    // Create new student
    public function create($name, $email, $password)
    {
        // Insert into users table
        $stmt = $this->db->prepare(
            "INSERT INTO users (name, email, password, role) 
             VALUES (?, ?, ?, 'student')"
        );
        $stmt->execute([$name, $email, password_hash($password, PASSWORD_DEFAULT)]);
        
        $userId = $this->db->lastInsertId();
        
        // Insert into students table
        $stmt = $this->db->prepare("INSERT INTO students (id) VALUES (?)");
        return $stmt->execute([$userId]);
    }

    // Search students by keyword
    public function search($keyword)
    {
        $stmt = $this->db->prepare("
            SELECT students.*, users.name, users.email
            FROM students
            JOIN users ON students.id = users.id
            WHERE users.name LIKE ? OR users.email LIKE ?
        ");
        $stmt->execute(["%$keyword%", "%$keyword%"]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
}

Model Best Practices

Database Abstraction

All database queries are contained in model classes

Prepared Statements

PDO prepared statements prevent SQL injection

Password Hashing

Passwords are hashed using password_hash() before storage

Reusability

Models can be used across multiple controllers

Views

Views are PHP templates that generate HTML output.

View Example

app/views/students/index.php
<!DOCTYPE html>
<html>
<head>
    <title>Students</title>
    <link rel="stylesheet" href="/school_management/public/assets/css/bootstrap.min.css">
</head>
<body>
    <div class="container mt-5">
        <h1>Students List</h1>
        
        <a href="/school_management/public/students/create" class="btn btn-primary mb-3">
            Add New Student
        </a>
        
        <table class="table table-striped">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Name</th>
                    <th>Email</th>
                    <th>Actions</th>
                </tr>
            </thead>
            <tbody>
                <?php foreach ($students as $student): ?>
                    <tr>
                        <td><?= htmlspecialchars($student['id']) ?></td>
                        <td><?= htmlspecialchars($student['name']) ?></td>
                        <td><?= htmlspecialchars($student['email']) ?></td>
                        <td>
                            <a href="/school_management/public/students/delete?id=<?= $student['id'] ?>" 
                               class="btn btn-danger btn-sm"
                               onclick="return confirm('Are you sure?')">
                                Delete
                            </a>
                        </td>
                    </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
    </div>
</body>
</html>

View Characteristics

  • Minimal logic - only presentation logic (loops, conditionals)
  • XSS protection via htmlspecialchars() for output escaping
  • Bootstrap integration for responsive UI
  • Data passed from controllers as PHP variables

Core Components

Authentication Class

The Auth class in app/core/Auth.php provides centralized authentication and authorization:
app/core/Auth.php
class Auth
{
    private static function redirectLogin()
    {
        header("Location: /school_management/public/index.php/login");
        exit;
    }

    // Check login + session timeout
    public static function check()
    {
        if (!isset($_SESSION['user'])) {
            self::redirectLogin();
        }

        // Auto logout after 30 minutes of inactivity
        if (isset($_SESSION['LAST_ACTIVITY']) && 
            (time() - $_SESSION['LAST_ACTIVITY'] > 1800)) {
            session_unset();
            session_destroy();
            self::redirectLogin();
        }

        // Update last activity time
        $_SESSION['LAST_ACTIVITY'] = time();
    }

    public static function admin()
    {
        self::check();
        if ($_SESSION['user']['role'] !== 'admin') {
            self::redirectLogin();
        }
    }
}

Request Flow Example

Here’s how a typical request flows through the MVC architecture:

Benefits of MVC Architecture

Separation of Concerns

Business logic, data access, and presentation are cleanly separated

Code Reusability

Models and controllers can be reused across different parts of the application

Easier Testing

Each component can be tested independently

Team Collaboration

Frontend and backend developers can work simultaneously on views and models

Maintainability

Changes to one component don’t affect others

Scalability

New features can be added following the same pattern

Next Steps

Database Schema

Explore the database structure and relationships

Security Features

Learn about authentication, authorization, and security measures

Build docs developers (and LLMs) love