Olumide
Members-
Posts
126 -
Joined
-
Last visited
-
Days Won
3
Olumide last won the day on November 25 2023
Olumide had the most liked content!
Profile Information
-
Gender
Male
- Donation Link
Recent Profile Visitors
2,570 profile views
Olumide's Achievements
-
Thank you sir, but I have created a table for user_responses and yet, while using the pagination (next, previous) the selected option are all deselected. Attached is the screenshot of page1 and page 2 and database with my script DROP TABLE IF EXISTS `exams`; CREATE TABLE IF NOT EXISTS `exams` ( `id` int NOT NULL AUTO_INCREMENT, `title` varchar(255) DEFAULT NULL, `description` text, `duration` int DEFAULT NULL, `pass_mark` int NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=42 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; DROP TABLE IF EXISTS `questions`; CREATE TABLE IF NOT EXISTS `questions` ( `id` int NOT NULL AUTO_INCREMENT, `exam_id` int NOT NULL, `question` text NOT NULL, `answer_a` varchar(255) DEFAULT NULL, `answer_b` varchar(255) DEFAULT NULL, `answer_c` varchar(255) DEFAULT NULL, `answer_d` varchar(255) DEFAULT NULL, `correct_answer` char(1) DEFAULT NULL, PRIMARY KEY (`id`), KEY `exam_id` (`exam_id`) ) ENGINE=MyISAM AUTO_INCREMENT=252 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; DROP TABLE IF EXISTS `results`; CREATE TABLE IF NOT EXISTS `results` ( `id` int NOT NULL AUTO_INCREMENT, `user_id` int DEFAULT NULL, `exam_id` int DEFAULT NULL, `score` int DEFAULT NULL, PRIMARY KEY (`id`), KEY `user_id` (`user_id`), KEY `exam_id` (`exam_id`) ) ENGINE=MyISAM AUTO_INCREMENT=37 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; DROP TABLE IF EXISTS `users`; CREATE TABLE IF NOT EXISTS `users` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(100) DEFAULT NULL, `email` varchar(100) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, `role` enum('admin','student') DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; DROP TABLE IF EXISTS `user_responses`; CREATE TABLE IF NOT EXISTS `user_responses` ( `id` int NOT NULL AUTO_INCREMENT, `user_id` int NOT NULL, `exam_id` int NOT NULL, `question_id` int NOT NULL, `selected_option` varchar(255) NOT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=27 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; exam.php <?php if (session_status() == PHP_SESSION_NONE) { session_start(); } include 'db_connect.php'; if (!isset($_SESSION['fullName']) || !isset($_SESSION['email']) || !isset($_SESSION['exam_id']) || !isset($_SESSION['user_id'])) { header('Location: instruction.php?exam_id=' . $_SESSION['exam_id']); exit; } $exam_id = $_SESSION['exam_id']; $user_id = $_SESSION['user_id']; $fullName = $_SESSION['fullName']; $email = $_SESSION['email']; $stmt = $pdo->prepare('SELECT * FROM exams WHERE id = ?'); $stmt->execute([$exam_id]); $exam = $stmt->fetch(PDO::FETCH_ASSOC); if (!$exam) { die('Exam not found'); } $stmt = $pdo->prepare('SELECT * FROM questions WHERE exam_id = ?'); $stmt->execute([$exam_id]); $questions = $stmt->fetchAll(PDO::FETCH_ASSOC); $remainingTime = $_SESSION['remaining_time'] ?? ($exam['duration'] * 60); if (isset($_SESSION['exam_start_time'])) { $elapsedTime = time() - $_SESSION['exam_start_time']; $remainingTime = max(0, $remainingTime - $elapsedTime); } else { $_SESSION['exam_start_time'] = time(); } $_SESSION['remaining_time'] = $remainingTime; $selected_answers = $_SESSION['selected_answers'] ?? []; $questionsPerPage = 5; $totalQuestions = count($questions); $totalPages = ceil($totalQuestions / $questionsPerPage); $page = isset($_GET['page']) ? (int)$_GET['page'] : 1; $page = max(1, min($page, $totalPages)); $offset = ($page - 1) * $questionsPerPage; $questionsToDisplay = array_slice($questions, $offset, $questionsPerPage); ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title><?php echo htmlspecialchars($exam['title']); ?></title> <link rel="stylesheet" type="text/css" href="styles.css"> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script> $(document).ready(function() { let duration = <?php echo $remainingTime; ?>; let timer; function startTimer() { timer = setInterval(function() { duration--; if (duration < 0) duration = 0; $('#timer').text(`${Math.floor(duration / 60)}:${duration % 60 < 10 ? '0' : ''}${duration % 60}`); if (duration === 0) { clearInterval(timer); submitExam(); } else if (duration <= 30) { $('#examForm input[type="radio"]').prop('disabled', true); if (duration === 5) { new Audio('alarm.mp3').play(); } } }, 1000); } startTimer(); function saveAnswers(callback) { let answers = {}; $('#examForm input[type="radio"]:checked').each(function() { let questionId = $(this).attr('name').match(/\d+/)[0]; let value = $(this).val(); answers[questionId] = value; }); $.ajax({ url: 'save_answers.php', type: 'POST', data: { answers: JSON.stringify(answers) }, success: function(response) { if (callback) callback(); } }); } function submitExam() { clearInterval(timer); let answers = {}; $('#examForm input[type="radio"]:checked').each(function() { let questionId = $(this).attr('name').match(/\d+/)[0]; let value = $(this).val(); answers[questionId] = value; }); $('<input>').attr({ type: 'hidden', name: 'selected_answers', value: JSON.stringify(answers) }).appendTo('#examForm'); $.ajax({ url: 'submit_exam.php', type: 'POST', data: $('#examForm').serialize(), success: function(response) { $('#examStatus').html(response); $('#examForm').hide(); }, error: function() { $('#examStatus').html('Error submitting exam.'); } }); } $('#examForm').on('submit', function(e) { e.preventDefault(); if (duration > 0) { if (confirm('Are you sure you want to submit the exam?')) { saveAnswers(submitExam); } else { if (timer) clearInterval(timer); startTimer(); } } else { submitExam(); } }); $('.pagination a').on('click', function(e) { e.preventDefault(); saveAnswers(function() { window.location.href = $(this).attr('href'); }.bind(this)); }); function preselectAnswers() { let selectedAnswers = <?php echo json_encode($selected_answers); ?>; for (let questionId in selectedAnswers) { let answer = selectedAnswers[questionId]; $(`input[name="answers[${questionId}]"][value="${answer}"]`).prop('checked', true); } } preselectAnswers(); }); </script> </head> <body> <div class="header"> <div class="timer">Time Remaining: <span id="timer"></span></div> <div class="subject"> <h1><?php echo htmlspecialchars($exam['title']); ?></h1> </div> <div class="name"> <?php echo htmlspecialchars($fullName); ?> </div> </div> <div style="padding-top: 60px; height: calc(100vh - 60px); overflow: auto;"> <form id="examForm"> <input type="hidden" name="exam_id" value="<?php echo htmlspecialchars($exam['id']); ?>"> <?php foreach ($questionsToDisplay as $index => $question): ?> <div class="question"> <p><?php echo ($offset + $index + 1) . '. ' . htmlspecialchars($question['question']); ?></p> <?php $options = [ 'A' => $question['answer_a'] ?? '', 'B' => $question['answer_b'] ?? '', 'C' => $question['answer_c'] ?? '', 'D' => $question['answer_d'] ?? '', ]; ?> <ul style="list-style-type: none;"> <?php foreach ($options as $key => $option): ?> <?php if (!empty($option)): ?> <li> <label> <input type="radio" name="answers[<?php echo $question['id']; ?>]" value="<?php echo htmlspecialchars($key); ?>" <?php echo (isset($selected_answers[$question['id']]) && $selected_answers[$question['id']] === $key) ? 'checked' : ''; ?>> <?php echo htmlspecialchars($key . '. ' . $option); ?> </label> </li> <?php endif; ?> <?php endforeach; ?> </ul> </div> <?php endforeach; ?> <div class="pagination"> <?php if ($page > 1): ?> <a href="?page=<?php echo $page - 1; ?>">« Previous</a> <?php endif; ?> <?php if ($page < $totalPages): ?> <a href="?page=<?php echo $page + 1; ?>">Next »</a> <?php endif; ?> </div> <div style="text-align: center;"> <button type="submit" style="display: inline-block;">Submit</button> </div> </form> <div id="examStatus"></div> </div> </body> </html> save_answers.php <?php if (session_status() == PHP_SESSION_NONE) { session_start(); } include 'db_connect.php'; if (!isset($_SESSION['exam_id']) || !isset($_SESSION['user_id'])) { die('Invalid request'); } $exam_id = $_SESSION['exam_id']; $user_id = $_SESSION['user_id']; $answers = json_decode($_POST['answers'], true); if (!$answers) { die('No answers to save'); } $_SESSION['selected_answers'] = array_merge($_SESSION['selected_answers'] ?? [], $answers); try { foreach ($answers as $question_id => $selected_option) { $stmt = $pdo->prepare('REPLACE INTO user_responses (user_id, exam_id, question_id, selected_option) VALUES (?, ?, ?, ?)'); $stmt->execute([$user_id, $exam_id, $question_id, $selected_option]); } echo 'Answers saved successfully'; } catch (PDOException $e) { echo 'Error saving answers: ' . $e->getMessage(); } submit_exam.php <?php if (session_status() == PHP_SESSION_NONE) { session_start(); } include 'db_connect.php'; // Ensure this file sets up the $pdo variable if ($_SERVER['REQUEST_METHOD'] === 'POST') { $exam_id = $_SESSION['exam_id']; $user_id = $_SESSION['user_id']; $selected_answers = json_decode($_POST['selected_answers'], true); // Insert or update user responses foreach ($selected_answers as $question_id => $selected_option) { $stmt = $pdo->prepare('REPLACE INTO user_responses (user_id, exam_id, question_id, selected_option) VALUES (?, ?, ?, ?)'); $stmt->execute([$user_id, $exam_id, $question_id, $selected_option]); } // Calculate the score $score = 0; foreach ($selected_answers as $question_id => $selected_option) { $stmt = $pdo->prepare('SELECT correct_answer FROM questions WHERE id = ?'); $stmt->execute([$question_id]); $correct_answer = $stmt->fetchColumn(); if ($correct_answer === $selected_option) { $score++; } } // Insert or update the result in the results table $stmt = $pdo->prepare('REPLACE INTO results (user_id, exam_id, score) VALUES (?, ?, ?)'); $stmt->execute([$user_id, $exam_id, $score]); // Destroy the session session_unset(); session_destroy(); // Response message echo "Exam submitted successfully! Your score is: $score"; } ?> Screen shot
-
Hi, I am having issues with this cbt project whereby my questions are selected 5 per page and when the user click on NEXT, the first page selected radio button option should be saved so that when the user click on previous button, he should be able to see the selected options. But I have been finding difficult to do. And I don't think it is right to create another table again to store the user answers because in each subjects, there are more than 15 questions. Please here is exam script and the screen short of the first page of the exam. <!DOCTYPE html> <html> <head> <title><?php echo htmlspecialchars($exam['title']); ?></title> <link rel="stylesheet" type="text/css" href="styles.css"> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script> $(document).ready(function() { let duration = <?php echo $remainingTime; ?>; let timer; function startTimer() { timer = setInterval(function() { duration--; if (duration < 0) duration = 0; $('#timer').text(`${Math.floor(duration / 60)}:${duration % 60 < 10 ? '0' : ''}${duration % 60}`); if (duration === 0) { clearInterval(timer); submitExam(); // Automatically submit the form when time expires } else if (duration <= 30) { // Disable form elements when less than 30 seconds remain $('#examForm input[type="radio"]').prop('disabled', true); if (duration === 5) { // Play alarm sound if time is below 5 seconds new Audio('alarm.mp3').play(); } } }, 1000); } startTimer(); function saveAnswers() { let answers = {}; $('#examForm input[type="radio"]:checked').each(function() { let name = $(this).attr('name'); let value = $(this).val(); answers[name] = value; }); return $.ajax({ url: 'save_answers.php', type: 'POST', data: { page: <?php echo $page; ?>, answers: JSON.stringify(answers) } }); } function submitExam() { clearInterval(timer); let answers = {}; $('#examForm input[type="radio"]:checked').each(function() { let name = $(this).attr('name'); let value = $(this).val(); answers[name] = value; }); $('<input>').attr({ type: 'hidden', name: 'selected_answers', value: JSON.stringify(answers) }).appendTo('#examForm'); $.ajax({ url: 'submit_exam.php', type: 'POST', data: $('#examForm').serialize(), success: function(response) { $('#examStatus').html(response); $('#examForm').hide(); // Hide the form after submission }, error: function() { $('#examStatus').html('Error submitting exam.'); } }); } $('#examForm').on('submit', function(e) { e.preventDefault(); if (duration > 0) { if (confirm('Are you sure you want to submit the exam?')) { saveAnswers().done(function() { submitExam(); }); } else { if (timer) clearInterval(timer); startTimer(); } } else { submitExam(); } }); $('.pagination a').on('click', function(e) { e.preventDefault(); saveAnswers().done(function() { window.location.href = $(this).attr('href'); // Navigate to the new page }.bind(this)); }); function preselectAnswers() { let selectedAnswers = <?php echo json_encode($selected_answers); ?>; for (let questionId in selectedAnswers) { let answer = selectedAnswers[questionId]; $(`input[name="answers[${questionId}]"][value="${answer}"]`).prop('checked', true); } } preselectAnswers(); }); </script> </head> <body> <div class="header"> <div class="timer">Time Remaining: <span id="timer"></span></div> <div class="subject"> <h1><?php echo htmlspecialchars($exam['title']); ?></h1> </div> <div class="name"> <?php echo htmlspecialchars($fullName); ?> </div> </div> <div style="padding-top: 60px; height: calc(100vh - 60px); overflow: auto;"> <!-- Adjusted for fixed header --> <form id="examForm"> <input type="hidden" name="exam_id" value="<?php echo htmlspecialchars($exam['id']); ?>"> <?php foreach ($questionsToDisplay as $index => $question): ?> <div class="question"> <p><?php echo ($offset + $index + 1) . '. ' . htmlspecialchars($question['question']); ?></p> <?php $options = isset($question['options']) ? json_decode($question['options'], true) : null; if (is_null($options) || !is_array($options)) { $options = [ 'A' => $question['answer_a'] ?? '', 'B' => $question['answer_b'] ?? '', 'C' => $question['answer_c'] ?? '', 'D' => $question['answer_d'] ?? '', ]; } ?> <ul style="list-style-type: none;"> <?php foreach ($options as $key => $option): ?> <?php if (!empty($option)): ?> <li> <label> <input type="radio" name="answers[<?php echo $question['id']; ?>]" value="<?php echo htmlspecialchars($key); ?>" <?php echo (isset($_SESSION['selected_answers'][$question['id']]) && $_SESSION['selected_answers'][$question['id']] === $key) ? 'checked' : ''; ?>> <?php echo htmlspecialchars($key . '. ' . $option); ?> </label> </li> <?php endif; ?> <?php endforeach; ?> </ul> </div> <?php endforeach; ?> <div class="pagination"> <?php if ($page > 1): ?> <a href="?page=<?php echo ($page - 1); ?>" class="pagination button">« Previous</a> <?php endif; ?> <?php if ($page < $totalPages): ?> <a href="?page=<?php echo ($page + 1); ?>" class="pagination button">Next »</a> <?php endif; ?> </div> <button type="submit">Submit Exam</button> </form> <div id="examStatus"></div> </div> </body> </html> save_answers.php <?php session_start(); if ($_SERVER['REQUEST_METHOD'] === 'POST') { $page = isset($_POST['page']) ? (int)$_POST['page'] : 0; $answers = isset($_POST['answers']) ? json_decode($_POST['answers'], true) : []; if (!isset($_SESSION['selected_answers'])) { $_SESSION['selected_answers'] = []; } // Update session with the received answers $_SESSION['selected_answers'][$page] = $answers; echo 'Answers saved.'; } ?> screen short
-
Hi, I am currently using a shared hosting provider that includes cPanel, MySQL database support, and phpMyAdmin, but I've been experiencing frequent fluctuations and downtime. I'm looking for a more stable and reliable hosting solution that is also cost-effective. Here are my requirements: cPanel or Equivalent: I need a control panel for easy website and server management. MySQL Database Support: Reliable MySQL database hosting is essential. phpMyAdmin: A web-based interface for managing MySQL databases. Uptime and Stability: A hosting provider known for good uptime and stability. Cost-Effective: Affordable pricing, ideally comparable to shared hosting costs. Additional Features: Any additional features like automatic backups, SSL certificates, and support for PHP applications would be a plus. Could you please recommend any hosting providers that meet these criteria? Personal experiences and specific plans that you have had success with would be greatly appreciated. Thank you for your assistance!
-
You'll need to install Composer on your web server. Composer is a dependency manager for PHP that allows you to easily manage libraries and packages. Go to the https://getcomposer.org/, download the Installer for Composer depending on your OS. Open the downloaded Composer-Setup.exe (Windows OS as an example) file. Follow the prompts in the installation wizard. Make sure to select the option to add Composer to the system PATH during installation. Verify Installation: Open Command Prompt. Type composer and press Enter. You should see the Composer version and available commands, confirming that Composer is installed and accessible globally. Open Command Prompt and navigate to your project directory: cd path\to\your\project\directory Use Composer to install the PhpSpreadsheet library by creating a composer.json file and running composer install. Include the Composer autoload file in your PHP script and use PhpSpreadsheet to read your Excel files.
-
To read .xlsx files using PHP 8, you can use the PhpSpreadsheet library. It's the successor to PHPExcel and fully supports PHP 8. You can run this command "composer require phpoffice/phpspreadsheet" and Once you have PhpSpreadsheet installed, you can use it to read .xlsx files. Here's a basic example: <?php require 'vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\IOFactory; try { $spreadsheet = IOFactory::load('path/to/your/file.xlsx'); $sheet = $spreadsheet->getActiveSheet(); // Get the highest row and column numbers referenced in the worksheet $highestRow = $sheet->getHighestRow(); // e.g. 10 $highestColumn = $sheet->getHighestColumn(); // e.g 'F' // Iterate over each row in the worksheet in turn for ($row = 1; $row <= $highestRow; $row++) { $rowData = $sheet->rangeToArray('A' . $row . ':' . $highestColumn . $row, NULL, TRUE, FALSE); print_r($rowData); } } catch (Exception $e) { echo 'Error loading file: ', $e->getMessage(); } ?>
-
Thank you so much for the support and all the guidance. Though, I have solved the problem by using instascan instead of the previous quagga and html5 qrcode. But getting worked is nothing but to take to practices all the programming advices you have highlighted which is very essential. I cannot but to always thank you all in this forum for your help and I can say ever since I have joined this forum, I have never for once regret that. You are all amazing. Cheers
-
I want to design an attendance system such that the class teacher can scan students' ID card QR code using their phone, and it will be recorded immediately in the database. Currently, I have tested HTML QR code and Quagga, but I haven't tested scanning the ID card yet. I am only testing with a phone and PC camera because I want the user to be able to use either device to scan the student ID card. I'm not sure where the error is. Could anyone please enlighten me? Here is the dashboard.php where the user can click scan ID Card <?php // pages/dashboard.php session_start(); if (!isset($_SESSION['username'])) { header('Location: login.php'); exit(); } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="../css/styles.css"> <title>Dashboard</title> </head> <body> <div class="container"> <header> <div id="branding"> <h1>QR Smart Attendance</h1> </div> <nav> <ul> <li><a href="dashboard.php">Dashboard</a></li> <li><a href="generate_id_card.php">Generate ID Card</a></li> <li><a href="record_attendance.php">Record Attendance</a></li> <li><a href="transfer_attendance.php">Transfer Attendance</a></li> <li><a href="logout.php">Logout</a></li> </ul> </nav> </header> <div class="dashboard-container"> <h2>Welcome, <?php echo htmlspecialchars($_SESSION['username']); ?></h2> <!-- Add a button for scanning ID cards --> <button id="scanButton">Scan ID Card</button> <!-- Container for the scanner --> <div id="scanner-container" style="width: 100%; height: 400px; display:none;"></div> <script src="https://unpkg.com/@ericblade/quagga2/dist/quagga.min.js"></script> <script> document.getElementById('scanButton').addEventListener('click', function() { // Display the scanner container document.getElementById('scanner-container').style.display = 'block'; Quagga.init({ inputStream: { name: "Live", type: "LiveStream", target: document.querySelector('#scanner-container'), constraints: { width: 640, height: 480, facingMode: "environment" // or "user" for front-facing camera } }, decoder: { readers: ["qr_reader"] // Use the QR reader }, locate: true // Enable locating the QR code in the image }, function(err) { if (err) { console.error('QuaggaJS initialization failed:', err); return; } console.log("QuaggaJS initialization finished. Ready to start"); Quagga.start(); }); // Handle scanned results Quagga.onDetected(function(result) { if (result && result.codeResult && result.codeResult.code) { console.log('Scanned code:', result.codeResult.code); // Redirect to record_attendance.php with student_id or handle accordingly window.location.href = 'record_attendance.php?student_id=' + result.codeResult.code; } else { console.warn('No code detected'); } }); // Optional: Handle processing errors Quagga.onProcessed(function(result) { var drawingCtx = Quagga.canvas.ctx.overlay, drawingCanvas = Quagga.canvas.dom.overlay; if (result) { if (result.boxes) { drawingCtx.clearRect(0, 0, drawingCanvas.width, drawingCanvas.height); result.boxes.filter(function(box) { return box !== result.box; }).forEach(function(box) { Quagga.ImageDebug.drawPath(box, { x: 0, y: 1 }, drawingCtx, { color: "green", lineWidth: 2 }); }); } if (result.box) { Quagga.ImageDebug.drawPath(result.box, { x: 0, y: 1 }, drawingCtx, { color: "#00F", lineWidth: 2 }); } if (result.codeResult && result.codeResult.code) { Quagga.ImageDebug.drawPath(result.line, { x: 'x', y: 'y' }, drawingCtx, { color: 'red', lineWidth: 3 }); } } }); }); </script> </div> </div> </body> </html> And here is record_attendance.php <?php // pages/record_attendance.php session_start(); if (!isset($_SESSION['username'])) { header('Location: login.php'); exit(); } require_once '../includes/db.php'; // Include db.php for database connection and functions // Check if a student ID is scanned and process attendance if (isset($_GET['student_id'])) { $student_id = sanitizeInput($_GET['student_id']); $date = date('Y-m-d'); // Check if attendance record already exists for today $query = "SELECT * FROM attendance WHERE student_id = ? AND date = ?"; $stmt = $conn->prepare($query); $stmt->bind_param("is", $student_id, $date); $stmt->execute(); $stmt->store_result(); if ($stmt->num_rows == 0) { // If no record exists, insert new attendance record $query = "INSERT INTO attendance (student_id, date, status) VALUES (?, ?, 'present')"; $stmt = $conn->prepare($query); $stmt->bind_param("is", $student_id, $date); $stmt->execute(); // Optional: Redirect back to dashboard after recording attendance header('Location: dashboard.php'); exit(); } else { // Optional: Handle case where attendance is already recorded for today echo "Attendance already recorded for today."; // Redirect or display message as needed } } else { // Handle case where no student ID is scanned echo "No student ID received. Please scan a valid student ID."; // Redirect or display message as needed } ?> Here is generate_id_card.php <?php // pages/generate_id_card.php session_start(); if (!isset($_SESSION['username']) || $_SESSION['role'] != 'admin') { header('Location: login.php'); exit(); } require_once '../includes/db.php'; // Ensure this path is correct require_once '../includes/functions.php'; if ($_SERVER['REQUEST_METHOD'] == 'POST') { $name = sanitizeInput($_POST['name']); $class = sanitizeInput($_POST['class']); $photo = $_FILES['photo']; if ($photo['error'] == 0) { $photo_path = '../images/' . basename($photo['name']); move_uploaded_file($photo['tmp_name'], $photo_path); // Insert student data into the database $insert_query = "INSERT INTO students (name, class, photo) VALUES (?, ?, ?)"; $stmt = $conn->prepare($insert_query); $stmt->bind_param("sss", $name, $class, $photo_path); $stmt->execute(); // Retrieve the inserted student's ID $student_id = $conn->insert_id; // Generate ID card with the student's details $id_card = generateIDCard($name, $class, $photo_path); echo "<p>ID Card generated: <a href='$id_card'>Download ID Card</a></p>"; } else { echo "<p>Error uploading photo.</p>"; } } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="../css/styles.css"> <title>Generate ID Card</title> </head> <body> <div class="container"> <header> <div id="branding"> <h1>QR Smart Attendance</h1> </div> </header> <div class="generate-container"> <h2>Generate Student ID Card</h2> <form method="post" enctype="multipart/form-data"> <input type="text" name="name" placeholder="Student Name" required> <input type="text" name="class" placeholder="Class" required> <input type="file" name="photo" accept="image/*" required> <button type="submit">Generate</button> </form> </div> </div> </body> </html> Here is functions.php <?php require_once '../vendor/autoload.php'; use Endroid\QrCode\QrCode; use Endroid\QrCode\Writer\PngWriter; function generateIDCard($name, $class, $photo_path) { // Ensure QR code directory exists $qrCodeDir = '../images/qrcodes'; if (!is_dir($qrCodeDir)) { mkdir($qrCodeDir, 0755, true); } // Generate a unique ID for the QR code $uniqueId = uniqid(); // Create the QR code $qrCode = new QrCode($uniqueId); $qrCode->setSize(300); // Set the QR code file path $qrCodePath = "$qrCodeDir/$uniqueId.png"; $qrCode->writeFile($qrCodePath); // Ensure font file exists $fontPath = '../fonts/arial.ttf'; if (!file_exists($fontPath)) { die('Font file not found.'); } // Create the ID card image $idCard = imagecreate(600, 400); $white = imagecolorallocate($idCard, 255, 255, 255); $black = imagecolorallocate($idCard, 0, 0, 0); // Add student details imagettftext($idCard, 20, 0, 20, 50, $black, $fontPath, "Name: $name"); imagettftext($idCard, 20, 0, 20, 100, $black, $fontPath, "Class: $class"); imagettftext($idCard, 20, 0, 20, 150, $black, $fontPath, "ID: $uniqueId"); // Add the student photo $photo = imagecreatefromjpeg($photo_path); if ($photo) { imagecopyresized($idCard, $photo, 400, 20, 0, 0, 160, 160, imagesx($photo), imagesy($photo)); } else { die('Photo file not found.'); } // Add the QR code $qrImage = imagecreatefrompng($qrCodePath); if ($qrImage) { imagecopyresized($idCard, $qrImage, 20, 200, 0, 0, 160, 160, imagesx($qrImage), imagesy($qrImage)); } else { die('QR code file not found.'); } // Ensure ID card directory exists $idCardDir = '../images/idcards'; if (!is_dir($idCardDir)) { mkdir($idCardDir, 0755, true); } // Save the ID card image $idCardPath = "$idCardDir/$uniqueId.png"; imagepng($idCard, $idCardPath); // Free up memory imagedestroy($idCard); imagedestroy($photo); imagedestroy($qrImage); return $idCardPath; } ?> My database DROP TABLE IF EXISTS `attendance`; CREATE TABLE IF NOT EXISTS `attendance` ( `id` int NOT NULL AUTO_INCREMENT, `student_id` int NOT NULL, `date` date NOT NULL, `status` enum('present','absent') NOT NULL, PRIMARY KEY (`id`), KEY `student_id` (`student_id`) ) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; DROP TABLE IF EXISTS `notifications`; CREATE TABLE IF NOT EXISTS `notifications` ( `id` int NOT NULL AUTO_INCREMENT, `message` text NOT NULL, `date` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; -- -------------------------------------------------------- -- -- Table structure for table `students` -- DROP TABLE IF EXISTS `students`; CREATE TABLE IF NOT EXISTS `students` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(100) NOT NULL, `class` varchar(50) NOT NULL, `photo` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; DROP TABLE IF EXISTS `users`; CREATE TABLE IF NOT EXISTS `users` ( `id` int NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL, `password` varchar(255) NOT NULL, `role` enum('admin','teacher') NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`) ) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-
I appreciate you, but that does not give me the options. Though, I pending the project for now as it is taking more time and still no solution. I will still get back on it.
-
I keep getting this error Warning: DOMDocument::loadXML(): Namespace prefix m on oMath is not defined in Entity, line: 1 in C:\wamp64\www\cbt\cbt_exam\vendor\phpoffice\math\src\Math\Reader\OfficeMathML.php on line 39 Call Stack #TimeMemoryFunctionLocation 10.0005449024{main}( )...\upload.php:0 20.0080581080convertDocxToHtml( $filename = 'uploads/Question_me2.docx' )...\upload.php:30 30.0087581080PhpOffice\PhpWord\IOFactory::load( $filename = 'uploads/Question_me2.docx', $readerName = ??? )...\upload.php:120 40.0100581872PhpOffice\PhpWord\Reader\Word2007->load( $docFile = 'uploads/Question_me2.docx' )...\IOFactory.php:89 50.0479598432PhpOffice\PhpWord\Reader\Word2007->readPart( $phpWord = class PhpOffice\PhpWord\PhpWord { private $sections = [0 => class PhpOffice\PhpWord\Element\Section { ... }]; private $collections = ['Bookmarks' => class PhpOffice\PhpWord\Collection\Bookmarks { ... }, 'Titles' => class PhpOffice\PhpWord\Collection\Titles { ... }, 'Footnotes' => class PhpOffice\PhpWord\Collection\Footnotes { ... }, 'Endnotes' => class PhpOffice\PhpWord\Collection\Endnotes { ... }, 'Charts' => class PhpOffice\PhpWord\Collection\Charts { ... }, 'Comments' => class PhpOffice\PhpWord\Collection\Comments { ... }]; private $metadata = ['DocInfo' => class PhpOffice\PhpWord\Metadata\DocInfo { ... }, 'Settings' => class PhpOffice\PhpWord\Metadata\Settings { ... }, 'Compatibility' => class PhpOffice\PhpWord\Metadata\Compatibility { ... }] }, $relationships = ['main' => ['rId1' => [...], 'rId2' => [...], 'rId3' => [...]], 'document' => ['rId1' => [...], 'rId2' => [...], 'rId3' => [...], 'rId4' => [...], 'rId5' => [...], 'rId6' => [...]]], $commentRefs = [], $partName = 'Document', $docFile = 'uploads/Question_me2.docx', $xmlFile = 'word/document.xml' )...\Word2007.php:89 and here is the OfficeMathML.php <?php namespace PhpOffice\Math\Reader; use DOMDocument; use DOMNode; use DOMXPath; use PhpOffice\Math\Element; use PhpOffice\Math\Exception\InvalidInputException; use PhpOffice\Math\Exception\NotImplementedException; use PhpOffice\Math\Math; class OfficeMathML implements ReaderInterface { /** @var DOMDocument */ protected $dom; /** @var Math */ protected $math; /** @var DOMXpath */ protected $xpath; /** @var string[] */ protected $operators = ['+', '-', '/', '∗']; public function read(string $content): ?Math { $nsMath = 'xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"'; $nsWord = 'xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"'; $content = str_replace( $nsMath, $nsMath . ' ' . $nsWord, $content ); $this->dom = new DOMDocument(); $this->dom->loadXML($content); $this->math = new Math(); $this->parseNode(null, $this->math); return $this->math; } /** * @see https://devblogs.microsoft.com/math-in-office/officemath/ * @see https://learn.microsoft.com/fr-fr/archive/blogs/murrays/mathml-and-ecma-math-omml * * @param Math|Element\AbstractGroupElement $parent */ protected function parseNode(?DOMNode $nodeRowElement, $parent): void { $this->xpath = new DOMXpath($this->dom); foreach ($this->xpath->query('*', $nodeRowElement) ?: [] as $nodeElement) { $element = $this->getElement($nodeElement); $parent->add($element); if ($element instanceof Element\AbstractGroupElement) { $this->parseNode($nodeElement, $element); } } } protected function getElement(DOMNode $nodeElement): Element\AbstractElement { switch ($nodeElement->nodeName) { case 'm:f': // Numerator $nodeNumerator = $this->xpath->query('m:num/m:r/m:t', $nodeElement); if ($nodeNumerator && $nodeNumerator->length == 1) { $value = $nodeNumerator->item(0)->nodeValue; if (is_numeric($value)) { $numerator = new Element\Numeric(floatval($value)); } else { $numerator = new Element\Identifier($value); } } else { throw new InvalidInputException(sprintf( '%s : The tag `%s` has no numerator defined', __METHOD__, $nodeElement->nodeName )); } // Denominator $nodeDenominator = $this->xpath->query('m:den/m:r/m:t', $nodeElement); if ($nodeDenominator && $nodeDenominator->length == 1) { $value = $nodeDenominator->item(0)->nodeValue; if (is_numeric($value)) { $denominator = new Element\Numeric(floatval($value)); } else { $denominator = new Element\Identifier($value); } } else { throw new InvalidInputException(sprintf( '%s : The tag `%s` has no denominator defined', __METHOD__, $nodeElement->nodeName )); } return new Element\Fraction($numerator, $denominator); case 'm:r': $nodeText = $this->xpath->query('m:t', $nodeElement); if ($nodeText && $nodeText->length == 1) { $value = trim($nodeText->item(0)->nodeValue); if (in_array($value, $this->operators)) { return new Element\Operator($value); } if (is_numeric($value)) { return new Element\Numeric(floatval($value)); } return new Element\Identifier($value); } throw new InvalidInputException(sprintf( '%s : The tag `%s` has no tag `m:t` defined', __METHOD__, $nodeElement->nodeName )); case 'm:oMath': return new Element\Row(); default: throw new NotImplementedException(sprintf( '%s : The tag `%s` is not implemented', __METHOD__, $nodeElement->nodeName )); } } } And here is my upload.php <?php session_start(); if ($_SESSION['role'] !== 'teacher') { header("Location: login.php"); exit(); } require 'db.php'; require 'vendor/autoload.php'; // Load the PHPWord library use PhpOffice\PhpWord\IOFactory; use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Shared\Html; $database = new Database(); $db = $database->getConnection(); if ($_SERVER['REQUEST_METHOD'] == 'POST') { $class_id = $_POST['class_id']; $subject_id = $_POST['subject_id']; $file = $_FILES['file']; if ($file['type'] == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') { $upload_dir = 'uploads/'; $file_path = $upload_dir . basename($file['name']); if (move_uploaded_file($file['tmp_name'], $file_path)) { try { // Convert .docx file to HTML $htmlFilePath = convertDocxToHtml($file_path); if ($htmlFilePath) { echo "File converted to HTML successfully.<br>"; } else { echo "Failed to convert file to HTML.<br>"; exit(); } // Parse the HTML file $htmlContent = file_get_contents($htmlFilePath); $questions = parseHtmlToQuestions($htmlContent); foreach ($questions as $question) { $stmt = $db->prepare("INSERT INTO questions (question_text, question_type, option_a, option_b, option_c, option_d, correct_option, subject_id) VALUES (?, 'Multiple Choice', ?, ?, ?, ?, ?, ?)"); if ($stmt->execute([ $question['question_text'], $question['options']['a'] ?? '', $question['options']['b'] ?? '', $question['options']['c'] ?? '', $question['options']['d'] ?? '', $question['correct_option'], $subject_id ])) { echo "Question inserted successfully: " . htmlspecialchars($question['question_text']) . "<br>"; } else { echo "Failed to insert question: " . htmlspecialchars($question['question_text']) . "<br>"; print_r($stmt->errorInfo()); } } echo "File uploaded and questions added successfully."; } catch (Exception $e) { echo "Error processing file: " . htmlspecialchars($e->getMessage()); } } else { echo "Failed to upload file."; } } else { echo "Invalid file type. Please upload a .docx file."; } } else { $classes = $db->query("SELECT * FROM classes")->fetchAll(PDO::FETCH_ASSOC); ?> <!DOCTYPE html> <html> <head> <title>Upload Questions</title> </head> <body> <h1>Upload Questions</h1> <form action="upload.php" method="post" enctype="multipart/form-data"> <label for="class">Class:</label> <select name="class_id" id="class" onchange="fetchSubjects(this.value)"> <option value="">Select Class</option> <?php foreach ($classes as $class): ?> <option value="<?= htmlspecialchars($class['class_id']) ?>"><?= htmlspecialchars($class['class_name']) ?></option> <?php endforeach; ?> </select> <label for="subject">Subject:</label> <select name="subject_id" id="subject"> <option value="">Select Subject</option> <!-- Subjects will be populated based on selected class --> </select> <label for="file">Choose a file:</label> <input type="file" name="file" id="file" accept=".docx"> <button type="submit">Upload</button> </form> <script> function fetchSubjects(classId) { fetch(`fetch_subjects.php?class_id=${classId}`) .then(response => response.json()) .then(data => { const subjectSelect = document.getElementById('subject'); subjectSelect.innerHTML = '<option value="">Select Subject</option>'; data.forEach(subject => { const option = document.createElement('option'); option.value = subject.subject_id; option.textContent = subject.subject_name; subjectSelect.appendChild(option); }); }); } </script> </body> </html> <?php } function convertDocxToHtml($filename) { $phpWord = IOFactory::load($filename); $htmlWriter = IOFactory::createWriter($phpWord, 'HTML'); $htmlFilePath = str_replace('.docx', '.html', $filename); $htmlWriter->save($htmlFilePath); return $htmlFilePath; } function parseHtmlToQuestions($htmlContent) { $questions = []; $currentQuestion = null; $dom = new DOMDocument; @$dom->loadHTML($htmlContent); $paragraphs = $dom->getElementsByTagName('p'); $currentPassage = ''; foreach ($paragraphs as $paragraph) { $text = trim($paragraph->textContent); $nodeContent = ''; foreach ($paragraph->childNodes as $node) { if ($node->nodeName === 'b' || $node->nodeName === 'strong') { $nodeContent .= '<b>' . $node->textContent . '</b>'; } elseif ($node->nodeName === 'i' || $node->nodeName === 'em') { $nodeContent .= '<i>' . $node->textContent . '</i>'; } elseif ($node->nodeName === 'img') { $src = $node->getAttribute('src'); $nodeContent .= '<img src="' . $src . '">'; } else { $nodeContent .= $node->textContent; } } // Handle equations (assuming they are marked with a specific tag or format) if (strpos($text, 'Equation:') === 0) { $equation = substr($text, 9); $currentQuestion['equation'] = $equation; // Store equations separately } if (strpos($text, 'Passage:') === 0) { if ($currentPassage) { $questions[] = ['passage' => $currentPassage, 'questions' => []]; } $currentPassage = substr($text, 8); } elseif (strpos($text, 'Question:') === 0) { if ($currentQuestion) { $questions[] = $currentQuestion; } $currentQuestion = [ 'question_text' => $nodeContent, 'options' => [], 'correct_option' => '', 'equation' => '', 'images' => [] ]; } elseif (preg_match('/^[A-D]\)/', $text)) { if ($currentQuestion) { $optionKey = strtolower($text[0]); $currentQuestion['options'][$optionKey] = substr($text, 3); } } elseif (strpos($text, 'Answer:') === 0) { if ($currentQuestion) { $currentQuestion['correct_option'] = trim(substr($text, 7)); } } } if ($currentQuestion) { $questions[] = $currentQuestion; } return $questions; } ?>
-
You are very intelligent sir. I saved the document as an html file and it created a folder as you have said. But my problem is, how do extract them? Here is my upload.php which extract text directly from Microsoft word but not extracting images or equation. <?php session_start(); if ($_SESSION['role'] !== 'teacher') { header("Location: login.php"); exit(); } require 'db.php'; require 'vendor/autoload.php'; // Load the PHPWord library use PhpOffice\PhpWord\IOFactory; $database = new Database(); $db = $database->getConnection(); if ($_SERVER['REQUEST_METHOD'] == 'POST') { $class_id = $_POST['class_id']; $subject_id = $_POST['subject_id']; $file = $_FILES['file']; if ($file['type'] == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') { $upload_dir = 'uploads/'; $file_path = $upload_dir . basename($file['name']); if (move_uploaded_file($file['tmp_name'], $file_path)) { $phpWord = IOFactory::load($file_path, 'Word2007'); if ($phpWord) { echo "File loaded successfully.<br>"; } else { echo "Failed to load file.<br>"; exit(); } $questions = []; $currentQuestion = null; foreach ($phpWord->getSections() as $section) { foreach ($section->getElements() as $element) { if (method_exists($element, 'getText')) { $text = trim($element->getText()); // Convert bold text $text = preg_replace('/\*\*(.*?)\*\*/', '<strong>$1</strong>', $text); // Convert italicized text $text = preg_replace('/__(.*?)__/', '<em>$1</em>', $text); // Convert quoted text to blockquote $text = preg_replace('/\"(.*?)\"/', '<blockquote>$1</blockquote>', $text); // Convert subscript text $text = preg_replace('/~(.*?)~/', '<sub>$1</sub>', $text); // Convert superscript text $text = preg_replace('/\^(.*?)\^/', '<sup>$1</sup>', $text); if (strpos($text, 'Question:') === 0) { if ($currentQuestion) { $questions[] = $currentQuestion; } $currentQuestion = [ 'question_text' => substr($text, 10), 'options' => [], 'correct_option' => '' ]; } elseif (strpos($text, 'A)') === 0 || strpos($text, 'B)') === 0 || strpos($text, 'C)') === 0 || strpos($text, 'D)') === 0) { if ($currentQuestion) { $optionKey = strtolower($text[0]); $currentQuestion['options'][$optionKey] = substr($text, 3); } } elseif (strpos($text, 'Answer:') === 0) { if ($currentQuestion) { $currentQuestion['correct_option'] = trim(substr($text, 7)); } } } elseif (method_exists($element, 'getDrawing')) { // Handle image extraction $drawing = $element->getDrawing(); $imagePath = $drawing->getPath(); $imageName = basename($imagePath); $newImagePath = $upload_dir . $imageName; copy($imagePath, $newImagePath); // Here you can store $newImagePath in the database for the question } } } if ($currentQuestion) { $questions[] = $currentQuestion; } foreach ($questions as $question) { $stmt = $db->prepare("INSERT INTO questions (question_text, question_type, option_a, option_b, option_c, option_d, correct_option, subject_id) VALUES (?, 'Multiple Choice', ?, ?, ?, ?, ?, ?)"); if ($stmt->execute([ $question['question_text'], $question['options']['a'] ?? '', $question['options']['b'] ?? '', $question['options']['c'] ?? '', $question['options']['d'] ?? '', $question['correct_option'], $subject_id ])) { echo "Question inserted successfully: " . $question['question_text'] . "<br>"; } else { echo "Failed to insert question: " . $question['question_text'] . "<br>"; print_r($stmt->errorInfo()); } } echo "File uploaded and questions added successfully."; } else { echo "Failed to upload file."; } } else { echo "Invalid file type. Please upload a .docx file."; } } else { $classes = $db->query("SELECT * FROM classes")->fetchAll(PDO::FETCH_ASSOC); ?> <!DOCTYPE html> <html> <head> <title>Upload Questions</title> </head> <body> <h1>Upload Questions</h1> <form action="upload.php" method="post" enctype="multipart/form-data"> <label for="class">Class:</label> <select name="class_id" id="class" onchange="fetchSubjects(this.value)"> <option value="">Select Class</option> <?php foreach ($classes as $class): ?> <option value="<?= $class['class_id'] ?>"><?= $class['class_name'] ?></option> <?php endforeach; ?> </select> <label for="subject">Subject:</label> <select name="subject_id" id="subject"> <option value="">Select Subject</option> <!-- Subjects will be populated based on selected class --> </select> <label for="file">Choose a file:</label> <input type="file" name="file" id="file" accept=".docx"> <button type="submit">Upload</button> </form> <script> function fetchSubjects(classId) { fetch(`fetch_subjects.php?class_id=${classId}`) .then(response => response.json()) .then(data => { const subjectSelect = document.getElementById('subject'); subjectSelect.innerHTML = '<option value="">Select Subject</option>'; data.forEach(subject => { const option = document.createElement('option'); option.value = subject.subject_id; option.textContent = subject.subject_name; subjectSelect.appendChild(option); }); }); } </script> </body> </html> <?php } ?>
-
Thank you sir. Can you please explain this further. In my previous and abandoned work, I do upload images inside the Microsoft word but and also wrote a script to identify that, but it doesn't work. It only captured the text documents.
-
Dear gurus in the house, I am trying to create an online CBT examination such that admin should be able to upload questions directly from Ms Word which might involve equations, graphs, formatting like bold, italicize and other features. But I am very confused regards this because I am not a guru and I don't want to use ready made software like moodle, but I want to design mine from scratch as a web application. I have used pho with no framework and was able to extract questions from Microsoft word with auto grading but this is not extracting the images, equations and the formats like bold. I stumbled from there again to use python with fastapi but all to no avail. Please guru in the house help me by putting me through on the model to use to achieve this. The questions will uploaded based on class like Basic 1, 2 and so on. I know you are all intelligent and here is a forum that solve problems.
-
Hi, I am a newbie to Laravel and trying to familiarize myself with it, so I am starting with a CBT project and when I navigate to http://127.0.0.1:8000/, it keeps taking me to laravel news page which differ from my project page. Here is my web.php <?php use Illuminate\Foundation\Application; use Illuminate\Support\Facades\Route; use Inertia\Inertia; use App\Http\Controllers\QuestionController; Route::get('questions', [QuestionController::class, 'index'])->name('questions.index'); Route::get('questions/create', [QuestionController::class, 'create'])->name('questions.create'); Route::post('questions', [QuestionController::class, 'store'])->name('questions.store'); Route::get('/', function () { return Inertia::render('Welcome', [ 'canLogin' => Route::has('login'), 'canRegister' => Route::has('register'), 'laravelVersion' => Application::VERSION, 'phpVersion' => PHP_VERSION, ]); }); Route::middleware([ 'auth:sanctum', config('jetstream.auth_session'), 'verified', ])->group(function () { Route::get('/dashboard', function () { return Inertia::render('Dashboard'); })->name('dashboard'); }); And here is the page I keeps loading to Please advise and if I could get a comprehensive tutorial that will guide me to pass the hurdles. I find it a bit difficult but with its authentication built in, it is okay.
-
I have an admission application form, and I want an email and SMS notification to be sent to the applicant's email and phone upon successful registration. I have tried using the mail() function, but I am not receiving any email notifications at the recipient's email. I also tried using Gmail, but none of them are working. I used Composer to install the vendor autoload, but it is still not working. I don't know where the error is coming from. Below are the tables and the code: Table CREATE TABLE applicants ( id INT AUTO_INCREMENT PRIMARY KEY, application_id VARCHAR(20) UNIQUE, surname VARCHAR(100), othername VARCHAR(100), dob DATE, phone VARCHAR(20), email VARCHAR(100), lga VARCHAR(100), state_origin VARCHAR(100), current_school VARCHAR(100), current_class VARCHAR(50), proposed_class ENUM('Year 7 (JSS1)', 'Year 8 (JSS2)', 'Year 10 (SS1)', 'Year 11 (SS2)', 'Year 1 (PRY 1)', 'Year 2 (PRY 2)', 'Year 3 (PRY 3)', 'Year 4 (PRY 4)'), status VARCHAR(20) DEFAULT 'Pending' ); CREATE TABLE exam_dates ( id INT AUTO_INCREMENT PRIMARY KEY, exam_date DATE, type ENUM('Online', 'On-site'), is_past BOOLEAN DEFAULT FALSE ); CREATE TABLE exam_registrations ( id INT AUTO_INCREMENT PRIMARY KEY, applicant_id INT, exam_date_id INT, FOREIGN KEY (applicant_id) REFERENCES applicants(id), FOREIGN KEY (exam_date_id) REFERENCES exam_dates(id) ); ALTER TABLE applicants ADD registered_on DATETIME; PHP <?php session_start(); require_once('db_config.php'); //require_once(__DIR__ . '/../vendor/autoload.php'); require_once('vendor/autoload.php'); // Import PHPMailer classes into the global namespace use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\Exception; // Fetch available exam dates from the database try { $stmt = $pdo->query("SELECT * FROM exam_dates WHERE is_past = FALSE"); $exam_dates = $stmt->fetchAll(PDO::FETCH_ASSOC); } catch(PDOException $e) { echo "Error: " . $e->getMessage(); } // Check if the user is logged in as an applicant if (!isset($_SESSION['user_type']) || $_SESSION['user_type'] !== 'applicant') { header("Location: login.php"); exit(); } // Logout logic if (isset($_POST['logout'])) { session_destroy(); // Destroy all session data header("Location: login.php"); // Redirect to the login page exit(); } // Set the applicant_id from the applicants table try { $username = $_SESSION['username']; $stmt = $pdo->prepare("SELECT * FROM applicants WHERE application_id = ?"); $stmt->execute([$username]); $applicant = $stmt->fetch(PDO::FETCH_ASSOC); $_SESSION['applicant_id'] = $applicant['id']; $applicant_email = $applicant['email']; // Store the applicant's email address } catch(PDOException $e) { echo "Error: " . $e->getMessage(); exit(); } // Check if the applicant has already registered for an exam date try { $stmt = $pdo->prepare("SELECT * FROM exam_registrations WHERE applicant_id = ?"); $stmt->execute([$applicant['id']]); $registered_exam_dates = $stmt->fetchAll(PDO::FETCH_ASSOC); } catch(PDOException $e) { echo "Error: " . $e->getMessage(); } // Handle exam registration if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['exam_date'])) { // Check if the applicant has already registered for an exam date if (!empty($registered_exam_dates)) { //echo "You have already registered for an exam date."; exit(); } $applicant_id = $_SESSION['applicant_id']; $exam_date_id = $_POST['exam_date']; // Insert exam registration details into exam_registrations table try { $stmt = $pdo->prepare("INSERT INTO exam_registrations (applicant_id, exam_date_id) VALUES (?, ?)"); $stmt->execute([$applicant_id, $exam_date_id]); // Redirect to exam confirmation page or show success message header("Location: exam_confirmation.php"); // Send SMS to applicant $message = "Thank you for your application. Your username is: " . $applicant['application_id'] . " and Password is your surname."; $api_url = 'my api url'; $token = 'my token'; $sender = 'Olu'; $recipient = $applicant['phone']; $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $api_url, CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => array( 'token' => $token, 'sender' => $sender, 'to' => $recipient, 'message' => $message, ), )); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo 'cURL Error #:' . $err; } else { echo 'SMS sent successfully.'; } // Send email notification to applicant using PHPMailer sendEmailNotification($applicant_email, $applicant['application_id'], $applicant['surname']); exit(); } catch(PDOException $e) { echo "Error: " . $e->getMessage(); } } // Function to send email notification using PHPMailer function sendEmailNotification($recipientEmail, $applicationId, $surname) { // Instantiate PHPMailer $mail = new PHPMailer(true); try { // SMTP configuration (Gmail) $mail->isSMTP(); $mail->Host = 'smtp.gmail.com'; $mail->SMTPAuth = true; $mail->Username = 'olu@gmail.com'; $mail->Password = 'mypassword'; $mail->SMTPSecure = 'tls'; $mail->Port = 587; // Email content $mail->setFrom('olu@gmail.com', 'My Schol'); $mail->addAddress($recipientEmail); $mail->Subject = 'Application Registration Confirmation'; $mail->isHTML(true); $mail->Body = "Dear $surname,<br><br>Thank you for your application at my Schol. Your username is: $applicationId and Password is your surname.<br><br>Best regards,<br>My Schol"; // Send email $mail->send(); echo 'Email sent successfully!'; } catch (Exception $e) { echo "Error: {$mail->ErrorInfo}"; } } ?> <!DOCTYPE html> <html> <head> <title>Applicant Dashboard</title> <script> // JavaScript function to display a popup function displayPopup() { alert("You have already registered for an exam date."); } </script> </head> <body> <h2>Welcome, <?php echo $applicant['surname']; ?></h2> <!-- Display applicant information --> <p>Applicant's Name: <?php echo $applicant['surname'] . ' ' . $applicant['othername']; ?></p> <p>Application ID: <?php echo $applicant['application_id']; ?></p> <p>Date of Birth: <?php echo $applicant['dob']; ?></p> <p>Phone: <?php echo $applicant['phone']; ?></p> <p>Email: <?php echo $applicant['email']; ?></p> <p>Local Government Area: <?php echo $applicant['lga']; ?></p> <p>State of Origin: <?php echo $applicant['state_origin']; ?></p> <p>Current School: <?php echo $applicant['current_school']; ?></p> <p>Current Class: <?php echo $applicant['current_class']; ?></p> <p>Proposed Class: <?php echo $applicant['proposed_class']; ?></p> <!-- Selected exam date --> <p>Selected Exam Date: <?php if (!empty($registered_exam_dates)) { $selected_exam_date_id = $registered_exam_dates[0]['exam_date_id']; foreach ($exam_dates as $date) { if ($date['id'] == $selected_exam_date_id) { echo date('F j, Y', strtotime($date['exam_date'])) . " (" . $date['type'] . ")"; break; } } } else { echo 'Not selected'; } ?> </p> <hr> <!-- Exam date selection --> <h3>Exam Date Selection</h3> <form id="exam_form" method="post"> <label for="exam_date">Select Exam Date:</label><br> <select id="exam_date" name="exam_date"> <?php foreach ($exam_dates as $date) : ?> <option value="<?php echo $date['id']; ?>"><?php echo $date['exam_date'] . " (" . $date['type'] . ")"; ?></option> <?php endforeach; ?> </select><br><br> <input type="button" value="Register for Exam" onclick="checkExamRegistration()"> <!--<input type="submit" value="Register for Exam">--> </form> <!-- Application status --> <h3>Application Status</h3> <p>Status: <?php echo $applicant['status']; ?></p> <!-- Logout form --> <form method="post"> <input type="submit" name="logout" value="Logout"> </form> <script> // Function to check if the applicant has already registered function checkExamRegistration() { <?php if (!empty($registered_exam_dates)): ?> displayPopup(); <?php else: ?> document.getElementById("exam_form").submit(); <?php endif; ?> } </script> </body> </html>