Paramclasses Academy - Blog

Tutorials Details

Student Management System Using Core PHP and MySQL

Student Management System Using Core PHP and MySQL

October 16, 2026

Student Management System Using Core PHP and MySQL

A Student Management System is a practical web development project that helps manage student information, including names, email addresses, phone numbers, courses, and registration dates.

Building this project using Core PHP and MySQL is an excellent way to practice PHP programming, database connectivity, CRUD operations, form validation, and secure coding techniques.

In this tutorial, you will learn how to build a basic Student Management System from scratch using Core PHP, MySQL, HTML, and CSS.

What Is a Student Management System?

A Student Management System is a web application used to store, organize, view, update, and delete student records.

Educational institutions and training centers can use such systems to manage student information more efficiently.

Features of This Project

This tutorial project includes:

  • Add new student records.

  • Display all registered students.

  • Edit existing student information.

  • Delete student records.

  • Search for students.

  • Validate form input.

  • Connect PHP with a MySQL database.

  • Use prepared statements to help prevent SQL injection.

  • Escape output to reduce the risk of cross-site scripting (XSS).

This is a learning project. Features such as authentication, role-based permissions, backups, and audit logs should be added before adapting it for production use.

Technologies Used

Technology Purpose
HTML5 Creates the page structure
CSS3 Styles the interface
Core PHP Handles application logic
MySQL Stores student records
PDO Connects PHP to MySQL securely

Step 1: Set Up the Development Environment

For this tutorial, we will use XAMPP on Windows.

  1. Install XAMPP.

  2. Start Apache and MySQL from the XAMPP Control Panel.

  3. Open your project directory:

C:\xampp\htdocs\
  1. Create a folder named:

student-management

Your project will be located at:

C:\xampp\htdocs\student-management\

Step 2: Create the MySQL Database

Open phpMyAdmin in your browser:

http://localhost/phpmyadmin

Create a database named:

student_management

Next, open the SQL tab and execute the following query.

CREATE DATABASE IF NOT EXISTS student_management;

USE student_management;

