Online Course Management System built with HTML, CSS, JavaScript, PHP, and MySQL.

📚 Project Introduction: Online Course Management System

This project is a comprehensive Online Course Management System (LMS - Learning Management System) designed for educational institutions, trainers, and content creators to deliver online courses. It provides a complete platform for course creation, student enrollment, lesson delivery, and progress tracking.

The Problem it Solves:
Traditional education delivery is limited by physical constraints and scheduling conflicts. This digital platform enables scalable, accessible learning where students can learn at their own pace, from anywhere, while instructors can reach a global audience without geographical limitations.

Key Features:

  • Student Features:
  • Browse available courses by category
  • View course details (description, syllabus, instructor, duration)
  • Enroll in courses (free or paid)
  • Access course lessons and materials
  • Track learning progress
  • Mark lessons as completed
  • Download course certificates upon completion
  • Leave reviews and ratings
  • Bookmark favorite courses
  • Discussion forums per course
  • Instructor Features:
  • Create and manage courses
  • Upload lessons (video, PDF, presentations)
  • Organize content into modules/sections
  • Track student enrollment and progress
  • Respond to student questions
  • View earnings (if paid courses)
  • Analytics dashboard
  • Admin Features:
  • Manage users (students, instructors, admins)
  • Approve/reject courses
  • Manage categories
  • Process instructor applications
  • View platform statistics
  • Manage payments and commissions
  • Site settings configuration

Technology Stack:

  • Frontend: HTML5, CSS3, JavaScript (Fetch API, Video.js for video playback)
  • Backend: PHP (Object-Oriented PHP with PDO)
  • Database: MySQL
  • Additional Libraries:
  • Video.js (Video player)
  • FPDF (Certificate generation)
  • PHPMailer (Email notifications)
  • Stripe/PayPal API (Payment processing)

📁 Project File Structure

online-course-system/
│
├── index.php                 # Homepage - Course listings
├── courses.php               # All courses page
├── course-details.php        # Single course details
├── course-content.php        # Course lessons player
├── my-courses.php            # Student enrolled courses
├── my-learning.php           # Student learning progress
├── instructors.php           # Instructors listing
├── instructor-profile.php    # Instructor profile page
├── login.php                 # User login
├── register.php              # User registration
├── logout.php                # Logout script
│
├── instructor/               # Instructor Panel
│   ├── dashboard.php         # Instructor dashboard
│   ├── courses.php           # Manage courses
│   ├── add-course.php        # Create new course
│   ├── edit-course.php       # Edit course
│   ├── lessons.php           # Manage lessons
│   ├── add-lesson.php        # Add lesson
│   ├── edit-lesson.php       # Edit lesson
│   ├── students.php          # View enrolled students
│   ├── earnings.php          # View earnings
│   ├── profile.php           # Instructor profile
│   └── logout.php            # Instructor logout
│
├── admin/                    # Admin Panel
│   ├── index.php             # Admin login
│   ├── dashboard.php         # Admin dashboard
│   ├── users.php             # Manage users
│   ├── courses.php           # Manage courses
│   ├── categories.php        # Manage categories
│   ├── instructor-applications.php # Approve instructors
│   ├── payments.php          # Manage payments
│   ├── settings.php          # Site settings
│   └── logout.php            # Admin logout
│
├── includes/                  # Backend logic
│   ├── config.php             # Database connection
│   ├── functions.php          # Helper functions
│   ├── auth.php               # Authentication functions
│   ├── session.php            # Session management
│   └── mailer.php             # Email functions
│
├── api/                        # AJAX endpoints
│   ├── enroll.php              # Course enrollment
│   ├── mark-completed.php      # Mark lesson completed
│   ├── get-progress.php        # Get course progress
│   ├── add-review.php          # Add course review
│   └── search-courses.php      # Course search
│
├── assets/                    # Static assets
│   ├── css/
│   │   ├── style.css          # Main styles
│   │   └── admin.css          # Admin styles
│   ├── js/
│   │   ├── main.js            # Main JavaScript
│   │   ├── player.js          # Video player
│   │   └── progress.js        # Progress tracking
│   ├── images/
│   │   ├── courses/           # Course thumbnails
│   │   ├── instructors/       # Instructor photos
│   │   └── certificates/      # Generated certificates
│   └── vendor/                 # Third-party libraries
│       ├── video.js/           # Video player
│       └── fpdf/               # PDF generator
│
├── uploads/                    # Uploaded files
│   ├── lessons/                # Video lessons
│   ├── materials/              # Course materials (PDF, etc.)
│   └── temp/                   # Temporary files
│
└── database/
└── course_system.sql       # Database dump

🗄️ Database Setup (database/course_system.sql)

Create a database named course_system and run this SQL.

