PHP在线测验系统删除中间题目后无法加载下一题求助
Alright, let's break down why your quiz is skipping the third active question and fix it step by step.
The Root Problem
Your current code uses the database's question_number directly as the quiz's question index in the URL (?n=X). But when you deactivate/delete a question (like question_number=3 in your case), the active questions have non-consecutive question_number values (1, 2, 4). So when the quiz tries to load ?n=3, there's no active question with question_number=3, hence the missing question. The total count shows 3 active questions, but the URL indices don't map to the actual set of active questions.
The Fix: Use a "Display Sequence" Instead of Raw question_number
We need to assign consecutive display numbers to active questions, regardless of their original question_number in the database. Here's how to adjust your code:
1. Update the Home/Start Page
Instead of just counting active questions, generate a consecutive display number for each active question. This ensures the "Start Quiz" link points to the first logical quiz question, not the first raw question_number.
<?php // Generate consecutive display numbers for active questions (MySQL 8+ syntax) $query ="SELECT *, ROW_NUMBER() OVER (ORDER BY question_number) AS display_number FROM questions where status='1' ORDER BY question_number"; $results = $mysqli->query($query) or die($mysqli->error.__LINE__); $total = $results->num_rows; ?> <a href="question.php?n=1" class="start">Start Quiz</a>
If you're using MySQL 5.x (no ROW_NUMBER() support):
Replace the query with this variable-based approach:
$query ="SELECT *, @row := @row + 1 AS display_number FROM questions, (SELECT @row := 0) AS row_counter WHERE status='1' ORDER BY question_number";
2. Rewrite question.php to Use Display Numbers
Now, instead of using the URL's n directly as question_number, we first find which question_number corresponds to the requested display number. This way, even if question_number is non-consecutive, the quiz flows through all active questions in order.
<?php $display_number = (int) $_GET['n']; // First, get all active questions with their display numbers $query = "SELECT *, ROW_NUMBER() OVER (ORDER BY question_number) AS display_number FROM questions WHERE status='1' ORDER BY question_number"; $results = $mysqli->query($query) or die($mysqli->error.__LINE__); $total = $results->num_rows; // Validate the display number is within valid range if ($display_number < 1 || $display_number > $total) { header("Location: index.php"); // Redirect to home if invalid exit; } // Find the matching question_number for this display number $target_question_number = null; while ($row = $results->fetch_assoc()) { if ($row['display_number'] === $display_number) { $target_question_number = $row['question_number']; break; } } // Fetch the actual question using the target question_number $query = "SELECT * FROM `questions` WHERE question_number = $target_question_number AND status='1'"; $result = $mysqli->query($query) or die($mysqli->error.__LINE__); $question = $result->fetch_assoc(); // Fetch the choices for this question $query = "SELECT * FROM `choices` WHERE question_number = $target_question_number AND status='1'"; $choices = $mysqli->query($query) or die($mysqli->error.__LINE__); ?> <div class="current">Question <?php echo $display_number; ?> of <?php echo $total; ?></div> <p class="question"> <?php echo $question['text']; ?> </p> <form method="post" action="process.php"> <ul class="choices"> <?php while($row = $choices->fetch_assoc()): ?> <li><input name="choice" type="radio" value="<?php echo $row['id']; ?>"/><?php echo $row['text']; ?></li> <?php endwhile; ?> </ul> <input type="submit" value="Submit" /> <input type="hidden" name="display_number" value="<?php echo $display_number; ?>" /> <input type="hidden" name="question_number" value="<?php echo $target_question_number; ?>" /> </form>
3. Update process.php (Critical for Next Question Flow)
You'll need to adjust your process.php to increment the display_number instead of question_number when loading the next question. For example:
<?php // After processing the user's answer $current_display = (int)$_POST['display_number']; // Fetch total active questions (you can also pass this via a hidden input for efficiency) $total_query = "SELECT COUNT(*) AS total FROM questions WHERE status='1'"; $total_result = $mysqli->query($total_query); $total_active = $total_result->fetch_assoc()['total']; $next_display = $current_display + 1; if ($next_display > $total_active) { // Redirect to results page when quiz is complete header("Location: results.php"); } else { // Redirect to next question using the display number header("Location: question.php?n=$next_display"); } exit; ?>
Why This Works
By separating the display sequence (what the user sees as Question 1, 2, 3) from the database's question_number (the internal ID that stays even when questions are deactivated), you ensure the quiz always flows through all active questions in order, no matter which questions are removed or marked inactive.
内容的提问来源于stack exchange,提问作者tester