CREATE TABLE students (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(150) NOT NULL UNIQUE,
    phone VARCHAR(20) NOT NULL,
    course VARCHAR(100) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

The students table stores student details. The id field is the primary key, and the unique constraint on email prevents duplicate email addresses.

Step 3: Create the Project Structure

Inside your student-management folder, create these files:

student-management/
│
├── config.php
├── index.php
├── create.php
├── edit.php
├── delete.php
└── style.css

Each file has a specific responsibility:

  • config.php — database connection and shared helper functions.

  • index.php — displays and searches student records.

  • create.php — adds new students.

  • edit.php — updates existing students.

  • delete.php — deletes student records.

  • style.css — styles the application.

Step 4: Connect PHP to MySQL

File path: student-management/config.php

Add the following code:

<?php

declare(strict_types=1);

$host = 'localhost';
$dbname = 'student_management';
$username = 'root';
$password = '';

try {
    $pdo = new PDO(
        "mysql:host={$host};dbname={$dbname};charset=utf8mb4",
        $username,
        $password,
        [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES => false,
        ]
    );
} catch (PDOException $e) {
    error_log($e->getMessage());
    http_response_code(500);
    exit('Database connection failed.');
}

function escape(string $value): string
{
    return htmlspecialchars(
        $value,
        ENT_QUOTES | ENT_SUBSTITUTE,
        'UTF-8'
    );
}

function csrfToken(): string
{
    if (empty($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }

    return $_SESSION['csrf_token'];
}

function verifyCsrfToken(): void
{
    $submittedToken = $_POST['csrf_token'] ?? '';
    $sessionToken = $_SESSION['csrf_token'] ?? '';

    if (
        !is_string($submittedToken) ||
        !is_string($sessionToken) ||
        $sessionToken === '' ||
        !hash_equals($sessionToken, $submittedToken)
    ) {
        http_response_code(403);
        exit('Invalid security token. Please reload the form.');
    }
}

The PDO connection uses exception-based error handling and prepared-statement settings. The escape() function safely encodes text for HTML output, while the CSRF functions help protect forms against cross-site request forgery.

The database credentials above are suitable only for a typical local XAMPP setup. Use environment-based configuration and a dedicated database account in production.

Step 5: Display and Search Student Records

File path: student-management/index.php

This page displays all student records and provides a search field.

<?php

declare(strict_types=1);

session_start();

require __DIR__ . '/config.php';

$search = trim((string) ($_GET['search'] ?? ''));

if ($search !== '') {
    $stmt = $pdo->prepare(
        "SELECT id, name, email, phone, course, created_at
         FROM students
         WHERE name LIKE :name
            OR email LIKE :email
            OR course LIKE :course
         ORDER BY id DESC"
    );

    $term = '%' . $search . '%';

    $stmt->execute([
        'name' => $term,
        'email' => $term,
        'course' => $term,
    ]);
} else {
    $stmt = $pdo->query(
        "SELECT id, name, email, phone, course, created_at
         FROM students
         ORDER BY id DESC"
    );
}

$students = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Student Management System</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
    <header class="page-header">
        <div>
            <h1>Student Management System</h1>
            <p>Manage student records in one place.</p>
        </div>

        <a class="btn" href="create.php">+ Add Student</a>
    </header>

    <form class="search-form" method="GET" action="index.php">
        <input
            type="search"
            name="search"
            placeholder="Search by name, email, or course"
            value="<?= escape($search) ?>"
        >

        <button type="submit" class="btn">Search</button>

        <?php if ($search !== ''): ?>
            <a class="btn btn-secondary" href="index.php">Reset</a>
        <?php endif; ?>
    </form>

    <div class="table-wrapper">
        <table>
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Name</th>
                    <th>Email</th>
                    <th>Phone</th>
                    <th>Course</th>
                    <th>Registered</th>
                    <th>Actions</th>
                </tr>
            </thead>

            <tbody>
            <?php if ($students): ?>
                <?php foreach ($students as $student): ?>
                    <tr>
                        <td><?= (int) $student['id'] ?></td>
                        <td><?= escape($student['name']) ?></td>
                        <td><?= escape($student['email']) ?></td>
                        <td><?= escape($student['phone']) ?></td>
                        <td><?= escape($student['course']) ?></td>
                        <td><?= escape($student['created_at']) ?></td>
                        <td class="actions">
                            <a
                                class="btn btn-small"
                                href="edit.php?id=<?= (int) $student['id'] ?>"
                            >Edit</a>

                            <form
                                method="POST"
                                action="delete.php"
                                onsubmit="return confirm('Are you sure you want to delete this student?');"
                            >
                                <input
                                    type="hidden"
                                    name="id"
                                    value="<?= (int) $student['id'] ?>"
                                >

                                <input
                                    type="hidden"
                                    name="csrf_token"
                                    value="<?= escape(csrfToken()) ?>"
                                >

                                <button
                                    type="submit"
                                    class="btn btn-danger btn-small"
                                >Delete</button>
                            </form>
                        </td>
                    </tr>
                <?php endforeach; ?>
            <?php else: ?>
                <tr>
                    <td colspan="7" class="empty">
                        No student records found.
                    </td>
                </tr>
            <?php endif; ?>
            </tbody>
        </table>
    </div>
</div>
</body>
</html>

This page uses a prepared statement for the search query and escapes values before displaying them. The delete operation uses a POST form instead of a destructive GET link.

Step 6: Add a New Student

File path: student-management/create.php

This page displays a form and inserts a new record into the database.

<?php

declare(strict_types=1);

session_start();

require __DIR__ . '/config.php';

$errors = [];
$name = '';
$email = '';
$phone = '';
$course = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    verifyCsrfToken();

    $name = trim((string) ($_POST['name'] ?? ''));
    $email = trim((string) ($_POST['email'] ?? ''));
    $phone = trim((string) ($_POST['phone'] ?? ''));
    $course = trim((string) ($_POST['course'] ?? ''));

    if ($name === '' || strlen($name) > 100) {
        $errors[] = 'Name is required and must be within 100 bytes.';
    }

    if (
        $email === '' ||
        strlen($email) > 150 ||
        !filter_var($email, FILTER_VALIDATE_EMAIL)
    ) {
        $errors[] = 'Please enter a valid email address.';
    }

    if ($phone === '' || strlen($phone) > 20) {
        $errors[] = 'Phone is required and must be within 20 bytes.';
    }

    if ($course === '' || strlen($course) > 100) {
        $errors[] = 'Course is required and must be within 100 bytes.';
    }

    if (!$errors) {
        try {
            $stmt = $pdo->prepare(
                "INSERT INTO students (name, email, phone, course)
                 VALUES (:name, :email, :phone, :course)"
            );

            $stmt->execute([
                'name' => $name,
                'email' => $email,
                'phone' => $phone,
                'course' => $course,
            ]);

            header('Location: index.php');
            exit;
        } catch (PDOException $e) {
            if ($e->getCode() === '23000') {
                $errors[] = 'This email address may already be registered.';
            } else {
                error_log($e->getMessage());
                $errors[] = 'Unable to save the student. Please try again.';
            }
        }
    }
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Add Student</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
<div class="form-container">
    <h1>Add New Student</h1>

    <?php foreach ($errors as $error): ?>
        <p class="error"><?= escape($error) ?></p>
    <?php endforeach; ?>

    <form method="POST" action="create.php">
        <input
            type="hidden"
            name="csrf_token"
            value="<?= escape(csrfToken()) ?>"
        >

        <label for="name">Full Name</label>
        <input
            id="name"
            type="text"
            name="name"
            maxlength="100"
            value="<?= escape($name) ?>"
            required
        >

        <label for="email">Email Address</label>
        <input
            id="email"
            type="email"
            name="email"
            maxlength="150"
            value="<?= escape($email) ?>"
            required
        >

        <label for="phone">Phone Number</label>
        <input
            id="phone"
            type="text"
            name="phone"
            maxlength="20"
            value="<?= escape($phone) ?>"
            required
        >

        <label for="course">Course</label>
        <input
            id="course"
            type="text"
            name="course"
            maxlength="100"
            value="<?= escape($course) ?>"
            required
        >

        <button type="submit" class="btn">Save Student</button>
        <a class="btn btn-secondary" href="index.php">Back</a>
    </form>
</div>
</body>
</html>

The form validates input on the server and uses a prepared statement for the insert query. The email column's unique constraint prevents duplicate email addresses.

Step 7: Edit Student Details

File path: student-management/edit.php

This page loads an existing record and updates it after the form is submitted.

<?php

declare(strict_types=1);

session_start();

require __DIR__ . '/config.php';

$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);

if (!$id || $id < 1) {
    http_response_code(400);
    exit('Invalid student ID.');
}

$stmt = $pdo->prepare(
    "SELECT id, name, email, phone, course
     FROM students
     WHERE id = :id"
);

$stmt->execute(['id' => $id]);

$student = $stmt->fetch();

if (!$student) {
    http_response_code(404);
    exit('Student not found.');
}

$errors = [];

$name = $student['name'];
$email = $student['email'];
$phone = $student['phone'];
$course = $student['course'];

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    verifyCsrfToken();

    $name = trim((string) ($_POST['name'] ?? ''));
    $email = trim((string) ($_POST['email'] ?? ''));
    $phone = trim((string) ($_POST['phone'] ?? ''));
    $course = trim((string) ($_POST['course'] ?? ''));

    if ($name === '' || strlen($name) > 100) {
        $errors[] = 'Name is required and must be within 100 bytes.';
    }

    if (
        $email === '' ||
        strlen($email) > 150 ||
        !filter_var($email, FILTER_VALIDATE_EMAIL)
    ) {
        $errors[] = 'Please enter a valid email address.';
    }

    if ($phone === '' || strlen($phone) > 20) {
        $errors[] = 'Phone is required and must be within 20 bytes.';
    }

    if ($course === '' || strlen($course) > 100) {
        $errors[] = 'Course is required and must be within 100 bytes.';
    }

    if (!$errors) {
        try {
            $stmt = $pdo->prepare(
                "UPDATE students
                 SET name = :name,
                     email = :email,
                     phone = :phone,
                     course = :course
                 WHERE id = :id"
            );

            $stmt->execute([
                'name' => $name,
                'email' => $email,
                'phone' => $phone,
                'course' => $course,
                'id' => $id,
            ]);

            header('Location: index.php');
            exit;
        } catch (PDOException $e) {
            if ($e->getCode() === '23000') {
                $errors[] = 'This email address may already be registered.';
            } else {
                error_log($e->getMessage());
                $errors[] = 'Unable to update the student. Please try again.';
            }
        }
    }
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Edit Student</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
<div class="form-container">
    <h1>Edit Student</h1>

    <?php foreach ($errors as $error): ?>
        <p class="error"><?= escape($error) ?></p>
    <?php endforeach; ?>

    <form method="POST" action="edit.php?id=<?= (int) $id ?>">
        <input
            type="hidden"
            name="csrf_token"
            value="<?= escape(csrfToken()) ?>"
        >

        <label for="name">Full Name</label>
        <input
            id="name"
            type="text"
            name="name"
            maxlength="100"
            value="<?= escape($name) ?>"
            required
        >

        <label for="email">Email Address</label>
        <input
            id="email"
            type="email"
            name="email"
            maxlength="150"
            value="<?= escape($email) ?>"
            required
        >

        <label for="phone">Phone Number</label>
        <input
            id="phone"
            type="text"
            name="phone"
            maxlength="20"
            value="<?= escape($phone) ?>"
            required
        >

        <label for="course">Course</label>
        <input
            id="course"
            type="text"
            name="course"
            maxlength="100"
            value="<?= escape($course) ?>"
            required
        >

        <button type="submit" class="btn">Update Student</button>
        <a class="btn btn-secondary" href="index.php">Cancel</a>
    </form>
</div>
</body>
</html>

The script validates the student ID, loads the existing record, validates submitted fields, and updates the record using a prepared statement.

Step 8: Delete a Student Record

File path: student-management/delete.php

Use POST requests and a CSRF token for deletion.

<?php

declare(strict_types=1);

session_start();

require __DIR__ . '/config.php';

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    header('Allow: POST');
    exit('Method not allowed.');
}