-- phpMyAdmin SQL Dump
-- Database: `course_system`
CREATE DATABASE IF NOT EXISTS `course_system`;
USE `course_system`;
-- --------------------------------------------------------
-- Table structure for table `users`
-- --------------------------------------------------------
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`email` varchar(100) NOT NULL,
`password` varchar(255) NOT NULL,
`full_name` varchar(100) NOT NULL,
`bio` text DEFAULT NULL,
`avatar` varchar(255) DEFAULT 'default-avatar.png',
`role` enum('student','instructor','admin') DEFAULT 'student',
`instructor_status` enum('pending','approved','rejected') DEFAULT NULL,
`qualifications` text DEFAULT NULL,
`expertise` varchar(255) DEFAULT NULL,
`social_links` text DEFAULT NULL,
`status` enum('active','inactive','banned') DEFAULT 'active',
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
`last_login` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Default admin (password: admin123)
INSERT INTO `users` (`username`, `email`, `password`, `full_name`, `role`) VALUES
('admin', '[email protected]', '$2y$10$YourHashedPasswordHere', 'Administrator', 'admin');
-- Sample instructor (password: instructor123)
INSERT INTO `users` (`username`, `email`, `password`, `full_name`, `role`, `instructor_status`, `qualifications`, `expertise`) VALUES
('john.doe', '[email protected]', '$2y$10$YourHashedPasswordHere', 'John Doe', 'instructor', 'approved', 'PhD in Computer Science, 10+ years teaching experience', 'Web Development, Database Systems, Algorithms');
-- Sample student (password: student123)
INSERT INTO `users` (`username`, `email`, `password`, `full_name`, `role`) VALUES
('jane.smith', '[email protected]', '$2y$10$YourHashedPasswordHere', 'Jane Smith', 'student');
-- --------------------------------------------------------
-- Table structure for table `categories`
-- --------------------------------------------------------
CREATE TABLE `categories` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`slug` varchar(100) NOT NULL,
`description` text DEFAULT NULL,
`icon` varchar(50) DEFAULT NULL,
`parent_id` int(11) DEFAULT NULL,
`status` enum('active','inactive') DEFAULT 'active',
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
UNIQUE KEY `slug` (`slug`),
KEY `parent_id` (`parent_id`),
CONSTRAINT `categories_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `categories` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Sample categories
INSERT INTO `categories` (`name`, `slug`, `description`, `icon`) VALUES
('Web Development', 'web-development', 'Learn HTML, CSS, JavaScript, and modern frameworks', '🌐'),
('Data Science', 'data-science', 'Python, Machine Learning, Data Analysis, AI', '📊'),
('Mobile Development', 'mobile-development', 'iOS, Android, React Native, Flutter', '📱'),
('Business', 'business', 'Entrepreneurship, Marketing, Management', '💼'),
('Design', 'design', 'UI/UX, Graphic Design, Adobe Creative Suite', '🎨'),
('Photography', 'photography', 'Digital Photography, Editing, Composition', '📷');
-- --------------------------------------------------------
-- Table structure for table `courses`
-- --------------------------------------------------------
CREATE TABLE `courses` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(200) NOT NULL,
`slug` varchar(200) NOT NULL,
`description` longtext NOT NULL,
`short_description` varchar(500) DEFAULT NULL,
`category_id` int(11) NOT NULL,
`instructor_id` int(11) NOT NULL,
`level` enum('beginner','intermediate','advanced','all-levels') DEFAULT 'beginner',
`language` varchar(50) DEFAULT 'English',
`thumbnail` varchar(255) DEFAULT NULL,
`promo_video` varchar(255) DEFAULT NULL,
`price` decimal(10,2) DEFAULT 0.00,
`discount_price` decimal(10,2) DEFAULT NULL,
`duration_hours` int(11) DEFAULT NULL,
`lessons_count` int(11) DEFAULT 0,
`students_count` int(11) DEFAULT 0,
`rating` decimal(3,2) DEFAULT 0.00,
`reviews_count` int(11) DEFAULT 0,
`requirements` text DEFAULT NULL,
`what_you_learn` text DEFAULT NULL,
`target_audience` text DEFAULT NULL,
`status` enum('draft','pending','published','rejected','archived') DEFAULT 'draft',
`is_featured` tinyint(1) DEFAULT 0,
`is_free` tinyint(1) DEFAULT 0,
`certificate_available` tinyint(1) DEFAULT 1,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
`updated_at` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp(),
`published_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `slug` (`slug`),
KEY `category_id` (`category_id`),
KEY `instructor_id` (`instructor_id`),
KEY `status` (`status`),
FULLTEXT KEY `search` (`title`,`description`,`short_description`),
CONSTRAINT `courses_ibfk_1` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ON DELETE CASCADE,
CONSTRAINT `courses_ibfk_2` FOREIGN KEY (`instructor_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Sample course
INSERT INTO `courses` (`title`, `slug`, `description`, `short_description`, `category_id`, `instructor_id`, `level`, `price`, `duration_hours`, `lessons_count`, `students_count`, `rating`, `status`, `is_featured`) VALUES
('Complete Web Development Bootcamp', 'complete-web-development-bootcamp', '<p>This comprehensive course covers everything you need to become a professional web developer. From HTML and CSS basics to advanced JavaScript frameworks and backend development with Node.js.</p><p>You''ll build real-world projects including e-commerce sites, social media clones, and portfolio websites. By the end, you''ll have the skills to land your first developer job.</p>', 'Master HTML, CSS, JavaScript, React, Node.js and become a full-stack web developer', 1, 2, 'beginner', 89.99, 40, 150, 1234, 4.8, 'published', 1);
-- --------------------------------------------------------
-- Table structure for table `course_sections`
-- --------------------------------------------------------
CREATE TABLE `course_sections` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`course_id` int(11) NOT NULL,
`title` varchar(200) NOT NULL,
`description` text DEFAULT NULL,
`order_position` int(11) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
KEY `course_id` (`course_id`),
CONSTRAINT `course_sections_ibfk_1` FOREIGN KEY (`course_id`) REFERENCES `courses` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- --------------------------------------------------------
-- Table structure for table `lessons`
-- --------------------------------------------------------
CREATE TABLE `lessons` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`section_id` int(11) NOT NULL,
`title` varchar(200) NOT NULL,
`description` text DEFAULT NULL,
`content_type` enum('video','pdf','text','quiz','assignment') DEFAULT 'video',
`video_url` varchar(255) DEFAULT NULL,
`video_duration` int(11) DEFAULT NULL COMMENT 'in seconds',
`file_path` varchar(255) DEFAULT NULL,
`text_content` longtext DEFAULT NULL,
`is_preview` tinyint(1) DEFAULT 0,
`order_position` int(11) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
KEY `section_id` (`section_id`),
CONSTRAINT `lessons_ibfk_1` FOREIGN KEY (`section_id`) REFERENCES `course_sections` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- --------------------------------------------------------
-- Table structure for table `enrollments`
-- --------------------------------------------------------
CREATE TABLE `enrollments` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`course_id` int(11) NOT NULL,
`progress` int(11) DEFAULT 0 COMMENT 'percentage',
`completed_lessons` int(11) DEFAULT 0,
`total_lessons` int(11) DEFAULT 0,
`last_accessed` timestamp NULL DEFAULT NULL,
`completed_at` timestamp NULL DEFAULT NULL,
`certificate_issued` tinyint(1) DEFAULT 0,
`certificate_code` varchar(100) DEFAULT NULL,
`enrolled_at` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
UNIQUE KEY `unique_enrollment` (`user_id`,`course_id`),
KEY `course_id` (`course_id`),
CONSTRAINT `enrollments_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
CONSTRAINT `enrollments_ibfk_2` FOREIGN KEY (`course_id`) REFERENCES `courses` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- --------------------------------------------------------
-- Table structure for table `lesson_progress`
-- --------------------------------------------------------
CREATE TABLE `lesson_progress` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`lesson_id` int(11) NOT NULL,
`course_id` int(11) NOT NULL,
`completed` tinyint(1) DEFAULT 0,
`completed_at` timestamp NULL DEFAULT NULL,
`last_position` int(11) DEFAULT NULL COMMENT 'video position in seconds',
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
UNIQUE KEY `unique_progress` (`user_id`,`lesson_id`),
KEY `lesson_id` (`lesson_id`),
KEY `course_id` (`course_id`),
CONSTRAINT `lesson_progress_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
CONSTRAINT `lesson_progress_ibfk_2` FOREIGN KEY (`lesson_id`) REFERENCES `lessons` (`id`) ON DELETE CASCADE,
CONSTRAINT `lesson_progress_ibfk_3` FOREIGN KEY (`course_id`) REFERENCES `courses` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- --------------------------------------------------------
-- Table structure for table `reviews`
-- --------------------------------------------------------
CREATE TABLE `reviews` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`course_id` int(11) NOT NULL,
`rating` int(1) NOT NULL,
`review` text DEFAULT NULL,
`status` enum('pending','approved','rejected') DEFAULT 'pending',
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
UNIQUE KEY `unique_review` (`user_id`,`course_id`),
KEY `course_id` (`course_id`),
CONSTRAINT `reviews_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
CONSTRAINT `reviews_ibfk_2` FOREIGN KEY (`course_id`) REFERENCES `courses` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- --------------------------------------------------------
-- Table structure for table `payments`
-- --------------------------------------------------------
CREATE TABLE `payments` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`course_id` int(11) NOT NULL,
`amount` decimal(10,2) NOT NULL,
`payment_method` enum('paypal','stripe','bank','wallet') DEFAULT NULL,
`transaction_id` varchar(100) DEFAULT NULL,
`status` enum('pending','completed','failed','refunded') DEFAULT 'pending',
`commission_amount` decimal(10,2) DEFAULT NULL,
`instructor_earning` decimal(10,2) DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `course_id` (`course_id`),
CONSTRAINT `payments_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
CONSTRAINT `payments_ibfk_2` FOREIGN KEY (`course_id`) REFERENCES `courses` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- --------------------------------------------------------
-- Table structure for table `wishlist`
-- --------------------------------------------------------
CREATE TABLE `wishlist` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`course_id` int(11) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
UNIQUE KEY `unique_wishlist` (`user_id`,`course_id`),
KEY `course_id` (`course_id`),
CONSTRAINT `wishlist_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
CONSTRAINT `wishlist_ibfk_2` FOREIGN KEY (`course_id`) REFERENCES `courses` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- --------------------------------------------------------
-- Table structure for table `discussions`
-- --------------------------------------------------------
CREATE TABLE `discussions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`course_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`title` varchar(255) NOT NULL,
`content` text NOT NULL,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
KEY `course_id` (`course_id`),
KEY `user_id` (`user_id`),
CONSTRAINT `discussions_ibfk_1` FOREIGN KEY (`course_id`) REFERENCES `courses` (`id`) ON DELETE CASCADE,
CONSTRAINT `discussions_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- --------------------------------------------------------
-- Table structure for table `discussion_replies`
-- --------------------------------------------------------
CREATE TABLE `discussion_replies` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`discussion_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`content` text NOT NULL,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
KEY `discussion_id` (`discussion_id`),
KEY `user_id` (`user_id`),
CONSTRAINT `discussion_replies_ibfk_1` FOREIGN KEY (`discussion_id`) REFERENCES `discussions` (`id`) ON DELETE CASCADE,
CONSTRAINT `discussion_replies_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- --------------------------------------------------------
-- Table structure for table `settings`
-- --------------------------------------------------------
CREATE TABLE `settings` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`setting_key` varchar(100) NOT NULL,
`setting_value` text DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `setting_key` (`setting_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Default settings
INSERT INTO `settings` (`setting_key`, `setting_value`) VALUES
('site_title', 'Online Course System'),
('site_description', 'Learn Anything, Anytime, Anywhere'),
('site_logo', 'logo.png'),
('contact_email', '[email protected]'),
('commission_rate', '20'), -- 20% platform commission
('currency', 'USD'),
('instructor_application', '1'), -- Allow instructor applications
('certificate_enabled', '1');
COMMIT;

💻 Core PHP Files

1. Database Configuration (includes/config.php)

<?php
// Database configuration
define('DB_HOST', 'localhost');
define('DB_NAME', 'course_system');
define('DB_USER', 'root');
define('DB_PASS', '');
try {
$pdo = new PDO(
"mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8mb4",
DB_USER,
DB_PASS,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]
);
} catch (PDOException $e) {
die("Connection failed: " . $e->getMessage());
}
// Start session if not started
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
// Load settings
$settings = [];
$stmt = $pdo->query("SELECT setting_key, setting_value FROM settings");
while ($row = $stmt->fetch()) {
$settings[$row['setting_key']] = $row['setting_value'];
}
// Site configuration
define('SITE_NAME', $settings['site_title'] ?? 'Online Course System');
define('SITE_URL', 'http://localhost/online-course-system/');
define('CONTACT_EMAIL', $settings['contact_email'] ?? '[email protected]');
define('COMMISSION_RATE', $settings['commission_rate'] ?? 20);
define('CURRENCY', $settings['currency'] ?? 'USD');
define('UPLOAD_PATH', __DIR__ . '/../uploads/');
// Helper functions
function sanitize($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
function redirect($url) {
header("Location: $url");
exit;
}
function isLoggedIn() {
return isset($_SESSION['user_id']);
}
function isInstructor() {
return isset($_SESSION['user_role']) && $_SESSION['user_role'] === 'instructor';
}
function isAdmin() {
return isset($_SESSION['user_role']) && $_SESSION['user_role'] === 'admin';
}
function formatDate($date, $format = 'M d, Y') {
return date($format, strtotime($date));
}
function formatCurrency($amount) {
$symbol = CURRENCY == 'USD' ? '$' : (CURRENCY == 'EUR' ? '€' : '£');
return $symbol . number_format($amount, 2);
}
function timeAgo($timestamp) {
$time_ago = strtotime($timestamp);
$current_time = time();
$time_difference = $current_time - $time_ago;
$seconds = $time_difference;
$minutes = round($seconds / 60);
$hours = round($seconds / 3600);
$days = round($seconds / 86400);
$weeks = round($seconds / 604800);
$months = round($seconds / 2629440);
$years = round($seconds / 31553280);
if ($seconds <= 60) {
return "Just now";
} else if ($minutes <= 60) {
return ($minutes == 1) ? "1 minute ago" : "$minutes minutes ago";
} else if ($hours <= 24) {
return ($hours == 1) ? "1 hour ago" : "$hours hours ago";
} else if ($days <= 7) {
return ($days == 1) ? "yesterday" : "$days days ago";
} else if ($weeks <= 4.3) {
return ($weeks == 1) ? "1 week ago" : "$weeks weeks ago";
} else if ($months <= 12) {
return ($months == 1) ? "1 month ago" : "$months months ago";
} else {
return ($years == 1) ? "1 year ago" : "$years years ago";
}
}
function createSlug($string) {
$string = strtolower($string);
$string = preg_replace('/[^a-z0-9-]/', '-', $string);
$string = preg_replace('/-+/', '-', $string);
return trim($string, '-');
}
function getInitials($name) {
$words = explode(' ', $name);
$initials = '';
foreach ($words as $word) {
$initials .= strtoupper(substr($word, 0, 1));
}
return substr($initials, 0, 2);
}
function calculateProgress($completed, $total) {
if ($total == 0) return 0;
return round(($completed / $total) * 100);
}
function getUserById($id) {
global $pdo;
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);
return $stmt->fetch();
}
function getCourseProgress($user_id, $course_id) {
global $pdo;
// Get total lessons in course
$total = $pdo->prepare("
SELECT COUNT(*) FROM lessons l
JOIN course_sections cs ON l.section_id = cs.id
WHERE cs.course_id = ?
");
$total->execute([$course_id]);
$total_lessons = $total->fetchColumn();
// Get completed lessons
$completed = $pdo->prepare("
SELECT COUNT(*) FROM lesson_progress
WHERE user_id = ? AND course_id = ? AND completed = 1
");
$completed->execute([$user_id, $course_id]);
$completed_lessons = $completed->fetchColumn();
return [
'total' => $total_lessons,
'completed' => $completed_lessons,
'percentage' => calculateProgress($completed_lessons, $total_lessons)
];
}
function sendEmail($to, $subject, $message) {
// Use PHPMailer for production
$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";
$headers .= "From: " . SITE_NAME . " <noreply@" . $_SERVER['HTTP_HOST'] . ">\r\n";
return mail($to, $subject, $message, $headers);
}
?>

2. Authentication Functions (includes/auth.php)

<?php
require_once 'config.php';
class Auth {
public static function login($email, $password) {
global $pdo;
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password'])) {
if ($user['status'] != 'active') {
return ['success' => false, 'message' => 'Your account is not active. Please contact support.'];
}
$_SESSION['user_id'] = $user['id'];
$_SESSION['user_name'] = $user['full_name'];
$_SESSION['user_email'] = $user['email'];
$_SESSION['user_role'] = $user['role'];
$_SESSION['user_avatar'] = $user['avatar'];
// Update last login
$pdo->prepare("UPDATE users SET last_login = NOW() WHERE id = ?")->execute([$user['id']]);
return ['success' => true, 'role' => $user['role']];
}
return ['success' => false, 'message' => 'Invalid email or password'];
}
public static function register($data) {
global $pdo;
// Check if email exists
$stmt = $pdo->prepare("SELECT id FROM users WHERE email = ?");
$stmt->execute([$data['email']]);
if ($stmt->fetch()) {
return ['success' => false, 'message' => 'Email already registered'];
}
// Check if username exists
$stmt = $pdo->prepare("SELECT id FROM users WHERE username = ?");
$stmt->execute([$data['username']]);
if ($stmt->fetch()) {
return ['success' => false, 'message' => 'Username already taken'];
}
// Hash password
$hashedPassword = password_hash($data['password'], PASSWORD_DEFAULT);
// Insert user
$stmt = $pdo->prepare("
INSERT INTO users (username, email, password, full_name, role) 
VALUES (?, ?, ?, ?, 'student')
");
$success = $stmt->execute([
$data['username'],
$data['email'],
$hashedPassword,
$data['full_name']
]);
if ($success) {
// Send welcome email
$subject = "Welcome to " . SITE_NAME;
$message = "
<h1>Welcome to " . SITE_NAME . "!</h1>
<p>Dear {$data['full_name']},</p>
<p>Thank you for registering. You can now browse and enroll in courses.</p>
<p><a href='" . SITE_URL . "login.php'>Click here to login</a></p>
";
sendEmail($data['email'], $subject, $message);
return ['success' => true, 'message' => 'Registration successful! Please login.'];
}
return ['success' => false, 'message' => 'Registration failed. Please try again.'];
}
public static function applyInstructor($data) {
global $pdo;
if (!isset($_SESSION['user_id'])) {
return ['success' => false, 'message' => 'Please login first'];
}
$stmt = $pdo->prepare("
UPDATE users 
SET instructor_status = 'pending', qualifications = ?, expertise = ?, social_links = ?
WHERE id = ?
");
$success = $stmt->execute([
$data['qualifications'],
$data['expertise'],
json_encode($data['social_links']),
$_SESSION['user_id']
]);
if ($success) {
// Notify admin
$subject = "New Instructor Application";
$message = "A user has applied to become an instructor. Please review their application in the admin panel.";
sendEmail(CONTACT_EMAIL, $subject, $message);
return ['success' => true, 'message' => 'Application submitted successfully! We will review it shortly.'];
}
return ['success' => false, 'message' => 'Application failed. Please try again.'];
}
public static function logout() {
session_destroy();
redirect('login.php');
}
public static function checkLogin() {
if (!isset($_SESSION['user_id'])) {
redirect('login.php');
}
}
public static function checkInstructor() {
self::checkLogin();
if ($_SESSION['user_role'] !== 'instructor') {
redirect('../index.php');
}
}
public static function checkAdmin() {
self::checkLogin();
if ($_SESSION['user_role'] !== 'admin') {
redirect('../index.php');
}
}
public static function getCurrentUser() {
global $pdo;
if (!isset($_SESSION['user_id'])) {
return null;
}
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
return $stmt->fetch();
}
}
?>

3. Homepage - Course Listings (index.php)

<?php
require_once 'includes/config.php';
// Get featured courses
$featured_courses = $pdo->query("
SELECT c.*, u.full_name as instructor_name, cat.name as category_name, cat.slug as category_slug
FROM courses c
JOIN users u ON c.instructor_id = u.id
JOIN categories cat ON c.category_id = cat.id
WHERE c.status = 'published' AND c.is_featured = 1
ORDER BY c.created_at DESC
LIMIT 6
")->fetchAll();
// Get latest courses
$latest_courses = $pdo->query("
SELECT c.*, u.full_name as instructor_name, cat.name as category_name, cat.slug as category_slug
FROM courses c
JOIN users u ON c.instructor_id = u.id
JOIN categories cat ON c.category_id = cat.id
WHERE c.status = 'published'
ORDER BY c.created_at DESC
LIMIT 8
")->fetchAll();
// Get popular courses (by students count)
$popular_courses = $pdo->query("
SELECT c.*, u.full_name as instructor_name, cat.name as category_name, cat.slug as category_slug
FROM courses c
JOIN users u ON c.instructor_id = u.id
JOIN categories cat ON c.category_id = cat.id
WHERE c.status = 'published'
ORDER BY c.students_count DESC
LIMIT 4
")->fetchAll();
// Get categories for navigation
$categories = $pdo->query("
SELECT * FROM categories 
WHERE status = 'active' AND parent_id IS NULL
ORDER BY name
")->fetchAll();
// Get statistics
$total_courses = $pdo->query("SELECT COUNT(*) FROM courses WHERE status = 'published'")->fetchColumn();
$total_students = $pdo->query("SELECT COUNT(DISTINCT user_id) FROM enrollments")->fetchColumn();
$total_instructors = $pdo->query("SELECT COUNT(*) FROM users WHERE role = 'instructor' AND instructor_status = 'approved'")->fetchColumn();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo SITE_NAME; ?> - Learn Anything, Anytime, Anywhere</title>
<meta name="description" content="Discover thousands of online courses taught by expert instructors. Learn at your own pace with lifetime access.">
<link rel="stylesheet" href="assets/css/style.css">
</head>
<body>
<!-- Header -->
<header class="site-header">
<div class="top-header">
<div class="container">
<div class="header-left">
<span class="welcome-message">Welcome to <?php echo SITE_NAME; ?></span>
</div>
<div class="header-right">
<?php if (isLoggedIn()): ?>
<span>Hello, <?php echo $_SESSION['user_name']; ?></span>
<a href="my-courses.php">My Courses</a>
<a href="my-learning.php">My Learning</a>
<?php if (isInstructor()): ?>
<a href="instructor/dashboard.php">Instructor Dashboard</a>
<?php endif; ?>
<?php if (isAdmin()): ?>
<a href="admin/dashboard.php">Admin</a>
<?php endif; ?>
<a href="logout.php">Logout</a>
<?php else: ?>
<a href="login.php">Login</a>
<a href="register.php" class="btn-register">Sign Up</a>
<?php endif; ?>
</div>
</div>
</div>
<div class="main-header">
<div class="container">
<div class="logo">
<a href="index.php">
<h1><?php echo SITE_NAME; ?></h1>
</a>
</div>
<nav class="main-nav">
<ul>
<li><a href="index.php" class="active">Home</a></li>
<li><a href="courses.php">All Courses</a></li>
<li class="dropdown">
<a href="#">Categories</a>
<ul class="dropdown-menu">
<?php foreach ($categories as $cat): ?>
<li><a href="courses.php?category=<?php echo $cat['slug']; ?>"><?php echo $cat['name']; ?></a></li>
<?php endforeach; ?>
</ul>
</li>
<li><a href="instructors.php">Instructors</a></li>
</ul>
</nav>
<div class="search-bar">
<form action="courses.php" method="GET">
<input type="text" name="search" placeholder="Search for courses...">
<button type="submit">🔍</button>
</form>
</div>
</div>
</div>
</header>
<!-- Hero Section -->
<section class="hero">
<div class="container">
<div class="hero-content">
<h1>Learn Anything, Anytime, Anywhere</h1>
<p>Access thousands of expert-led courses and take your skills to the next level. Learn at your own pace with lifetime access.</p>
<div class="hero-stats">
<div class="stat-item">
<span class="stat-number"><?php echo number_format($total_courses); ?>+</span>
<span class="stat-label">Courses</span>
</div>
<div class="stat-item">
<span class="stat-number"><?php echo number_format($total_students); ?>+</span>
<span class="stat-label">Students</span>
</div>
<div class="stat-item">
<span class="stat-number"><?php echo number_format($total_instructors); ?>+</span>
<span class="stat-label">Instructors</span>
</div>
</div>
<div class="hero-actions">
<a href="courses.php" class="btn btn-large btn-primary">Browse Courses</a>
<?php if (!isLoggedIn()): ?>
<a href="register.php" class="btn btn-large">Start Learning Free</a>
<?php endif; ?>
</div>
</div>
</div>
</section>
<!-- Featured Courses -->
<?php if (!empty($featured_courses)): ?>
<section class="featured-courses">
<div class="container">
<div class="section-header">
<h2 class="section-title">Featured Courses</h2>
<a href="courses.php?filter=featured" class="view-all">View All →</a>
</div>
<div class="course-grid">
<?php foreach ($featured_courses as $course): ?>
<div class="course-card">
<div class="course-image">
<a href="course-details.php?slug=<?php echo $course['slug']; ?>">
<img src="assets/images/courses/<?php echo $course['thumbnail'] ?: 'default-course.jpg'; ?>" 
alt="<?php echo $course['title']; ?>">
</a>
<?php if ($course['is_free']): ?>
<span class="course-badge free">Free</span>
<?php elseif ($course['discount_price']): ?>
<span class="course-badge sale">Sale</span>
<?php endif; ?>
</div>
<div class="course-content">
<div class="course-category">
<a href="courses.php?category=<?php echo $course['category_slug']; ?>">
<?php echo $course['category_name']; ?>
</a>
</div>
<h3 class="course-title">
<a href="course-details.php?slug=<?php echo $course['slug']; ?>">
<?php echo $course['title']; ?>
</a>
</h3>
<div class="course-instructor">
by <a href="instructor-profile.php?id=<?php echo $course['instructor_id']; ?>">
<?php echo $course['instructor_name']; ?>
</a>
</div>
<div class="course-meta">
<span class="course-rating">
★ <?php echo number_format($course['rating'], 1); ?>
(<?php echo $course['reviews_count']; ?>)
</span>
<span class="course-students">
👥 <?php echo number_format($course['students_count']); ?>
</span>
<span class="course-duration">
⏱️ <?php echo $course['duration_hours']; ?>h
</span>
</div>
<div class="course-price">
<?php if ($course['is_free']): ?>
<span class="price-free">Free</span>
<?php elseif ($course['discount_price']): ?>
<span class="price-old"><?php echo formatCurrency($course['price']); ?></span>
<span class="price-current"><?php echo formatCurrency($course['discount_price']); ?></span>
<?php else: ?>
<span class="price-current"><?php echo formatCurrency($course['price']); ?></span>
<?php endif; ?>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
</section>
<?php endif; ?>
<!-- Categories Section -->
<section class="categories-section">
<div class="container">
<h2 class="section-title">Browse by Category</h2>
<div class="categories-grid">
<?php foreach ($categories as $category): ?>
<a href="courses.php?category=<?php echo $category['slug']; ?>" class="category-card">
<span class="category-icon"><?php echo $category['icon']; ?></span>
<h3 class="category-name"><?php echo $category['name']; ?></h3>
<span class="category-count">
<?php
$count = $pdo->prepare("SELECT COUNT(*) FROM courses WHERE category_id = ? AND status = 'published'");
$count->execute([$category['id']]);
echo $count->fetchColumn() . ' courses';
?>
</span>
</a>
<?php endforeach; ?>
</div>
</div>
</section>
<!-- Latest Courses -->
<section class="latest-courses">
<div class="container">
<div class="section-header">
<h2 class="section-title">New & Trending</h2>
<a href="courses.php" class="view-all">View All →</a>
</div>
<div class="course-grid">
<?php foreach ($latest_courses as $course): ?>
<div class="course-card">
<div class="course-image">
<a href="course-details.php?slug=<?php echo $course['slug']; ?>">
<img src="assets/images/courses/<?php echo $course['thumbnail'] ?: 'default-course.jpg'; ?>" 
alt="<?php echo $course['title']; ?>">
</a>
</div>
<div class="course-content">
<div class="course-category">
<a href="courses.php?category=<?php echo $course['category_slug']; ?>">
<?php echo $course['category_name']; ?>
</a>
</div>
<h3 class="course-title">
<a href="course-details.php?slug=<?php echo $course['slug']; ?>">
<?php echo $course['title']; ?>
</a>
</h3>
<div class="course-instructor">
by <?php echo $course['instructor_name']; ?>
</div>
<div class="course-meta">
<span class="course-rating">
★ <?php echo number_format($course['rating'], 1); ?>
</span>
<span class="course-students">
👥 <?php echo number_format($course['students_count']); ?>
</span>
</div>
<div class="course-price">
<?php if ($course['is_free']): ?>
<span class="price-free">Free</span>
<?php else: ?>
<span class="price-current"><?php echo formatCurrency($course['price']); ?></span>
<?php endif; ?>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
</section>
<!-- Testimonials / Stats -->
<section class="stats-section">
<div class="container">
<div class="stats-grid">
<div class="stat-box">
<span class="stat-value">50K+</span>
<span class="stat-label">Happy Students</span>
</div>
<div class="stat-box">
<span class="stat-value">1000+</span>
<span class="stat-label">Expert Courses</span>
</div>
<div class="stat-box">
<span class="stat-value">200+</span>
<span class="stat-label">Expert Instructors</span>
</div>
<div class="stat-box">
<span class="stat-value">24/7</span>
<span class="stat-label">Lifetime Access</span>
</div>
</div>
</div>
</section>
<!-- Become Instructor CTA -->
<section class="cta-section">
<div class="container">
<div class="cta-content">
<h2>Share Your Knowledge</h2>
<p>Become an instructor and reach millions of students worldwide. Create your own course today.</p>
<?php if (isLoggedIn()): ?>
<a href="become-instructor.php" class="btn btn-large btn-primary">Apply as Instructor</a>
<?php else: ?>
<a href="register.php?role=instructor" class="btn btn-large btn-primary">Start Teaching</a>
<?php endif; ?>
</div>
</div>
</section>
<!-- Footer -->
<footer class="site-footer">
<div class="container">
<div class="footer-widgets">
<div class="footer-widget">
<h4>About Us</h4>
<p><?php echo SITE_NAME; ?> is a leading online learning platform offering thousands of courses across various categories.</p>
</div>
<div class="footer-widget">
<h4>Quick Links</h4>
<ul>
<li><a href="about.php">About Us</a></li>
<li><a href="contact.php">Contact</a></li>
<li><a href="faq.php">FAQ</a></li>
<li><a href="terms.php">Terms of Use</a></li>
<li><a href="privacy.php">Privacy Policy</a></li>
</ul>
</div>
<div class="footer-widget">
<h4>Categories</h4>
<ul>
<?php foreach (array_slice($categories, 0, 5) as $cat): ?>
<li><a href="courses.php?category=<?php echo $cat['slug']; ?>"><?php echo $cat['name']; ?></a></li>
<?php endforeach; ?>
</ul>
</div>
<div class="footer-widget">
<h4>Follow Us</h4>
<div class="social-links">
<a href="#" target="_blank">Facebook</a>
<a href="#" target="_blank">Twitter</a>
<a href="#" target="_blank">LinkedIn</a>
<a href="#" target="_blank">YouTube</a>
</div>
</div>
</div>
<div class="footer-bottom">
<p>&copy; <?php echo date('Y'); ?> <?php echo SITE_NAME; ?>. All rights reserved.</p>
</div>
</div>
</footer>
<script src="assets/js/main.js"></script>
</body>
</html>

4. Course Details Page (course-details.php)

<?php
require_once 'includes/config.php';
$slug = $_GET['slug'] ?? '';
if (empty($slug)) {
redirect('courses.php');
}
// Get course details
$stmt = $pdo->prepare("
SELECT c.*, u.full_name as instructor_name, u.avatar as instructor_avatar, u.bio as instructor_bio,
u.id as instructor_id, cat.name as category_name, cat.slug as category_slug
FROM courses c
JOIN users u ON c.instructor_id = u.id
JOIN categories cat ON c.category_id = cat.id
WHERE c.slug = ? AND c.status = 'published'
");
$stmt->execute([$slug]);
$course = $stmt->fetch();
if (!$course) {
redirect('courses.php');
}
// Check if user is enrolled
$is_enrolled = false;
$course_progress = 0;
if (isLoggedIn()) {
$enroll_check = $pdo->prepare("SELECT * FROM enrollments WHERE user_id = ? AND course_id = ?");
$enroll_check->execute([$_SESSION['user_id'], $course['id']]);
$is_enrolled = $enroll_check->fetch();
if ($is_enrolled) {
$progress = getCourseProgress($_SESSION['user_id'], $course['id']);
$course_progress = $progress['percentage'];
}
}
// Check if in wishlist
$in_wishlist = false;
if (isLoggedIn()) {
$wishlist_check = $pdo->prepare("SELECT * FROM wishlist WHERE user_id = ? AND course_id = ?");
$wishlist_check->execute([$_SESSION['user_id'], $course['id']]);
$in_wishlist = $wishlist_check->fetch();
}
// Get course sections and lessons
$sections = $pdo->prepare("
SELECT cs.*, 
(SELECT COUNT(*) FROM lessons WHERE section_id = cs.id) as lesson_count
FROM course_sections cs
WHERE cs.course_id = ?
ORDER BY cs.order_position
");
$sections->execute([$course['id']]);
$course_sections = $sections->fetchAll();
$lessons_by_section = [];
foreach ($course_sections as $section) {
$lessons = $pdo->prepare("
SELECT * FROM lessons 
WHERE section_id = ? 
ORDER BY order_position
");
$lessons->execute([$section['id']]);
$lessons_by_section[$section['id']] = $lessons->fetchAll();
}
// Get reviews
$reviews = $pdo->prepare("
SELECT r.*, u.full_name, u.avatar
FROM reviews r
JOIN users u ON r.user_id = u.id
WHERE r.course_id = ? AND r.status = 'approved'
ORDER BY r.created_at DESC
LIMIT 10
");
$reviews->execute([$course['id']]);
$course_reviews = $reviews->fetchAll();
// Handle review submission
$review_error = '';
$review_success = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['submit_review']) && $is_enrolled) {
$rating = (int)$_POST['rating'];
$review_text = sanitize($_POST['review']);
if ($rating < 1 || $rating > 5) {
$review_error = 'Please select a rating';
} elseif (empty($review_text)) {
$review_error = 'Please enter your review';
} else {
// Check if already reviewed
$check = $pdo->prepare("SELECT id FROM reviews WHERE user_id = ? AND course_id = ?");
$check->execute([$_SESSION['user_id'], $course['id']]);
if ($check->fetch()) {
$review_error = 'You have already reviewed this course';
} else {
$stmt = $pdo->prepare("
INSERT INTO reviews (user_id, course_id, rating, review, status) 
VALUES (?, ?, ?, ?, 'pending')
");
$stmt->execute([$_SESSION['user_id'], $course['id'], $rating, $review_text]);
$review_success = 'Your review has been submitted and is waiting for approval.';
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo $course['title']; ?> - <?php echo SITE_NAME; ?></title>
<meta name="description" content="<?php echo getExcerpt($course['short_description'] ?: $course['description'], 160); ?>">
<link rel="stylesheet" href="assets/css/style.css">
</head>
<body>
<!-- Header -->
<?php include 'includes/header.php'; ?>
<!-- Course Header -->
<div class="course-header">
<div class="container">
<div class="course-header-content">
<div class="breadcrumb">
<a href="index.php">Home</a> / 
<a href="courses.php?category=<?php echo $course['category_slug']; ?>"><?php echo $course['category_name']; ?></a> / 
<span><?php echo $course['title']; ?></span>
</div>
<h1 class="course-title-large"><?php echo $course['title']; ?></h1>
<p class="course-description-short"><?php echo $course['short_description']; ?></p>
<div class="course-stats-large">
<span class="rating">★ <?php echo number_format($course['rating'], 1); ?> (<?php echo $course['reviews_count']; ?> reviews)</span>
<span class="students">👥 <?php echo number_format($course['students_count']); ?> students</span>
<span class="duration">⏱️ <?php echo $course['duration_hours']; ?> hours</span>
<span class="lessons">📚 <?php echo $course['lessons_count']; ?> lessons</span>
<span class="level">📊 <?php echo ucfirst($course['level']); ?></span>
</div>
<div class="instructor-info">
<img src="assets/images/<?php echo $course['instructor_avatar'] ?: 'default-avatar.png'; ?>" 
alt="<?php echo $course['instructor_name']; ?>" class="instructor-avatar">
<span>Created by <a href="instructor-profile.php?id=<?php echo $course['instructor_id']; ?>"><?php echo $course['instructor_name']; ?></a></span>
</div>
</div>
<div class="course-card-sidebar">
<div class="course-card-image">
<img src="assets/images/courses/<?php echo $course['thumbnail'] ?: 'default-course.jpg'; ?>" 
alt="<?php echo $course['title']; ?>">
<?php if ($course['promo_video']): ?>
<button class="play-promo" onclick="playPromoVideo()">▶</button>
<?php endif; ?>
</div>
<div class="course-card-pricing">
<?php if ($course['is_free']): ?>
<div class="price-large free">Free</div>
<?php elseif ($course['discount_price']): ?>
<div class="price-large">
<span class="old-price"><?php echo formatCurrency($course['price']); ?></span>
<span class="current-price"><?php echo formatCurrency($course['discount_price']); ?></span>
</div>
<?php else: ?>
<div class="price-large"><?php echo formatCurrency($course['price']); ?></div>
<?php endif; ?>
<?php if ($is_enrolled): ?>
<div class="enrolled-status">
<p>You are enrolled in this course</p>
<div class="progress-circle">
<div class="progress" style="width: <?php echo $course_progress; ?>%"></div>
<span><?php echo $course_progress; ?>% complete</span>
</div>
<a href="course-content.php?course=<?php echo $course['slug']; ?>" class="btn btn-primary btn-block">Continue Learning</a>
</div>
<?php else: ?>
<button class="btn btn-primary btn-large btn-block" onclick="enrollCourse(<?php echo $course['id']; ?>)">
<?php echo $course['is_free'] ? 'Enroll for Free' : 'Buy Now'; ?>
</button>
<button class="btn btn-outline btn-block" onclick="toggleWishlist(<?php echo $course['id']; ?>)">
<?php echo $in_wishlist ? '❤️ Remove from Wishlist' : '🤍 Add to Wishlist'; ?>
</button>
<p class="money-back">30-Day Money-Back Guarantee</p>
<?php endif; ?>
<div class="course-includes">
<h4>This course includes:</h4>
<ul>
<li>📹 <?php echo $course['duration_hours']; ?> hours on-demand video</li>
<li>📄 <?php echo $course['lessons_count']; ?> downloadable resources</li>
<li>📱 Access on mobile and TV</li>
<li>🏆 Certificate of completion</li>
<li>⏳ Full lifetime access</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- Main Content -->
<div class="container">
<div class="course-main">
<!-- Left Column - Course Content -->
<div class="course-content-main">
<!-- What you'll learn -->
<div class="course-section learn-section">
<h3>What you'll learn</h3>
<?php if ($course['what_you_learn']): ?>
<div class="learn-grid">
<?php 
$learn_items = explode("\n", $course['what_you_learn']);
foreach ($learn_items as $item): 
if (trim($item)):
?>
<div class="learn-item">✓ <?php echo $item; ?></div>
<?php 
endif;
endforeach; 
?>
</div>
<?php endif; ?>
</div>
<!-- Course Description -->
<div class="course-section">
<h3>Description</h3>
<div class="course-description">
<?php echo $course['description']; ?>
</div>
</div>
<!-- Course Content / Syllabus -->
<div class="course-section">
<h3>Course Content</h3>
<div class="course-sections">
<?php foreach ($course_sections as $index => $section): ?>
<div class="section-item">
<div class="section-header" onclick="toggleSection(<?php echo $section['id']; ?>)">
<span class="section-toggle">▼</span>
<span class="section-title"><?php echo $section['title']; ?></span>
<span class="section-meta">
<?php echo $section['lesson_count']; ?> lessons
</span>
</div>
<div class="section-content" id="section-<?php echo $section['id']; ?>">
<?php if (!empty($lessons_by_section[$section['id']])): ?>
<ul class="lesson-list">
<?php foreach ($lessons_by_section[$section['id']] as $lesson): ?>
<li class="lesson-item">
<span class="lesson-icon">
<?php 
switch($lesson['content_type']) {
case 'video': echo '📹'; break;
case 'pdf': echo '📄'; break;
case 'text': echo '📝'; break;
case 'quiz': echo '❓'; break;
default: echo '📹';
}
?>
</span>
<span class="lesson-title"><?php echo $lesson['title']; ?></span>
<?php if ($lesson['is_preview'] && !$is_enrolled): ?>
<button class="btn-preview" onclick="previewLesson(<?php echo $lesson['id']; ?>)">Preview</button>
<?php endif; ?>
<?php if ($lesson['video_duration']): ?>
<span class="lesson-duration">
<?php echo floor($lesson['video_duration'] / 60); ?>:<?php echo str_pad($lesson['video_duration'] % 60, 2, '0', STR_PAD_LEFT); ?>
</span>
<?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<!-- Requirements -->
<?php if ($course['requirements']): ?>
<div class="course-section">
<h3>Requirements</h3>
<ul class="requirements-list">
<?php 
$req_items = explode("\n", $course['requirements']);
foreach ($req_items as $item): 
if (trim($item)):
?>
<li>• <?php echo $item; ?></li>
<?php 
endif;
endforeach; 
?>
</ul>
</div>
<?php endif; ?>
<!-- Target Audience -->
<?php if ($course['target_audience']): ?>
<div class="course-section">
<h3>Who this course is for</h3>
<ul class="audience-list">
<?php 
$audience_items = explode("\n", $course['target_audience']);
foreach ($audience_items as $item): 
if (trim($item)):
?>
<li>• <?php echo $item; ?></li>
<?php 
endif;
endforeach; 
?>
</ul>
</div>
<?php endif; ?>
<!-- Reviews Section -->
<div class="course-section">
<h3>Reviews</h3>
<?php if ($review_success): ?>
<div class="alert alert-success"><?php echo $review_success; ?></div>
<?php endif; ?>
<?php if ($review_error): ?>
<div class="alert alert-error"><?php echo $review_error; ?></div>
<?php endif; ?>
<?php if ($is_enrolled && !$course_reviews): ?>
<div class="review-form">
<h4>Write a Review</h4>
<form method="POST" action="">
<div class="rating-select">
<label>Your Rating:</label>
<div class="stars">
<?php for ($i = 1; $i <= 5; $i++): ?>
<span class="star" onclick="setRating(<?php echo $i; ?>)">★</span>
<?php endfor; ?>
</div>
<input type="hidden" name="rating" id="rating-value" value="5">
</div>
<div class="form-group">
<label for="review">Your Review:</label>
<textarea id="review" name="review" rows="4" required></textarea>
</div>
<button type="submit" name="submit_review" class="btn btn-primary">Submit Review</button>
</form>
</div>
<?php endif; ?>
<div class="reviews-list">
<?php if (empty($course_reviews)): ?>
<p>No reviews yet. Be the first to review this course!</p>
<?php else: ?>
<?php foreach ($course_reviews as $review): ?>
<div class="review-item">
<div class="reviewer">
<img src="assets/images/<?php echo $review['avatar'] ?: 'default-avatar.png'; ?>" 
alt="<?php echo $review['full_name']; ?>" class="reviewer-avatar">
<div>
<span class="reviewer-name"><?php echo $review['full_name']; ?></span>
<span class="review-date"><?php echo timeAgo($review['created_at']); ?></span>
</div>
</div>
<div class="review-rating">
<?php for ($i = 1; $i <= 5; $i++): ?>
<span class="star <?php echo $i <= $review['rating'] ? 'filled' : ''; ?>">★</span>
<?php endfor; ?>
</div>
<p class="review-content"><?php echo $review['review']; ?></p>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>
<!-- Footer -->
<?php include 'includes/footer.php'; ?>
<script src="assets/js/main.js"></script>
<script>
function enrollCourse(courseId) {
<?php if (!isLoggedIn()): ?>
window.location.href = 'login.php?redirect=course-details.php?slug=<?php echo $course['slug']; ?>';
return;
<?php endif; ?>
fetch('api/enroll.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'course_id=' + courseId
})
.then(response => response.json())
.then(data => {
if (data.success) {
window.location.href = 'course-content.php?course=<?php echo $course['slug']; ?>';
} else {
alert(data.message);
}
});
}
function toggleWishlist(courseId) {
<?php if (!isLoggedIn()): ?>
window.location.href = 'login.php?redirect=course-details.php?slug=<?php echo $course['slug']; ?>';
return;
<?php endif; ?>
fetch('api/toggle-wishlist.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'course_id=' + courseId
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
}
});
}
function toggleSection(sectionId) {
const content = document.getElementById('section-' + sectionId);
const header = content.previousElementSibling;
const toggle = header.querySelector('.section-toggle');
if (content.style.display === 'none' || !content.style.display) {
content.style.display = 'block';
toggle.textContent = '▼';
} else {
content.style.display = 'none';
toggle.textContent = '▶';
}
}
function setRating(rating) {
document.getElementById('rating-value').value = rating;
const stars = document.querySelectorAll('.stars .star');
stars.forEach((star, index) => {
if (index < rating) {
star.classList.add('selected');
} else {
star.classList.remove('selected');
}
});
}
</script>
</body>
</html>

5. Course Content Player (course-content.php)

<?php
require_once 'includes/config.php';
require_once 'includes/auth.php';
Auth::checkLogin();
$slug = $_GET['course'] ?? '';
$lesson_id = isset($_GET['lesson']) ? (int)$_GET['lesson'] : 0;
if (empty($slug)) {
redirect('my-courses.php');
}
// Get course details
$stmt = $pdo->prepare("
SELECT c.*, u.full_name as instructor_name
FROM courses c
JOIN users u ON c.instructor_id = u.id
WHERE c.slug = ? AND c.status = 'published'
");
$stmt->execute([$slug]);
$course = $stmt->fetch();
if (!$course) {
redirect('my-courses.php');
}
// Check if user is enrolled
$enroll_check = $pdo->prepare("SELECT * FROM enrollments WHERE user_id = ? AND course_id = ?");
$enroll_check->execute([$_SESSION['user_id'], $course['id']]);
$enrollment = $enroll_check->fetch();
if (!$enrollment) {
$_SESSION['error'] = 'You must be enrolled to access this course';
redirect('course-details.php?slug=' . $slug);
}
// Get course sections and lessons
$sections = $pdo->prepare("
SELECT cs.*, 
(SELECT COUNT(*) FROM lessons WHERE section_id = cs.id) as lesson_count
FROM course_sections cs
WHERE cs.course_id = ?
ORDER BY cs.order_position
");
$sections->execute([$course['id']]);
$course_sections = $sections->fetchAll();
$lessons_by_section = [];
$first_lesson = null;
foreach ($course_sections as $section) {
$lessons = $pdo->prepare("
SELECT * FROM lessons 
WHERE section_id = ? 
ORDER BY order_position
");
$lessons->execute([$section['id']]);
$lessons_by_section[$section['id']] = $lessons->fetchAll();
if (!$first_lesson && !empty($lessons_by_section[$section['id']])) {
$first_lesson = $lessons_by_section[$section['id']][0];
}
}
// If no lesson selected, use first lesson
if (!$lesson_id && $first_lesson) {
$lesson_id = $first_lesson['id'];
}
// Get current lesson
$current_lesson = null;
if ($lesson_id) {
$stmt = $pdo->prepare("SELECT * FROM lessons WHERE id = ?");
$stmt->execute([$lesson_id]);
$current_lesson = $stmt->fetch();
// Check if lesson belongs to this course
$lesson_check = $pdo->prepare("
SELECT l.* FROM lessons l
JOIN course_sections cs ON l.section_id = cs.id
WHERE l.id = ? AND cs.course_id = ?
");
$lesson_check->execute([$lesson_id, $course['id']]);
if (!$lesson_check->fetch()) {
$current_lesson = null;
}
}
// Get lesson progress
$lesson_progress = [];
if ($lesson_id) {
$progress = $pdo->prepare("
SELECT completed FROM lesson_progress 
WHERE user_id = ? AND lesson_id = ?
");
$progress->execute([$_SESSION['user_id'], $lesson_id]);
$lesson_progress = $progress->fetch();
}
// Get course progress
$course_progress = getCourseProgress($_SESSION['user_id'], $course['id']);
// Handle lesson completion
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['mark_completed'])) {
$lesson_id = (int)$_POST['lesson_id'];
// Check if already completed
$check = $pdo->prepare("
SELECT id FROM lesson_progress 
WHERE user_id = ? AND lesson_id = ?
");
$check->execute([$_SESSION['user_id'], $lesson_id]);
if (!$check->fetch()) {
$pdo->prepare("
INSERT INTO lesson_progress (user_id, lesson_id, course_id, completed, completed_at)
VALUES (?, ?, ?, 1, NOW())
")->execute([$_SESSION['user_id'], $lesson_id, $course['id']]);
// Update enrollment progress
$completed_count = $pdo->prepare("
SELECT COUNT(*) FROM lesson_progress 
WHERE user_id = ? AND course_id = ? AND completed = 1
");
$completed_count->execute([$_SESSION['user_id'], $course['id']]);
$completed = $completed_count->fetchColumn();
$progress_percentage = calculateProgress($completed, $course['lessons_count']);
$pdo->prepare("
UPDATE enrollments 
SET progress = ?, completed_lessons = ?
WHERE user_id = ? AND course_id = ?
")->execute([$progress_percentage, $completed, $_SESSION['user_id'], $course['id']]);
// Check if course completed
if ($completed >= $course['lessons_count'] && $course['certificate_available']) {
// Generate certificate
$certificate_code = 'CERT-' . strtoupper(uniqid());
$pdo->prepare("
UPDATE enrollments 
SET completed_at = NOW(), certificate_issued = 1, certificate_code = ?
WHERE user_id = ? AND course_id = ?
")->execute([$certificate_code, $_SESSION['user_id'], $course['id']]);
}
}
redirect('course-content.php?course=' . $slug . '&lesson=' . $lesson_id);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo $course['title']; ?> - <?php echo SITE_NAME; ?></title>
<link rel="stylesheet" href="assets/css/style.css">
<link href="https://vjs.zencdn.net/7.20.3/video-js.css" rel="stylesheet" />
</head>
<body class="course-player-page">
<div class="course-player">
<!-- Header -->
<header class="player-header">
<div class="container">
<div class="player-header-left">
<a href="my-courses.php" class="back-link">← Back to My Courses</a>
<h1><?php echo $course['title']; ?></h1>
</div>
<div class="player-header-right">
<div class="course-progress">
<div class="progress-bar">
<div class="progress" style="width: <?php echo $course_progress['percentage']; ?>%"></div>
</div>
<span><?php echo $course_progress['percentage']; ?>% Complete</span>
</div>
</div>
</div>
</header>
<div class="player-container">
<!-- Sidebar - Course Content -->
<aside class="player-sidebar">
<div class="sidebar-header">
<h3>Course Content</h3>
<span><?php echo $course['lessons_count']; ?> lessons</span>
</div>
<div class="sidebar-content">
<?php foreach ($course_sections as $section): ?>
<div class="sidebar-section">
<div class="section-title" onclick="toggleSidebarSection(<?php echo $section['id']; ?>)">
<span class="toggle">▼</span>
<span class="title"><?php echo $section['title']; ?></span>
<span class="count"><?php echo $section['lesson_count']; ?></span>
</div>
<div class="section-lessons" id="sidebar-section-<?php echo $section['id']; ?>">
<?php if (!empty($lessons_by_section[$section['id']])): ?>
<?php foreach ($lessons_by_section[$section['id']] as $lesson): 
// Check if lesson is completed
$completed = $pdo->prepare("
SELECT completed FROM lesson_progress 
WHERE user_id = ? AND lesson_id = ?
");
$completed->execute([$_SESSION['user_id'], $lesson['id']]);
$is_completed = $completed->fetch();
?>
<a href="course-content.php?course=<?php echo $slug; ?>&lesson=<?php echo $lesson['id']; ?>" 
class="lesson-link <?php echo $lesson['id'] == $lesson_id ? 'active' : ''; ?>">
<span class="lesson-status">
<?php if ($is_completed): ?>
<span class="completed">✓</span>
<?php else: ?>
<span class="not-completed">○</span>
<?php endif; ?>
</span>
<span class="lesson-title"><?php echo $lesson['title']; ?></span>
<?php if ($lesson['video_duration']): ?>
<span class="lesson-duration">
<?php echo floor($lesson['video_duration'] / 60); ?>:<?php echo str_pad($lesson['video_duration'] % 60, 2, '0', STR_PAD_LEFT); ?>
</span>
<?php endif; ?>
</a>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>
</aside>
<!-- Main Content - Video Player -->
<main class="player-main">
<?php if ($current_lesson): ?>
<div class="lesson-container">
<h2 class="lesson-title"><?php echo $current_lesson['title']; ?></h2>
<?php if ($current_lesson['content_type'] == 'video'): ?>
<div class="video-container">
<video
id="my-video"
class="video-js vjs-big-play-centered"
controls
preload="auto"
width="100%"
height="auto"
data-setup='{"fluid": true}'
>
<source src="<?php echo $current_lesson['video_url']; ?>" type="video/mp4">
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a
web browser that <a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
</div>
<?php elseif ($current_lesson['content_type'] == 'pdf'): ?>
<div class="pdf-container">
<iframe src="<?php echo $current_lesson['file_path']; ?>" width="100%" height="600px"></iframe>
</div>
<?php elseif ($current_lesson['content_type'] == 'text'): ?>
<div class="text-content">
<?php echo $current_lesson['text_content']; ?>
</div>
<?php endif; ?>
<?php if ($current_lesson['description']): ?>
<div class="lesson-description">
<h3>Lesson Description</h3>
<p><?php echo $current_lesson['description']; ?></p>
</div>
<?php endif; ?>
<div class="lesson-actions">
<?php if (!$lesson_progress): ?>
<form method="POST" action="">
<input type="hidden" name="lesson_id" value="<?php echo $current_lesson['id']; ?>">
<button type="submit" name="mark_completed" class="btn btn-success">
Mark as Completed
</button>
</form>
<?php else: ?>
<span class="completed-badge">✓ Lesson Completed</span>
<?php endif; ?>
<!-- Navigation between lessons -->
<div class="lesson-navigation">
<?php
// Find previous and next lessons
$all_lessons = [];
foreach ($course_sections as $section) {
if (!empty($lessons_by_section[$section['id']])) {
$all_lessons = array_merge($all_lessons, $lessons_by_section[$section['id']]);
}
}
$current_index = array_search($current_lesson['id'], array_column($all_lessons, 'id'));
$prev_lesson = $current_index > 0 ? $all_lessons[$current_index - 1] : null;
$next_lesson = $current_index < count($all_lessons) - 1 ? $all_lessons[$current_index + 1] : null;
?>
<?php if ($prev_lesson): ?>
<a href="course-content.php?course=<?php echo $slug; ?>&lesson=<?php echo $prev_lesson['id']; ?>" class="btn">
← Previous Lesson
</a>
<?php endif; ?>
<?php if ($next_lesson): ?>
<a href="course-content.php?course=<?php echo $slug; ?>&lesson=<?php echo $next_lesson['id']; ?>" class="btn btn-primary">
Next Lesson →
</a>
<?php endif; ?>
</div>
</div>
</div>
<?php else: ?>
<div class="no-lesson-selected">
<h2>Select a lesson to start learning</h2>
<p>Choose a lesson from the course content sidebar.</p>
</div>
<?php endif; ?>
</main>
</div>
</div>
<script src="https://vjs.zencdn.net/7.20.3/video.min.js"></script>
<script src="assets/js/player.js"></script>
<script>
function toggleSidebarSection(sectionId) {
const content = document.getElementById('sidebar-section-' + sectionId);
const header = content.previousElementSibling;
const toggle = header.querySelector('.toggle');
if (content.style.display === 'none' || !content.style.display) {
content.style.display = 'block';
toggle.textContent = '▼';
} else {
content.style.display = 'none';
toggle.textContent = '▶';
}
}
</script>
</body>
</html>

6. Instructor Dashboard (instructor/dashboard.php)

<?php
require_once '../includes/config.php';
require_once '../includes/auth.php';
Auth::checkInstructor();
$instructor_id = $_SESSION['user_id'];
// Get statistics
$total_courses = $pdo->prepare("SELECT COUNT(*) FROM courses WHERE instructor_id = ?");
$total_courses->execute([$instructor_id]);
$course_count = $total_courses->fetchColumn();
$published_courses = $pdo->prepare("SELECT COUNT(*) FROM courses WHERE instructor_id = ? AND status = 'published'");
$published_courses->execute([$instructor_id]);
$published_count = $published_courses->fetchColumn();
$total_students = $pdo->prepare("
SELECT COUNT(DISTINCT e.user_id) 
FROM enrollments e
JOIN courses c ON e.course_id = c.id
WHERE c.instructor_id = ?
");
$total_students->execute([$instructor_id]);
$student_count = $total_students->fetchColumn();
$total_earnings = $pdo->prepare("
SELECT SUM(p.instructor_earning) 
FROM payments p
JOIN courses c ON p.course_id = c.id
WHERE c.instructor_id = ? AND p.status = 'completed'
");
$total_earnings->execute([$instructor_id]);
$earnings = $total_earnings->fetchColumn();
// Get recent courses
$recent_courses = $pdo->prepare("
SELECT c.*, 
(SELECT COUNT(*) FROM enrollments WHERE course_id = c.id) as student_count
FROM courses c
WHERE c.instructor_id = ?
ORDER BY c.created_at DESC
LIMIT 5
");
$recent_courses->execute([$instructor_id]);
$courses = $recent_courses->fetchAll();
// Get recent enrollments
$recent_enrollments = $pdo->prepare("
SELECT e.*, u.full_name as student_name, u.email, c.title as course_title
FROM enrollments e
JOIN users u ON e.user_id = u.id
JOIN courses c ON e.course_id = c.id
WHERE c.instructor_id = ?
ORDER BY e.enrolled_at DESC
LIMIT 10
");
$recent_enrollments->execute([$instructor_id]);
$enrollments = $recent_enrollments->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Instructor Dashboard - <?php echo SITE_NAME; ?></title>
<link rel="stylesheet" href="../assets/css/admin.css">
</head>
<body>
<div class="admin-wrapper">
<!-- Sidebar -->
<aside class="sidebar">
<div class="sidebar-header">
<h2>Instructor Panel</h2>
<p>Welcome, <?php echo $_SESSION['user_name']; ?></p>
</div>
<nav class="sidebar-nav">
<ul>
<li><a href="dashboard.php" class="active">Dashboard</a></li>
<li><a href="courses.php">My Courses</a></li>
<li><a href="add-course.php">Create Course</a></li>
<li><a href="students.php">My Students</a></li>
<li><a href="earnings.php">Earnings</a></li>
<li><a href="profile.php">Profile</a></li>
<li><a href="logout.php">Logout</a></li>
</ul>
</nav>
</aside>
<!-- Main Content -->
<main class="admin-main">
<div class="container">
<h1>Instructor Dashboard</h1>
<!-- Stats Cards -->
<div class="stats-grid">
<div class="stat-card">
<div class="stat-icon">📚</div>
<div class="stat-details">
<h3><?php echo $course_count; ?></h3>
<p>Total Courses</p>
<small><?php echo $published_count; ?> published</small>
</div>
</div>
<div class="stat-card">
<div class="stat-icon">👥</div>
<div class="stat-details">
<h3><?php echo number_format($student_count); ?></h3>
<p>Total Students</p>
</div>
</div>
<div class="stat-card">
<div class="stat-icon">💰</div>
<div class="stat-details">
<h3><?php echo formatCurrency($earnings ?: 0); ?></h3>
<p>Total Earnings</p>
</div>
</div>
</div>
<!-- Quick Actions -->
<div class="quick-actions">
<a href="add-course.php" class="action-card">
<span class="action-icon">➕</span>
<span>Create New Course</span>
</a>
<a href="courses.php" class="action-card">
<span class="action-icon">📝</span>
<span>Manage Courses</span>
</a>
<a href="profile.php" class="action-card">
<span class="action-icon">👤</span>
<span>Update Profile</span>
</a>
</div>
<!-- Recent Courses -->
<div class="card">
<div class="card-header">
<h3>Your Courses</h3>
<a href="courses.php" class="btn btn-sm">View All</a>
</div>
<div class="card-body">
<table class="data-table">
<thead>
<tr>
<th>Course Title</th>
<th>Students</th>
<th>Price</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($courses as $course): ?>
<tr>
<td><?php echo $course['title']; ?></td>
<td><?php echo number_format($course['student_count']); ?></td>
<td><?php echo $course['is_free'] ? 'Free' : formatCurrency($course['price']); ?></td>
<td>
<span class="badge badge-<?php echo $course['status']; ?>">
<?php echo ucfirst($course['status']); ?>
</span>
</td>
<td>
<a href="edit-course.php?id=<?php echo $course['id']; ?>" class="btn-small">Edit</a>
<a href="lessons.php?course=<?php echo $course['id']; ?>" class="btn-small">Lessons</a>
<a href="../course-details.php?slug=<?php echo $course['slug']; ?>" class="btn-small" target="_blank">View</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<!-- Recent Enrollments -->
<div class="card">
<div class="card-header">
<h3>Recent Enrollments</h3>
</div>
<div class="card-body">
<table class="data-table">
<thead>
<tr>
<th>Student</th>
<th>Course</th>
<th>Enrolled</th>
<th>Progress</th>
</tr>
</thead>
<tbody>
<?php foreach ($enrollments as $enrollment): ?>
<tr>
<td>
<?php echo $enrollment['student_name']; ?><br>
<small><?php echo $enrollment['email']; ?></small>
</td>
<td><?php echo $enrollment['course_title']; ?></td>
<td><?php echo timeAgo($enrollment['enrolled_at']); ?></td>
<td><?php echo $enrollment['progress']; ?>%</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</main>
</div>
</body>
</html>

7. Instructor - Add Course (instructor/add-course.php)

<?php
require_once '../includes/config.php';
require_once '../includes/auth.php';
Auth::checkInstructor();
// Get categories
$categories = $pdo->query("SELECT * FROM categories WHERE status = 'active' ORDER BY name")->fetchAll();
$errors = [];
$form_data = [
'title' => '',
'short_description' => '',
'description' => '',
'category_id' => '',
'level' => 'beginner',
'language' => 'English',
'price' => 0,
'is_free' => 0,
'requirements' => '',
'what_you_learn' => '',
'target_audience' => ''
];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Sanitize input
$form_data['title'] = sanitize($_POST['title']);
$form_data['short_description'] = sanitize($_POST['short_description']);
$form_data['description'] = $_POST['description'];
$form_data['category_id'] = (int)$_POST['category_id'];
$form_data['level'] = $_POST['level'];
$form_data['language'] = sanitize($_POST['language']);
$form_data['price'] = (float)$_POST['price'];
$form_data['is_free'] = isset($_POST['is_free']) ? 1 : 0;
$form_data['requirements'] = sanitize($_POST['requirements']);
$form_data['what_you_learn'] = sanitize($_POST['what_you_learn']);
$form_data['target_audience'] = sanitize($_POST['target_audience']);
// Validate
if (empty($form_data['title'])) {
$errors['title'] = 'Title is required';
}
if (empty($form_data['description'])) {
$errors['description'] = 'Description is required';
}
if (empty($form_data['category_id'])) {
$errors['category_id'] = 'Category is required';
}
if (!$form_data['is_free'] && $form_data['price'] <= 0) {
$errors['price'] = 'Price must be greater than 0 for paid courses';
}
// Handle thumbnail upload
if (isset($_FILES['thumbnail']) && $_FILES['thumbnail']['error'] == 0) {
$allowed = ['image/jpeg', 'image/png', 'image/jpg'];
$max_size = 2 * 1024 * 1024; // 2MB
if (!in_array($_FILES['thumbnail']['type'], $allowed)) {
$errors['thumbnail'] = 'Only JPG and PNG images are allowed';
} elseif ($_FILES['thumbnail']['size'] > $max_size) {
$errors['thumbnail'] = 'Image size must be less than 2MB';
} else {
$extension = pathinfo($_FILES['thumbnail']['name'], PATHINFO_EXTENSION);
$filename = uniqid() . '.' . $extension;
$upload_path = '../assets/images/courses/' . $filename;
if (move_uploaded_file($_FILES['thumbnail']['tmp_name'], $upload_path)) {
$form_data['thumbnail'] = $filename;
}
}
}
if (empty($errors)) {
try {
// Create slug
$slug = createSlug($form_data['title']);
// Check if slug exists
$check = $pdo->prepare("SELECT id FROM courses WHERE slug = ?");
$check->execute([$slug]);
if ($check->fetch()) {
$slug .= '-' . uniqid();
}
// Calculate duration (will be updated later when lessons are added)
$duration = 0;
// Insert course
$stmt = $pdo->prepare("
INSERT INTO courses (
title, slug, short_description, description, category_id, instructor_id,
level, language, price, is_free, thumbnail, requirements, what_you_learn,
target_audience, duration_hours, status
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'draft')
");
$stmt->execute([
$form_data['title'],
$slug,
$form_data['short_description'],
$form_data['description'],
$form_data['category_id'],
$_SESSION['user_id'],
$form_data['level'],
$form_data['language'],
$form_data['price'],
$form_data['is_free'],
$form_data['thumbnail'] ?? null,
$form_data['requirements'],
$form_data['what_you_learn'],
$form_data['target_audience'],
$duration
]);
$course_id = $pdo->lastInsertId();
$_SESSION['success'] = 'Course created successfully! Now add your lessons.';
redirect('lessons.php?course=' . $course_id);
} catch (Exception $e) {
$errors['general'] = 'Failed to create course: ' . $e->getMessage();
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Create Course - <?php echo SITE_NAME; ?></title>
<link rel="stylesheet" href="../assets/css/admin.css">
<script src="../assets/vendor/tinymce/tinymce.min.js"></script>
</head>
<body>
<div class="admin-wrapper">
<!-- Sidebar -->
<aside class="sidebar">
<div class="sidebar-header">
<h2>Instructor Panel</h2>
<p>Welcome, <?php echo $_SESSION['user_name']; ?></p>
</div>
<nav class="sidebar-nav">
<ul>
<li><a href="dashboard.php">Dashboard</a></li>
<li><a href="courses.php">My Courses</a></li>
<li><a href="add-course.php" class="active">Create Course</a></li>
<li><a href="students.php">My Students</a></li>
<li><a href="earnings.php">Earnings</a></li>
<li><a href="profile.php">Profile</a></li>
<li><a href="logout.php">Logout</a></li>
</ul>
</nav>
</aside>
<!-- Main Content -->
<main class="admin-main">
<div class="container">
<div class="page-header">
<h1>Create New Course</h1>
<a href="courses.php" class="btn">← Back to Courses</a>
</div>
<?php if (!empty($errors['general'])): ?>
<div class="alert alert-error"><?php echo $errors['general']; ?></div>
<?php endif; ?>
<div class="card">
<div class="card-body">
<form method="POST" action="" enctype="multipart/form-data" class="admin-form">
<!-- Basic Information -->
<h3>Basic Information</h3>
<div class="form-group">
<label for="title">Course Title *</label>
<input type="text" id="title" name="title" 
value="<?php echo htmlspecialchars($form_data['title']); ?>" required>
<?php if (isset($errors['title'])): ?>
<span class="error"><?php echo $errors['title']; ?></span>
<?php endif; ?>
</div>
<div class="form-group">
<label for="short_description">Short Description</label>
<textarea id="short_description" name="short_description" rows="3"><?php echo $form_data['short_description']; ?></textarea>
<small>Brief summary of your course (max 500 characters)</small>
</div>
<div class="form-group">
<label for="description">Full Description *</label>
<textarea id="description" name="description" rows="10"><?php echo $form_data['description']; ?></textarea>
<?php if (isset($errors['description'])): ?>
<span class="error"><?php echo $errors['description']; ?></span>
<?php endif; ?>
</div>
<!-- Course Settings -->
<h3>Course Settings</h3>
<div class="form-row">
<div class="form-group col-md-6">
<label for="category_id">Category *</label>
<select id="category_id" name="category_id" required>
<option value="">Select Category</option>
<?php foreach ($categories as $cat): ?>
<option value="<?php echo $cat['id']; ?>" 
<?php echo $form_data['category_id'] == $cat['id'] ? 'selected' : ''; ?>>
<?php echo $cat['name']; ?>
</option>
<?php endforeach; ?>
</select>
<?php if (isset($errors['category_id'])): ?>
<span class="error"><?php echo $errors['category_id']; ?></span>
<?php endif; ?>
</div>
<div class="form-group col-md-6">
<label for="level">Level</label>
<select id="level" name="level">
<option value="beginner" <?php echo $form_data['level'] == 'beginner' ? 'selected' : ''; ?>>Beginner</option>
<option value="intermediate" <?php echo $form_data['level'] == 'intermediate' ? 'selected' : ''; ?>>Intermediate</option>
<option value="advanced" <?php echo $form_data['level'] == 'advanced' ? 'selected' : ''; ?>>Advanced</option>
<option value="all-levels" <?php echo $form_data['level'] == 'all-levels' ? 'selected' : ''; ?>>All Levels</option>
</select>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="language">Language</label>
<input type="text" id="language" name="language" value="<?php echo $form_data['language']; ?>">
</div>
<div class="form-group col-md-6">
<label for="thumbnail">Course Thumbnail</label>
<input type="file" id="thumbnail" name="thumbnail" accept="image/*">
<?php if (isset($errors['thumbnail'])): ?>
<span class="error"><?php echo $errors['thumbnail']; ?></span>
<?php endif; ?>
<small>Recommended size: 1280x720px, Max size: 2MB</small>
</div>
</div>
<!-- Pricing -->
<h3>Pricing</h3>
<div class="form-group">
<label>
<input type="checkbox" name="is_free" value="1" 
<?php echo $form_data['is_free'] ? 'checked' : ''; ?>
onchange="togglePriceField(this)">
This is a free course
</label>
</div>
<div class="form-group" id="price-field" <?php echo $form_data['is_free'] ? 'style="display:none"' : ''; ?>>
<label for="price">Price (<?php echo CURRENCY; ?>)</label>
<input type="number" id="price" name="price" step="0.01" min="0" 
value="<?php echo $form_data['price']; ?>">
<?php if (isset($errors['price'])): ?>
<span class="error"><?php echo $errors['price']; ?></span>
<?php endif; ?>
</div>
<!-- Course Content -->
<h3>Course Content</h3>
<div class="form-group">
<label for="requirements">Requirements / Prerequisites</label>
<textarea id="requirements" name="requirements" rows="4"><?php echo $form_data['requirements']; ?></textarea>
<small>One item per line</small>
</div>
<div class="form-group">
<label for="what_you_learn">What Students Will Learn</label>
<textarea id="what_you_learn" name="what_you_learn" rows="4"><?php echo $form_data['what_you_learn']; ?></textarea>
<small>One item per line</small>
</div>
<div class="form-group">
<label for="target_audience">Target Audience</label>
<textarea id="target_audience" name="target_audience" rows="4"><?php echo $form_data['target_audience']; ?></textarea>
<small>One item per line</small>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Create Course</button>
<button type="reset" class="btn">Reset</button>
</div>
</form>
</div>
</div>
</div>
</main>
</div>
<script>
tinymce.init({
selector: '#description',
height: 400,
plugins: 'advlist autolink lists link image charmap print preview anchor searchreplace visualblocks code fullscreen insertdatetime media table paste code help wordcount',
toolbar: 'undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | removeformat | help'
});
function togglePriceField(checkbox) {
const priceField = document.getElementById('price-field');
priceField.style.display = checkbox.checked ? 'none' : 'block';
}
</script>
</body>
</html>

8. Instructor - Manage Lessons (instructor/lessons.php)

<?php
require_once '../includes/config.php';
require_once '../includes/auth.php';
Auth::checkInstructor();
$course_id = isset($_GET['course']) ? (int)$_GET['course'] : 0;
if (!$course_id) {
redirect('courses.php');
}
// Check if course belongs to instructor
$course_check = $pdo->prepare("SELECT * FROM courses WHERE id = ? AND instructor_id = ?");
$course_check->execute([$course_id, $_SESSION['user_id']]);
$course = $course_check->fetch();
if (!$course) {
$_SESSION['error'] = 'Course not found';
redirect('courses.php');
}
// Handle lesson deletion
if (isset($_GET['delete'])) {
$lesson_id = (int)$_GET['delete'];
// Check if lesson belongs to this course
$check = $pdo->prepare("
SELECT l.* FROM lessons l
JOIN course_sections cs ON l.section_id = cs.id
WHERE l.id = ? AND cs.course_id = ?
");
$check->execute([$lesson_id, $course_id]);
if ($check->fetch()) {
$pdo->prepare("DELETE FROM lessons WHERE id = ?")->execute([$lesson_id]);
$_SESSION['success'] = 'Lesson deleted successfully';
}
redirect('lessons.php?course=' . $course_id);
}
// Get course sections
$sections = $pdo->prepare("
SELECT * FROM course_sections 
WHERE course_id = ? 
ORDER BY order_position
");
$sections->execute([$course_id]);
$course_sections = $sections->fetchAll();
// Get lessons by section
$lessons_by_section = [];
foreach ($course_sections as $section) {
$lessons = $pdo->prepare("
SELECT * FROM lessons 
WHERE section_id = ? 
ORDER BY order_position
");
$lessons->execute([$section['id']]);
$lessons_by_section[$section['id']] = $lessons->fetchAll();
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Manage Lessons - <?php echo $course['title']; ?></title>
<link rel="stylesheet" href="../assets/css/admin.css">
</head>
<body>
<div class="admin-wrapper">
<!-- Sidebar -->
<aside class="sidebar">
<div class="sidebar-header">
<h2>Instructor Panel</h2>
<p>Welcome, <?php echo $_SESSION['user_name']; ?></p>
</div>
<nav class="sidebar-nav">
<ul>
<li><a href="dashboard.php">Dashboard</a></li>
<li><a href="courses.php">My Courses</a></li>
<li><a href="add-course.php">Create Course</a></li>
<li><a href="students.php">My Students</a></li>
<li><a href="earnings.php">Earnings</a></li>
<li><a href="profile.php">Profile</a></li>
<li><a href="logout.php">Logout</a></li>
</ul>
</nav>
</aside>
<!-- Main Content -->
<main class="admin-main">
<div class="container">
<div class="page-header">
<h1>Manage Lessons: <?php echo $course['title']; ?></h1>
<div>
<a href="add-section.php?course=<?php echo $course_id; ?>" class="btn">+ Add Section</a>
<a href="add-lesson.php?course=<?php echo $course_id; ?>" class="btn btn-primary">+ Add Lesson</a>
<a href="courses.php" class="btn">← Back</a>
</div>
</div>
<?php if (isset($_SESSION['success'])): ?>
<div class="alert alert-success"><?php echo $_SESSION['success']; unset($_SESSION['success']); ?></div>
<?php endif; ?>
<?php if (empty($course_sections)): ?>
<div class="card">
<div class="card-body text-center">
<p>No sections yet. Start by creating a section for your course.</p>
<a href="add-section.php?course=<?php echo $course_id; ?>" class="btn btn-primary">Create First Section</a>
</div>
</div>
<?php else: ?>
<?php foreach ($course_sections as $section): ?>
<div class="card">
<div class="card-header">
<h3>
<?php echo $section['title']; ?>
<small>(<?php echo count($lessons_by_section[$section['id']] ?? []); ?> lessons)</small>
</h3>
<div>
<a href="edit-section.php?id=<?php echo $section['id']; ?>" class="btn-small">Edit</a>
<a href="add-lesson.php?section=<?php echo $section['id']; ?>" class="btn-small btn-success">+ Lesson</a>
<a href="?delete_section=<?php echo $section['id']; ?>&course=<?php echo $course_id; ?>" 
class="btn-small btn-danger"
onclick="return confirm('Delete this section and all its lessons?')">Delete</a>
</div>
</div>
<div class="card-body">
<?php if (empty($lessons_by_section[$section['id']])): ?>
<p class="text-muted">No lessons in this section.</p>
<?php else: ?>
<table class="data-table">
<thead>
<tr>
<th>Order</th>
<th>Title</th>
<th>Type</th>
<th>Duration</th>
<th>Preview</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($lessons_by_section[$section['id']] as $lesson): ?>
<tr>
<td><?php echo $lesson['order_position']; ?></td>
<td><?php echo $lesson['title']; ?></td>
<td>
<span class="badge">
<?php echo ucfirst($lesson['content_type']); ?>
</span>
</td>
<td>
<?php if ($lesson['video_duration']): ?>
<?php echo floor($lesson['video_duration'] / 60); ?>:<?php echo str_pad($lesson['video_duration'] % 60, 2, '0', STR_PAD_LEFT); ?>
<?php else: ?>
-
<?php endif; ?>
</td>
<td>
<?php if ($lesson['is_preview']): ?>
<span class="badge badge-success">Yes</span>
<?php else: ?>
<span class="badge">No</span>
<?php endif; ?>
</td>
<td>
<a href="edit-lesson.php?id=<?php echo $lesson['id']; ?>" class="btn-small">Edit</a>
<a href="?delete=<?php echo $lesson['id']; ?>&course=<?php echo $course_id; ?>" 
class="btn-small btn-danger"
onclick="return confirm('Delete this lesson?')">Delete</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
<div class="card">
<div class="card-body text-center">
<?php if ($course['status'] == 'draft'): ?>
<form method="POST" action="publish-course.php" style="display:inline">
<input type="hidden" name="course_id" value="<?php echo $course_id; ?>">
<button type="submit" name="publish" class="btn btn-success btn-large">
Publish Course
</button>
</form>
<?php endif; ?>
<a href="preview-course.php?id=<?php echo $course_id; ?>" class="btn btn-primary btn-large" target="_blank">
Preview Course
</a>
</div>
</div>
<?php endif; ?>
</div>
</main>
</div>
</body>
</html>

9. API - Enroll in Course (api/enroll.php)

<?php
require_once '../includes/config.php';
require_once '../includes/auth.php';
header('Content-Type: application/json');
if (!isLoggedIn()) {
echo json_encode(['success' => false, 'message' => 'Please login to enroll']);
exit;
}
$course_id = (int)($_POST['course_id'] ?? 0);
if (!$course_id) {
echo json_encode(['success' => false, 'message' => 'Invalid course']);
exit;
}
// Get course details
$stmt = $pdo->prepare("SELECT * FROM courses WHERE id = ? AND status = 'published'");
$stmt->execute([$course_id]);
$course = $stmt->fetch();
if (!$course) {
echo json_encode(['success' => false, 'message' => 'Course not found']);
exit;
}
// Check if already enrolled
$check = $pdo->prepare("SELECT id FROM enrollments WHERE user_id = ? AND course_id = ?");
$check->execute([$_SESSION['user_id'], $course_id]);
if ($check->fetch()) {
echo json_encode(['success' => false, 'message' => 'Already enrolled in this course']);
exit;
}
try {
$pdo->beginTransaction();
// Create enrollment
$stmt = $pdo->prepare("
INSERT INTO enrollments (user_id, course_id, total_lessons, enrolled_at)
VALUES (?, ?, ?, NOW())
");
// Get total lessons count
$lessons = $pdo->prepare("
SELECT COUNT(*) FROM lessons l
JOIN course_sections cs ON l.section_id = cs.id
WHERE cs.course_id = ?
");
$lessons->execute([$course_id]);
$total_lessons = $lessons->fetchColumn();
$stmt->execute([$_SESSION['user_id'], $course_id, $total_lessons]);
// Update course students count
$pdo->prepare("UPDATE courses SET students_count = students_count + 1 WHERE id = ?")
->execute([$course_id]);
// Create payment record if paid
if (!$course['is_free'] && $course['price'] > 0) {
$commission = ($course['price'] * COMMISSION_RATE) / 100;
$instructor_earning = $course['price'] - $commission;
$pdo->prepare("
INSERT INTO payments (user_id, course_id, amount, status, commission_amount, instructor_earning)
VALUES (?, ?, ?, 'completed', ?, ?)
")->execute([$_SESSION['user_id'], $course_id, $course['price'], $commission, $instructor_earning]);
}
$pdo->commit();
// Send confirmation email
$user = Auth::getCurrentUser();
$subject = "Enrollment Confirmed: " . $course['title'];
$message = "
<h1>Enrollment Confirmed!</h1>
<p>Dear {$user['full_name']},</p>
<p>You have successfully enrolled in <strong>{$course['title']}</strong>.</p>
<p>You can now access the course content from your dashboard.</p>
<p><a href='" . SITE_URL . "course-content.php?course={$course['slug']}'>Start Learning</a></p>
";
sendEmail($user['email'], $subject, $message);
echo json_encode(['success' => true, 'message' => 'Enrollment successful']);
} catch (Exception $e) {
$pdo->rollBack();
echo json_encode(['success' => false, 'message' => 'Enrollment failed: ' . $e->getMessage()]);
}
?>

10. CSS Styling (assets/css/style.css)

/* Main Styles for Online Course System */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: #333;
background: #f8f9fa;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
/* Header Styles */
.site-header {
background: #fff;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
position: sticky;
top: 0;
z-index: 1000;
}
.top-header {
background: #2c3e50;
color: #fff;
padding: 0.5rem 0;
font-size: 0.9rem;
}
.top-header .container {
display: flex;
justify-content: space-between;
align-items: center;
}
.top-header a {
color: #fff;
text-decoration: none;
margin-left: 1rem;
}
.top-header a:hover {
color: #3498db;
}
.btn-register {
background: #27ae60;
padding: 0.3rem 1rem;
border-radius: 4px;
}
.btn-register:hover {
background: #229954;
color: #fff !important;
}
.main-header {
padding: 1rem 0;
}
.main-header .container {
display: flex;
justify-content: space-between;
align-items: center;
}
.logo h1 {
font-size: 1.8rem;
color: #2c3e50;
font-weight: 700;
}
.logo a {
text-decoration: none;
color: inherit;
}
.main-nav ul {
display: flex;
list-style: none;
gap: 1.5rem;
}
.main-nav a {
text-decoration: none;
color: #333;
font-weight: 500;
transition: color 0.3s;
}
.main-nav a:hover,
.main-nav a.active {
color: #3498db;
}
.dropdown {
position: relative;
}
.dropdown-menu {
display: none;
position: absolute;
top: 100%;
left: 0;
background: #fff;
min-width: 200px;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
border-radius: 4px;
padding: 0.5rem 0;
}
.dropdown:hover .dropdown-menu {
display: block;
}
.dropdown-menu li {
padding: 0;
}
.dropdown-menu a {
display: block;
padding: 0.5rem 1rem;
}
.search-bar form {
display: flex;
}
.search-bar input {
padding: 0.5rem 1rem;
border: 1px solid #ddd;
border-radius: 4px 0 0 4px;
width: 250px;
font-size: 0.9rem;
}
.search-bar button {
padding: 0.5rem 1rem;
background: #3498db;
color: #fff;
border: none;
border-radius: 0 4px 4px 0;
cursor: pointer;
}
.search-bar button:hover {
background: #2980b9;
}
/* Hero Section */
.hero {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #fff;
padding: 4rem 0;
text-align: center;
}
.hero h1 {
font-size: 3rem;
margin-bottom: 1rem;
}
.hero p {
font-size: 1.2rem;
margin-bottom: 2rem;
opacity: 0.9;
max-width: 600px;
margin-left: auto;
margin-right: auto;
}
.hero-stats {
display: flex;
justify-content: center;
gap: 3rem;
margin-bottom: 2rem;
}
.stat-item {
text-align: center;
}
.stat-number {
display: block;
font-size: 2rem;
font-weight: bold;
}
.stat-label {
font-size: 0.9rem;
opacity: 0.9;
}
.hero-actions {
display: flex;
gap: 1rem;
justify-content: center;
}
.btn {
display: inline-block;
padding: 0.75rem 1.5rem;
border-radius: 4px;
text-decoration: none;
font-weight: 500;
transition: all 0.3s;
border: none;
cursor: pointer;
font-size: 1rem;
}
.btn-primary {
background: #3498db;
color: #fff;
}
.btn-primary:hover {
background: #2980b9;
}
.btn-success {
background: #27ae60;
color: #fff;
}
.btn-success:hover {
background: #229954;
}
.btn-outline {
background: transparent;
border: 2px solid #fff;
color: #fff;
}
.btn-outline:hover {
background: #fff;
color: #333;
}
.btn-large {
padding: 1rem 2rem;
font-size: 1.1rem;
}
.btn-block {
display: block;
width: 100%;
text-align: center;
}
/* Section Styles */
section {
padding: 4rem 0;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
}
.section-title {
font-size: 2rem;
color: #2c3e50;
position: relative;
padding-bottom: 0.5rem;
}
.section-title:after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 60px;
height: 3px;
background: #3498db;
}
.view-all {
color: #3498db;
text-decoration: none;
font-weight: 500;
}
.view-all:hover {
text-decoration: underline;
}
/* Course Grid */
.course-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 2rem;
}
.course-card {
background: #fff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
transition: transform 0.3s, box-shadow 0.3s;
}
.course-card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 20px rgba(0,0,0,0.15);
}
.course-image {
position: relative;
height: 160px;
overflow: hidden;
}
.course-image img {
width: 100%;
height: 100%;
object-fit: cover;
}
.course-badge {
position: absolute;
top: 0.5rem;
right: 0.5rem;
padding: 0.25rem 0.5rem;
border-radius: 3px;
font-size: 0.75rem;
font-weight: bold;
text-transform: uppercase;
}
.course-badge.free {
background: #27ae60;
color: #fff;
}
.course-badge.sale {
background: #e74c3c;
color: #fff;
}
.course-content {
padding: 1.5rem;
}
.course-category {
margin-bottom: 0.5rem;
}
.course-category a {
color: #3498db;
text-decoration: none;
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.course-title {
font-size: 1.1rem;
margin-bottom: 0.5rem;
line-height: 1.4;
height: 3rem;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.course-title a {
color: #2c3e50;
text-decoration: none;
}
.course-title a:hover {
color: #3498db;
}
.course-instructor {
font-size: 0.9rem;
color: #666;
margin-bottom: 0.5rem;
}
.course-instructor a {
color: #666;
text-decoration: none;
}
.course-instructor a:hover {
color: #3498db;
}
.course-meta {
display: flex;
gap: 1rem;
font-size: 0.85rem;
color: #666;
margin-bottom: 1rem;
}
.course-rating {
color: #f39c12;
}
.course-price {
display: flex;
align-items: center;
gap: 0.5rem;
}
.price-old {
color: #999;
text-decoration: line-through;
font-size: 0.9rem;
}
.price-current {
font-size: 1.2rem;
font-weight: bold;
color: #2c3e50;
}
.price-free {
color: #27ae60;
font-weight: bold;
}
/* Categories Grid */
.categories-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
margin-top: 2rem;
}
.category-card {
background: #fff;
padding: 2rem;
border-radius: 8px;
text-align: center;
text-decoration: none;
color: #333;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
transition: transform 0.3s;
}
.category-card:hover {
transform: translateY(-5px);
}
.category-icon {
font-size: 3rem;
margin-bottom: 1rem;
display: block;
}
.category-name {
font-size: 1.2rem;
margin-bottom: 0.5rem;
}
.category-count {
color: #666;
font-size: 0.9rem;
}
/* Stats Section */
.stats-section {
background: #2c3e50;
color: #fff;
padding: 3rem 0;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 2rem;
text-align: center;
}
.stat-box {
padding: 1.5rem;
}
.stat-value {
display: block;
font-size: 2.5rem;
font-weight: bold;
margin-bottom: 0.5rem;
}
.stat-label {
font-size: 1rem;
opacity: 0.9;
}
/* CTA Section */
.cta-section {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #fff;
text-align: center;
padding: 4rem 0;
}
.cta-content h2 {
font-size: 2.5rem;
margin-bottom: 1rem;
}
.cta-content p {
font-size: 1.1rem;
margin-bottom: 2rem;
opacity: 0.9;
}
/* Course Details Page */
.course-header {
background: #2c3e50;
color: #fff;
padding: 3rem 0;
margin-bottom: 2rem;
}
.course-header .container {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 2rem;
}
.breadcrumb {
margin-bottom: 1rem;
font-size: 0.9rem;
}
.breadcrumb a {
color: #fff;
opacity: 0.8;
text-decoration: none;
}
.breadcrumb a:hover {
opacity: 1;
}
.course-title-large {
font-size: 2.5rem;
margin-bottom: 1rem;
line-height: 1.3;
}
.course-description-short {
font-size: 1.1rem;
opacity: 0.9;
margin-bottom: 1.5rem;
}
.course-stats-large {
display: flex;
gap: 1.5rem;
margin-bottom: 1.5rem;
font-size: 0.95rem;
}
.instructor-info {
display: flex;
align-items: center;
gap: 1rem;
}
.instructor-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
object-fit: cover;
}
.instructor-info a {
color: #fff;
text-decoration: none;
font-weight: 500;
}
.instructor-info a:hover {
text-decoration: underline;
}
.course-card-sidebar {
background: #fff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 5px 20px rgba(0,0,0,0.2);
}
.course-card-image {
position: relative;
height: 200px;
}
.course-card-image img {
width: 100%;
height: 100%;
object-fit: cover;
}
.play-promo {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 60px;
height: 60px;
background: rgba(52, 152, 219, 0.9);
border: none;
border-radius: 50%;
color: #fff;
font-size: 1.5rem;
cursor: pointer;
transition: background 0.3s;
}
.play-promo:hover {
background: #3498db;
}
.course-card-pricing {
padding: 1.5rem;
}
.price-large {
text-align: center;
margin-bottom: 1.5rem;
}
.old-price {
font-size: 1.2rem;
color: #999;
text-decoration: line-through;
margin-right: 0.5rem;
}
.current-price {
font-size: 2rem;
font-weight: bold;
color: #2c3e50;
}
.price-large.free {
font-size: 2rem;
color: #27ae60;
}
.money-back {
text-align: center;
color: #666;
font-size: 0.9rem;
margin: 1rem 0;
}
.course-includes {
border-top: 1px solid #eee;
padding-top: 1.5rem;
}
.course-includes h4 {
margin-bottom: 1rem;
color: #2c3e50;
}
.course-includes ul {
list-style: none;
}
.course-includes li {
margin-bottom: 0.5rem;
color: #666;
}
/* Course Main Content */
.course-main {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 2rem;
margin: 2rem 0;
}
.course-section {
background: #fff;
padding: 2rem;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
margin-bottom: 2rem;
}
.course-section h3 {
margin-bottom: 1.5rem;
color: #2c3e50;
font-size: 1.3rem;
}
.learn-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
}
.learn-item {
padding: 0.5rem 0;
color: #27ae60;
}
/* Course Sections Accordion */
.course-sections {
border: 1px solid #eee;
border-radius: 4px;
}
.section-item {
border-bottom: 1px solid #eee;
}
.section-item:last-child {
border-bottom: none;
}
.section-header {
padding: 1rem;
background: #f8f9fa;
cursor: pointer;
display: flex;
align-items: center;
gap: 0.5rem;
}
.section-toggle {
font-size: 0.8rem;
color: #666;
}
.section-title {
flex: 1;
font-weight: 500;
}
.section-meta {
color: #666;
font-size: 0.9rem;
}
.section-content {
padding: 1rem;
display: none;
}
.section-item:first-child .section-content {
display: block;
}
.lesson-list {
list-style: none;
}
.lesson-item {
padding: 0.5rem 0;
display: flex;
align-items: center;
gap: 0.5rem;
}
.lesson-icon {
width: 24px;
text-align: center;
}
.lesson-title {
flex: 1;
}
.lesson-duration {
color: #666;
font-size: 0.85rem;
}
.btn-preview {
padding: 0.25rem 0.5rem;
background: #3498db;
color: #fff;
border: none;
border-radius: 3px;
font-size: 0.8rem;
cursor: pointer;
}
.btn-preview:hover {
background: #2980b9;
}
/* Reviews */
.reviews-list {
margin-top: 2rem;
}
.review-item {
padding: 1.5rem;
border-bottom: 1px solid #eee;
}
.review-item:last-child {
border-bottom: none;
}
.reviewer {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 0.5rem;
}
.reviewer-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
object-fit: cover;
}
.reviewer-name {
font-weight: 500;
color: #2c3e50;
}
.review-date {
font-size: 0.85rem;
color: #999;
margin-left: 0.5rem;
}
.review-rating {
margin-bottom: 0.5rem;
}
.star {
color: #ddd;
font-size: 1.2rem;
}
.star.filled,
.star.selected {
color: #f39c12;
}
.review-content {
color: #666;
line-height: 1.6;
}
.review-form {
background: #f8f9fa;
padding: 1.5rem;
border-radius: 4px;
margin-bottom: 2rem;
}
.rating-select {
margin-bottom: 1rem;
}
.rating-select label {
display: block;
margin-bottom: 0.5rem;
}
.stars {
font-size: 1.5rem;
cursor: pointer;
}
.stars .star {
margin-right: 0.25rem;
}
/* Course Player */
.course-player-page {
overflow: hidden;
height: 100vh;
}
.course-player {
display: flex;
flex-direction: column;
height: 100vh;
}
.player-header {
background: #2c3e50;
color: #fff;
padding: 1rem 0;
flex-shrink: 0;
}
.player-header .container {
display: flex;
justify-content: space-between;
align-items: center;
}
.player-header-left {
display: flex;
align-items: center;
gap: 2rem;
}
.back-link {
color: #fff;
opacity: 0.8;
text-decoration: none;
}
.back-link:hover {
opacity: 1;
}
.player-header-left h1 {
font-size: 1.2rem;
font-weight: 500;
}
.course-progress {
display: flex;
align-items: center;
gap: 1rem;
min-width: 200px;
}
.progress-bar {
flex: 1;
height: 6px;
background: rgba(255,255,255,0.2);
border-radius: 3px;
overflow: hidden;
}
.progress-bar .progress {
height: 100%;
background: #27ae60;
}
.player-container {
display: flex;
flex: 1;
overflow: hidden;
}
/* Player Sidebar */
.player-sidebar {
width: 350px;
background: #fff;
border-right: 1px solid #ddd;
overflow-y: auto;
flex-shrink: 0;
}
.sidebar-header {
padding: 1rem;
background: #f8f9fa;
border-bottom: 1px solid #ddd;
display: flex;
justify-content: space-between;
align-items: center;
}
.sidebar-header h3 {
font-size: 1.1rem;
color: #2c3e50;
}
.sidebar-section {
border-bottom: 1px solid #eee;
}
.sidebar-section .section-title {
padding: 1rem;
background: #fff;
cursor: pointer;
display: flex;
align-items: center;
gap: 0.5rem;
}
.sidebar-section .section-title:hover {
background: #f8f9fa;
}
.sidebar-section .section-title .toggle {
font-size: 0.8rem;
color: #666;
}
.sidebar-section .section-title .title {
flex: 1;
font-weight: 500;
}
.sidebar-section .section-title .count {
color: #666;
font-size: 0.9rem;
}
.section-lessons {
padding: 0.5rem 0;
}
.lesson-link {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.75rem 1rem 0.75rem 2rem;
text-decoration: none;
color: #333;
border-left: 3px solid transparent;
}
.lesson-link:hover {
background: #f8f9fa;
}
.lesson-link.active {
background: #e8f0fe;
border-left-color: #3498db;
}
.lesson-status {
width: 20px;
text-align: center;
}
.completed {
color: #27ae60;
font-weight: bold;
}
.not-completed {
color: #999;
}
.lesson-link .lesson-title {
flex: 1;
font-size: 0.9rem;
}
.lesson-link .lesson-duration {
font-size: 0.8rem;
color: #999;
}
/* Player Main */
.player-main {
flex: 1;
background: #f8f9fa;
overflow-y: auto;
padding: 2rem;
}
.lesson-container {
max-width: 900px;
margin: 0 auto;
}
.lesson-title {
font-size: 1.8rem;
color: #2c3e50;
margin-bottom: 1.5rem;
}
.video-container {
background: #000;
border-radius: 8px;
overflow: hidden;
margin-bottom: 1.5rem;
}
.lesson-description {
background: #fff;
padding: 1.5rem;
border-radius: 8px;
margin: 1.5rem 0;
}
.lesson-description h3 {
margin-bottom: 1rem;
color: #2c3e50;
}
.lesson-actions {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 1.5rem;
}
.lesson-navigation {
display: flex;
gap: 1rem;
}
.completed-badge {
background: #27ae60;
color: #fff;
padding: 0.5rem 1rem;
border-radius: 4px;
}
.no-lesson-selected {
text-align: center;
padding: 4rem;
color: #666;
}
/* Footer */
.site-footer {
background: #2c3e50;
color: #fff;
padding: 3rem 0 1rem;
}
.footer-widgets {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
margin-bottom: 2rem;
}
.footer-widget h4 {
color: #fff;
margin-bottom: 1rem;
}
.footer-widget p {
color: #bdc3c7;
line-height: 1.6;
}
.footer-widget ul {
list-style: none;
}
.footer-widget li {
margin-bottom: 0.5rem;
}
.footer-widget a {
color: #bdc3c7;
text-decoration: none;
transition: color 0.3s;
}
.footer-widget a:hover {
color: #fff;
}
.social-links a {
display: inline-block;
margin-right: 1rem;
}
.footer-bottom {
text-align: center;
padding-top: 2rem;
border-top: 1px solid #34495e;
color: #bdc3c7;
}
/* Responsive */
@media (max-width: 1024px) {
.course-header .container {
grid-template-columns: 1fr;
}
.course-main {
grid-template-columns: 1fr;
}
}
@media (max-width: 768px) {
.main-header .container {
flex-direction: column;
gap: 1rem;
}
.main-nav ul {
flex-wrap: wrap;
justify-content: center;
}
.search-bar {
width: 100%;
}
.search-bar input {
width: 100%;
}
.hero h1 {
font-size: 2rem;
}
.hero-stats {
flex-direction: column;
gap: 1rem;
}
.hero-actions {
flex-direction: column;
}
.course-grid {
grid-template-columns: 1fr;
}
.categories-grid {
grid-template-columns: repeat(2, 1fr);
}
.stats-grid {
grid-template-columns: 1fr;
}
.player-container {
flex-direction: column;
}
.player-sidebar {
width: 100%;
height: 300px;
}
.player-header .container {
flex-direction: column;
gap: 1rem;
}
.player-header-left {
flex-direction: column;
gap: 0.5rem;
text-align: center;
}
.course-progress {
width: 100%;
}
}
@media (max-width: 480px) {
.categories-grid {
grid-template-columns: 1fr;
}
.learn-grid {
grid-template-columns: 1fr;
}
.footer-widgets {
grid-template-columns: 1fr;
text-align: center;
}
.social-links {
justify-content: center;
}
}

📝 How to Use This Project (Step-by-Step Guide)

Step 1: Install Local Server

  1. Download and install XAMPP from apachefriends.org
  2. Launch XAMPP Control Panel
  3. Start Apache and MySQL services

Step 2: Create Project Folder

  1. Navigate to C:\xampp\htdocs\ (Windows) or /Applications/XAMPP/htdocs/ (Mac)
  2. Create a new folder named online-course-system

Step 3: Set Up Database

  1. Open browser and go to http://localhost/phpmyadmin
  2. Click on "SQL" tab
  3. Copy the entire SQL from database/course_system.sql
  4. Paste and click "Go" to create database and tables

Step 4: Create Password Hashes

Create a file named hash.php in project root:

<?php
echo "admin123 hash: " . password_hash('admin123', PASSWORD_DEFAULT) . "\n";
echo "instructor123 hash: " . password_hash('instructor123', PASSWORD_DEFAULT) . "\n";
echo "student123 hash: " . password_hash('student123', PASSWORD_DEFAULT);
?>

Run it: http://localhost/online-course-system/hash.php
Copy the hashes and update them in the SQL insert statements for the users.

Step 5: Configure Database Connection

Open includes/config.php and verify:

define('DB_HOST', 'localhost');
define('DB_NAME', 'course_system');
define('DB_USER', 'root');
define('DB_PASS', '');

Step 6: Create Required Directories

Create these folders and set proper permissions:

  • assets/images/courses/ - for course thumbnails
  • assets/images/instructors/ - for instructor photos
  • uploads/lessons/ - for video lessons
  • uploads/materials/ - for course materials

Step 7: Download Third-Party Libraries

  1. Download TinyMCE from tiny.cloud and place in assets/vendor/tinymce/
  2. Download Video.js from videojs.com and place in assets/vendor/video.js/

Step 8: Test the Application

Public Side:

  • Open: http://localhost/online-course-system/
  • Browse courses by category
  • View course details
  • Register as a new student

Student Account:

  • Login with: Username: jane.smith, Password: student123
  • Enroll in courses
  • Access course content
  • Track learning progress

Instructor Account:

  • Login with: Username: john.doe, Password: instructor123
  • Create new courses
  • Add lessons and sections
  • View student enrollments

Admin Account:

  • Login with: Username: admin, Password: admin123
  • Manage users
  • Approve/reject courses
  • View platform statistics

Step 9: Add Sample Content

  1. Login as instructor
  2. Go to Create Course and add a new course
  3. Add sections to organize content
  4. Add lessons with videos or materials
  5. Publish the course
  6. Login as student and enroll in the course

Step 10: Configure Settings

  1. Login as admin
  2. Go to Settings
  3. Update site title, description
  4. Set commission rate
  5. Configure email settings

🎯 Features Summary

Student Features:

  • ✅ Browse courses by category
  • ✅ View detailed course information
  • ✅ Enroll in free or paid courses
  • ✅ Access course content with video player
  • ✅ Track learning progress
  • ✅ Mark lessons as completed
  • ✅ Leave reviews and ratings
  • ✅ Add courses to wishlist
  • ✅ View enrollment history

Instructor Features:

  • ✅ Create and manage courses
  • ✅ Organize content with sections
  • ✅ Upload video lessons and materials
  • ✅ Set pricing and discounts
  • ✅ View student enrollments
  • ✅ Track earnings
  • ✅ Update profile and expertise

Admin Features:

  • ✅ Dashboard with statistics
  • ✅ User management
  • ✅ Course approval system
  • ✅ Category management
  • ✅ Payment tracking
  • ✅ Site settings configuration
  • ✅ Instructor application management

Technical Features:

  • ✅ Secure authentication with roles
  • ✅ Password hashing
  • ✅ SQL injection prevention
  • ✅ XSS protection
  • ✅ Responsive design
  • ✅ Video streaming
  • ✅ Progress tracking
  • ✅ File upload handling
  • ✅ Email notifications

🚀 Future Enhancements

  1. Payment Integration: Stripe/PayPal for paid courses
  2. Certificate Generation: Auto-generate certificates on completion
  3. Discussion Forums: Course-specific discussion areas
  4. Quizzes & Assignments: Interactive assessments
  5. Live Classes: Integration with Zoom/YouTube Live
  6. Mobile App: React Native or Flutter apps
  7. Multi-language Support: Interface in multiple languages
  8. Course Bundles: Group courses for discount
  9. Subscription Model: Monthly/yearly subscriptions
  10. Affiliate System: Referral program for instructors
  11. Analytics Dashboard: Detailed student performance analytics
  12. Email Marketing: Automated email campaigns
  13. Social Login: Login with Facebook/Google
  14. Course Import/Export: Bulk course creation
  15. API: REST API for mobile apps
  16. Progress Reports: Download progress as PDF
  17. Course Recommendations: AI-powered suggestions
  18. Wishlist Reminders: Email when courses go on sale
  19. Course Reviews: Detailed review system
  20. Instructor Payouts: Automated payment system

This comprehensive Online Course Management System provides a complete solution for creating and managing online learning platforms!

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper