Creating an Online Quiz Platform involves several components, including a MySQL database schema, file structure, layout design using Bootstrap 5, and complete PHP scripts for user authentication and management. Below is a comprehensive guide to help you set up your system.
Project Introduction
The Online Quiz Platform is designed to provide a comprehensive solution for creating, managing, and participating in quizzes. This platform allows quiz creators to design quizzes with various question types, set time limits, and analyze participant performance. Participants can take quizzes, receive instant feedback, and view their results. With a robust MySQL database backend, the system ensures secure data management and a seamless user experience for all roles, including administrators, quiz creators, and participants.
Project Objectives
- To create a user-friendly interface for quiz creators to design and manage quizzes.
- To enable participants to easily register, log in, and take quizzes.
- To support various question types, including multiple choice, true/false, and short answer.
- To implement a scoring system that provides instant feedback to participants upon quiz completion.
- To allow users to submit feedback on quizzes for continuous improvement.
- To send notifications to users regarding quiz updates and results.
- To provide an administrative dashboard for managing users, quizzes, and feedback.
Project Modules
- User Management: Handles user registration, login, and role-based access for admins, quiz creators, and participants.
- Quiz Management: Allows quiz creators to create, edit, and delete quizzes, including setting time limits and descriptions.
- Question Management: Enables the addition and management of questions and answer options for each quiz.
- Quiz Attempt Management: Tracks user attempts at quizzes, scores, and completion times.
- Feedback System: Collects and manages feedback from participants regarding quizzes.
- Notification System: Sends notifications to users about quiz updates, results, and feedback requests.
- Admin Dashboard: Provides administrative tools for managing users, quizzes, and overall platform performance.
1. MySQL Database Schema
CREATE DATABASE online_quiz_platform;
USE online_quiz_platform;
-- Table for users
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE,
role ENUM('admin', 'quiz_creator', 'participant') DEFAULT 'participant',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Table for quizzes
CREATE TABLE quizzes (
id INT AUTO_INCREMENT PRIMARY KEY,
creator_id INT NOT NULL,
title VARCHAR(255) NOT NULL,
description TEXT,
time_limit INT, -- in seconds
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (creator_id) REFERENCES users(id) ON DELETE CASCADE
);
-- Table for questions
CREATE TABLE questions (
id INT AUTO_INCREMENT PRIMARY KEY,
quiz_id INT NOT NULL,
question_text TEXT NOT NULL,
question_type ENUM('multiple_choice', 'true_false', 'short_answer') NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (quiz_id) REFERENCES quizzes(id) ON DELETE CASCADE
);
-- Table for answer options (for multiple choice questions)
CREATE TABLE answer_options (
id INT AUTO_INCREMENT PRIMARY KEY,
question_id INT NOT NULL,
option_text VARCHAR(255) NOT NULL,
is_correct BOOLEAN DEFAULT FALSE,
FOREIGN KEY (question_id) REFERENCES questions(id) ON DELETE CASCADE
);
-- Table for quiz attempts
CREATE TABLE quiz_attempts (
id INT AUTO_INCREMENT PRIMARY KEY,
quiz_id INT NOT NULL,
user_id INT NOT NULL,
score DECIMAL(5, 2),
completed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (quiz_id) REFERENCES quizzes(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
-- Table for feedback
CREATE TABLE feedback (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
quiz_id INT NOT NULL,
comments TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (quiz_id) REFERENCES quizzes(id) ON DELETE CASCADE
);
-- Table for notifications
CREATE TABLE notifications (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
message TEXT NOT NULL,
is_read BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
2. File and Folder Structure
online_quiz_platform/
│
├── config/
│ └── db.php
│
├── public/
│ ├── index.php
│ ├── login.php
│ ├── register.php
│ ├── dashboard.php
│ ├── create_quiz.php
│ ├── edit_quiz.php
│ ├── take_quiz.php
│ ├── quiz_results.php
│ ├── feedback.php
│ ├── notifications.php
│ └── admin_dashboard.php
│
├── includes/
│ ├── header.php
│ ├── footer.php
│ └── functions.php
│
├── assets/
│ ├── css/
│ │ └── styles.css
│ ├── js/
│ │ └── scripts.js
│ └── images/
│
└── vendor/
└── (Bootstrap and other libraries)
3. Layout Based Design with Bootstrap 5
Header (includes/header.php)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="assets/css/styles.css">
<title>Online Quiz Platform</title>
</head>
<body>
<div class="container">
<header class="my-4">
<h1>Online Quiz Platform</h1>
</header>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="index.php">Home</a>
<button class ="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="create_quiz.php">Create Quiz</a>
</li>
<li class="nav-item">
<a class="nav-link" href="notifications.php">Notifications</a>
</li>
<li class="nav-item">
<a class="nav-link" href="login.php">Login</a>
</li>
<li class="nav-item">
<a class="nav-link" href="register.php">Register</a>
</li>
</ul>
</div>
</div>
</nav>
<main class="my-4">
Footer (includes/footer.php)
</main>
<footer class="text-center my-4">
<p>© 2023 Online Quiz Platform. All rights reserved.</p>
</footer>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
4. PHP Code for User Authentication
Registration (public/register.php)
<?php
require '../config/db.php';
require '../includes/header.php';
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$username = $_POST['username'];
$email = $_POST['email'];
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
$role = $_POST['role'];
$stmt = $conn->prepare("INSERT INTO users (username, email, password, role) VALUES (?, ?, ?, ?)");
$stmt->bind_param("ssss", $username, $email, $password, $role);
$stmt->execute();
$stmt->close();
header("Location: login.php");
}
?>
<form method="POST" action="">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="email" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<div class="mb-3">
<label for="role" class="form-label">Role</label>
<select class="form-select" id="role" name="role">
<option value="participant">Participant</option>
<option value="quiz_creator">Quiz Creator</option>
<option value="admin">Admin</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
<?php require '../includes/footer.php'; ?>
Login (public/login.php)
<?php
session_start();
require '../config/db.php';
require '../includes/header.php';
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$username = $_POST['username'];
$password = $_POST['password'];
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();
if ($user && password_verify($password, $user['password'])) {
$_SESSION['user_id'] = $user['id'];
$_SESSION['role'] = $user['role'];
header("Location: dashboard.php");
} else {
echo "Invalid credentials.";
}
}
?>
<form method="POST" action="">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" required </div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
<?php require '../includes/footer.php'; ?>
5. Additional PHP Scripts
Dashboard (public/dashboard.php)
<?php
session_start();
require '../config/db.php';
require '../includes/header.php';
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit();
}
$user_id = $_SESSION['user_id'];
$stmt = $conn->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $user_id);
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();
?>
<h2>Welcome, <?php echo $user['username']; ?></h2>
<p>Your role: <?php echo ucfirst($user['role']); ?></p>
<?php require '../includes/footer.php'; ?>
Create Quiz (public/create_quiz.php)
<?php
session_start();
require '../config/db.php';
require '../includes/header.php';
if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'quiz_creator') {
header("Location: login.php");
exit();
}
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$creator_id = $_SESSION['user_id'];
$title = $_POST['title'];
$description = $_POST['description'];
$time_limit = $_POST['time_limit'];
$stmt = $conn->prepare("INSERT INTO quizzes (creator_id, title, description, time_limit) VALUES (?, ?, ?, ?)");
$stmt->bind_param("issi", $creator_id, $title, $description, $time_limit);
$stmt->execute();
$stmt->close();
header("Location: dashboard.php");
}
?>
<form method="POST" action="">
<div class="mb-3">
<label for="title" class="form-label">Quiz Title</label>
<input type="text" class="form-control" id="title" name="title" required>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="description" rows="3"></textarea>
</div>
<div class="mb-3">
<label for="time_limit" class="form-label">Time Limit (in seconds)</label>
<input type="number" class="form-control" id="time_limit" name="time_limit" required>
</div>
<button type="submit" class="btn btn-primary">Create Quiz</button>
</form>
<?php require '../includes/footer.php'; ?>
Take Quiz (public/take_quiz.php)
<?php
session_start();
require '../config/db.php';
require '../includes/header.php';
if (!isset($_SESSION['user_id']) || !isset($_GET['quiz_id'])) {
header("Location: login.php");
exit();
}
$quiz_id = $_GET['quiz_id'];
$stmt = $conn->prepare("SELECT * FROM quizzes WHERE id = ?");
$stmt->bind_param("i", $quiz_id);
$stmt->execute();
$result = $stmt->get_result();
$quiz = $result->fetch_assoc();
$stmt = $conn->prepare("SELECT * FROM questions WHERE quiz_id = ?");
$stmt->bind_param("i", $quiz_id);
$stmt->execute();
$questions = $stmt->get_result();
?>
<h2><?php echo $quiz['title']; ?></h2>
<p><?php echo $quiz['description']; ?></p>
<form method="POST" action="quiz_results.php">
<input type="hidden" name="quiz_id" value="<?php echo $quiz_id; ?>">
<?php while ($question = $questions->fetch_assoc()): ?>
<div class="mb-3">
<label class="form-label"><?php echo $question['question_text']; ?></label>
<?php if ($question['question_type'] == 'multiple_choice'): ?>
<?php
$stmt = $conn->prepare("SELECT * FROM answer_options WHERE question_id = ?");
$stmt->bind_param("i", $question['id']);
$stmt->execute();
$options = $stmt->get_result();
while ($option = $options->fetch_assoc()): ?>
<div>
<input type="radio" name="answers[<?php echo $question['id']; ?>]" value="<?php echo $option['id']; ?>">
<?php echo $option['option_text']; ?>
</div>
<?php endwhile; ?>
<?php elseif ($question['question_type'] == 'true_false'): ?>
<div>
<input type="radio" name="answers[<?php echo $question['id ']; ?>]" value="true"> True
<input type="radio" name="answers[<?php echo $question['id']; ?>]" value="false"> False
</div>
<?php elseif ($question['question_type'] == 'short_answer'): ?>
<input type="text" class="form-control" name="answers[<?php echo $question['id']; ?>]">
<?php endif; ?>
</div>
<?php endwhile; ?>
<button type="submit" class="btn btn-primary">Submit Quiz</button>
</form>
<?php require '../includes/footer.php'; ?>
Quiz Results (public/quiz_results.php)
<?php
session_start();
require '../config/db.php';
require '../includes/header.php';
if (!isset($_SESSION['user_id']) || !isset($_POST['quiz_id'])) {
header("Location: login.php");
exit();
}
$quiz_id = $_POST['quiz_id'];
$user_id = $_SESSION['user_id'];
$score = 0;
foreach ($_POST['answers'] as $question_id => $answer_id) {
$stmt = $conn->prepare("SELECT * FROM questions WHERE id = ?");
$stmt->bind_param("i", $question_id);
$stmt->execute();
$question = $stmt->get_result()->fetch_assoc();
if ($question['question_type'] == 'multiple_choice') {
$stmt = $conn->prepare("SELECT * FROM answer_options WHERE id = ? AND is_correct = TRUE");
$stmt->bind_param("i", $answer_id);
$stmt->execute();
if ($stmt->get_result()->num_rows > 0) {
$score++;
}
} elseif ($question['question_type'] == 'true_false') {
$correct_answer = ($question['question_text'] == 'True') ? 'true' : 'false';
if ($answer_id == $correct_answer) {
$score++;
}
} elseif ($question['question_type'] == 'short_answer') {
// Implement logic for short answer grading if needed
}
}
$stmt = $conn->prepare("INSERT INTO quiz_attempts (quiz_id, user_id, score) VALUES (?, ?, ?)");
$stmt->bind_param("iid", $quiz_id, $user_id, $score);
$stmt->execute();
?>
<h2>Your Score: <?php echo $score; ?></h2>
<p>Thank you for taking the quiz!</p>
<?php require '../includes/footer.php'; ?>
Feedback (public/feedback.php)
<?php
session_start();
require '../config/db.php';
require '../includes/header.php';
if (!isset($_SESSION['user_id']) || !isset($_GET['quiz_id'])) {
header("Location: login.php");
exit();
}
$quiz_id = $_GET['quiz_id'];
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$user_id = $_SESSION['user_id'];
$comments = $_POST['comments'];
$stmt = $conn->prepare("INSERT INTO feedback (user_id, quiz_id, comments) VALUES (?, ?, ?)");
$stmt->bind_param("iis", $user_id, $quiz_id, $comments);
$stmt->execute();
$stmt->close();
header("Location: quiz_results.php?quiz_id=" . $quiz_id);
}
?>
<h2>Feedback for Quiz</h2>
<form method="POST" action="">
<div class="mb-3">
<label for="comments" class="form-label">Your Comments</label>
<textarea class="form-control" id="comments" name="comments" rows="3" required></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit Feedback</button>
</form>
<?php require '../includes/footer.php'; ?>
Notifications (public/notifications.php)
<?php
session_start();
require '../config/db.php';
require '../includes/header.php';
$user_id = $_SESSION['user_id'];
$stmt = $conn->prepare("SELECT * FROM notifications WHERE user_id = ? ORDER BY created_at DESC");
$stmt->bind_param("i", $user_id);
$stmt->execute();
$result = $stmt->get_result();
$notifications = $result->fetch_all(MYSQLI_ASSOC);
?>
<h3>Your Notifications</h3>
<ul class="list-group">
<?php foreach ($notifications as $notification): ?>
<li class="list-group-item <?php echo $notification['is_read'] ? 'list-group-item-secondary' : ''; ?>">
<?php echo $notification['message']; ?>
<small class="text-muted"><?php echo $notification['created_at']; ?></small>
</li>
<?php endforeach; ?>
</ul>
<?php require '../includes/footer.php'; ?>
Admin Dashboard (public/admin_dashboard.php)
<?php
session_start();
require '../config/db.php';
require '../includes/header.php';
if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'admin') {
header("Location: login.php");
exit();
}
$stmt = $conn->prepare("SELECT COUNT(*) AS user_count FROM users");
$stmt->execute();
$result = $stmt->get_result();
$user_count = $result->fetch_assoc()['user_count'];
$stmt = $conn->prepare("SELECT COUNT(*) AS quiz_count FROM quizzes");
$stmt->execute();
$result = $stmt->get_result();
$quiz_count = $result->fetch_assoc()['quiz_count'];
$stmt = $conn->prepare("SELECT COUNT(*) AS feedback_count FROM feedback");
$stmt->execute();
$result = $stmt->get_result();
$feedback_count = $result->fetch_assoc()['feedback_count'];
?>
<h2>Admin Dashboard</h2>
<p>Total Users: <?php echo $user_count; ?></p>
<p>Total Quizzes: <?php echo $quiz_count; ?></p>
<p>Total Feedback: <?php echo $feedback_count; ?></p>
<?php require '../includes/footer.php'; ?>
6. Additional Features to Consider
User Profiles: Allow users to edit their profiles and manage their settings.
Quiz Scheduling: Implement functionality for quiz creators to schedule quizzes for future dates.
Advanced Feedback System: Enhance feedback management with features for flagging inappropriate comments.
Analytics Dashboard: Provide quiz creators with insights into quiz performance and user engagement.
7. Security Measures
Data Validation: Ensure all user inputs are validated to prevent SQL injection and XSS attacks.
Password Security: Use strong hashing algorithms for storing passwords.
Session Security: Implement secure session management practices to protect user sessions.
8. Testing and Deployment
Unit Testing: Conduct unit tests for individual components to ensure they function correctly.
Integration Testing: Test the integration of different modules to ensure they work together seamlessly.
Deployment: Choose a reliable hosting provider and deploy the application, ensuring all configurations are optimized for performance.
9. Documentation
User Documentation: Create a user manual to guide users through the platform's features and functionalities.
Developer Documentation: Document the codebase and architecture for future reference and maintenance.
10. Future Enhancements
Mobile Application: Develop a mobile application for users to access the platform on the go.
Community Features: Create forums or discussion boards for users to share insights and strategies.
AI-Powered Recommendations: Implement machine learning algorithms to provide personalized quiz recommendations.
This structured approach will help you build a comprehensive Online Quiz Platform that meets user needs and adapts to future requirements.