verifyCsrfToken();

$id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);

if (!$id || $id < 1) {
    http_response_code(400);
    exit('Invalid student ID.');
}

$stmt = $pdo->prepare(
    "DELETE FROM students WHERE id = :id"
);

$stmt->execute(['id' => $id]);

header('Location: index.php');
exit;

This script accepts only POST requests, validates the ID, verifies the CSRF token, and uses a prepared statement to delete the record.

In a production application, deletion should also require proper authentication and authorization.

Step 9: Design the Application

File path: student-management/style.css

Add the following CSS for a clean, responsive interface.

* {
    box-sizing: border-box;
}

body {
    margin: 0;
    padding: 30px 16px;
    font-family: Arial, sans-serif;
    background: #f3f6fb;
    color: #1f2937;
}

.container,
.form-container {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
}

.form-container {
    max-width: 600px;
    background: #ffffff;
    padding: 28px;
    border-radius: 12px;
    box-shadow: 0 8px 30px rgba(15, 23, 42, 0.08);
}

.page-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 20px;
    margin-bottom: 24px;
}

h1 {
    margin-top: 0;
    color: #172554;
}

.page-header p {
    color: #64748b;
}

.search-form {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 20px;
}

input {
    width: 100%;
    padding: 12px;
    border: 1px solid #cbd5e1;
    border-radius: 7px;
    font-size: 15px;
}

.search-form input {
    flex: 1;
    min-width: 200px;
}

label {
    display: block;
    margin: 16px 0 7px;
    font-weight: 600;
}

.btn {
    display: inline-block;
    border: none;
    border-radius: 7px;
    padding: 11px 15px;
    background: #2563eb;
    color: #ffffff;
    text-decoration: none;
    font-size: 14px;
    cursor: pointer;
}

.btn:hover {
    background: #1d4ed8;
}

.btn-secondary {
    background: #64748b;
}

.btn-danger {
    background: #dc2626;
}

.btn-danger:hover {
    background: #b91c1c;
}

.btn-small {
    padding: 8px 10px;
    font-size: 13px;
}

.table-wrapper {
    width: 100%;
    overflow-x: auto;
    background: #ffffff;
    border-radius: 10px;
    box-shadow: 0 5px 20px rgba(15, 23, 42, 0.05);
}

table {
    width: 100%;
    min-width: 850px;
    border-collapse: collapse;
}

th,
td {
    padding: 14px;
    border-bottom: 1px solid #e2e8f0;
    text-align: left;
}

th {
    background: #eaf1ff;
    color: #1e3a8a;
}

tbody tr:hover {
    background: #f8fafc;
}

.actions {
    display: flex;
    align-items: center;
    gap: 7px;
}

.actions form {
    margin: 0;
}

.error {
    padding: 10px;
    background: #fee2e2;
    color: #991b1b;
    border-radius: 6px;
}

.empty {
    padding: 30px;
    text-align: center;
    color: #64748b;
}

@media (max-width: 700px) {
    body {
        padding: 20px 10px;
    }

    .page-header {
        align-items: flex-start;
        flex-direction: column;
    }

    .search-form {
        flex-direction: column;
    }

    .search-form input {
        min-width: 0;
    }

    .form-container {
        padding: 20px;
    }
}

The interface uses a responsive layout and horizontal table scrolling on smaller screens.

Step 10: Run the Student Management System

Make sure Apache and MySQL are running in XAMPP.

Open the following URL in your browser:

http://localhost/student-management/

You should see the Student Management System page.

Test the application in this order:

  1. Click Add Student.

  2. Enter valid student details and save.

  3. Confirm that the new student appears in the table.

  4. Search for a student by name, email, or course.

  5. Click Edit and update the student's details.

  6. Click Delete and confirm that the record is removed.

  7. Try invalid email addresses and duplicate emails to check validation.

If a database connection error occurs, verify the database name, username, password, and MySQL service in XAMPP.

Important Security Improvements for Production

This tutorial provides a foundation, but a real student management application needs additional safeguards.

Before deployment:

  • Add authentication and role-based authorization.

  • Use HTTPS.

  • Store database credentials outside public files.

  • Configure secure session cookies and session ID regeneration.

  • Add pagination for large student lists.

  • Apply stricter validation and appropriate database constraints.

  • Log errors privately instead of exposing internal details.

  • Implement backups, access controls, and appropriate data-retention policies.

The CSRF token protects form submissions against a common class of cross-site request forgery attacks, but it does not replace authentication or authorization.

Common Errors and Solutions

1. Database Connection Failed

Check that MySQL is running and that config.php contains the correct database settings.

2. Table Does Not Exist

Confirm that the students table was created inside the student_management database.

3. Duplicate Email Error

Each email address must be unique because the database column has a UNIQUE constraint.

4. Page Shows a Blank Screen

Check the PHP error logs. For local development, you can enable error display temporarily, but keep it disabled in production.

5. CSS Is Not Loading

Verify that style.css is located in the project root and that the HTML references it as:

<link rel="stylesheet" href="style.css">

Frequently Asked Questions (FAQs)

1. What is a Student Management System in PHP?

It is a web application that uses PHP and commonly a database such as MySQL to manage student records.

2. Which database is used in this project?

This tutorial uses MySQL to store student names, email addresses, phone numbers, courses, and registration dates.

3. What is CRUD in PHP?

CRUD stands for Create, Read, Update, and Delete. These are the four basic operations used to manage records in a database.

4. Why is PDO used in this project?

PDO provides a consistent database interface and supports prepared statements, which help prevent SQL injection when used correctly.

5. Can this project be extended?

Yes. You can add login and registration, pagination, course management, student attendance, fee tracking, CSV export, and an administrative dashboard.

Conclusion

Building a Student Management System using Core PHP and MySQL is a useful project for practicing fundamental web development skills. It combines database connectivity, CRUD operations, form validation, search, responsive design, and basic security measures.

Once the core features are working, you can extend the project with authentication, pagination, reporting, and role-based access control. These improvements will help you understand how to structure more complete PHP applications.