0

I'm trying to learn something new whilst stuck on lockdown. I'm trying to create a very basic multiple choice quiz page using my (very) limited knowledge of PHP/Javascript...

So I have a SQL database containing quiz questions. The main fields are the question, correct answer and then three incorrect answers. Currently the database has just one row.

<?php
$servername = "xxx";
$username = "xxx";
$password = "xxx";
$dbname = "xxx";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
} 

$sql = "SELECT * FROM quiz_db";
$result = $conn->query($sql);
$row = $result->fetch_assoc();

$conn->close();
?>

So the question, the correct answer, the three incorrect answers and anything else in the row are stored to $row.

Next I'm taking all four possible answers into an array and then shuffling the order:

<?php 
$answerslist = array($row["answercorrect"], $row["answerincorrect1"], $row["answerincorrect2"], $row["answerincorrect3"]);
shuffle($answerslist);
?>

Then I'm putting the four possible answers on a set of buttons in their now randomized order:

<div class="row">
    <div class="col-sm-3">
        <button id = "answerA" onclick="clickA()" class="answer"><?php echo $answerslist[0]; ?></button>
    </div>
    <div class="col-sm-3">
        <button id="answerB" onclick="clickB()" class="answer"><?php echo $answerslist[1]; ?></button>
    </div>
    <div class="col-sm-3">
        <button id = "answerC" onclick="clickC()" class="answer"><?php echo $answerslist[2]; ?></button>
    </div>
    <div class="col-sm-3">
        <button id = "answerD" onclick="clickD()"  class="answer"><?php echo $answerslist[3]; ?></button>
    </div>
</div>

You'll see I've assigned an onclick event to each button. This is as follows:

function clickA() {

var clickedAnswerA = "<?php echo $answerslist[0]; ?>"; // Get the value of the clicked answer

var correctAnswer = "<?php echo $row["answercorrect"] ?>"; // Get the value of the correct answer


if (clickedAnswerA == correctAnswer) {
     document.getElementById("result").innerHTML = "CORRECT!"; 
     document.getElementById("result").style.backgroundColor = "#32CD32";   
} else {
    document.getElementById("result").innerHTML = "WRONG!";
    document.getElementById("result").style.backgroundColor = "#CC0000";
}
}

There are four of the above scripts, one for each button. Essentially I wanted it to say, if the clicked answer = the correct answer, make the result CORRECT and green, otherwise WRONG! and red

And to my surprise, this all works as expected!

For the next stage, after the above, I wanted it to go to the next question in the resultset (i.e. the next question in $row). But I'm getting stuck. Currently there's only one question in the DB, but if I add another one, I'm not sure how I make the PHP essentially refresh. Any advice or pointers would be greatly appreciated.

Furthermore, if anyone can recommend any improvements to what I've done so far, perhaps for ease or efficiency, that would be great, thank you!

darossi
  • 99
  • 7
  • Forgot to put the link here: https://quizquack.xyz/1/ – darossi Apr 29 '20 at 09:38
  • 1
    avoid `select *`, use `select field1, field2...` and I prefer use bind_param, execute(), bind_result in my projects. – RGS Apr 29 '20 at 09:42
  • Thank you. What's the advantage of naming the fields over ```select *```? or rather, what are the pitfalls of using ```select *```? – darossi Apr 29 '20 at 09:44
  • 1
    select field is faster, you can use indexes: https://stackoverflow.com/questions/4203377/what-is-faster-select-or-select-field-when-only-requiring-field – RGS Apr 29 '20 at 09:47

1 Answers1

1

1. Don't keep everything in one row. Have relation between question and answers:

question
  id | title | ...
   1 | Question 1 | ...
   2 | Question 2 | ...

answer
 id | question_id | content | is_correct
  1 | 1           | Foo     | 1
  2 | 1           | Bar     | 0
  ...

2. Do query for data:

$question = $db->prepare('SELECT * FROM question WHERE id = :id')->queryRow([':id' => $id]);
$answers = $db->prepare('SELECT id, content, is_correct FROM answer WHERE question_id = :id')->queryAll([':id' => $id]);

that way you can have as much answers as you need per question.

3. Bind event for your elements, instead of onClick="" with each function doing the same.

4. var clickedAnswerA = "<?php echo $answerslist[0]; ?>"; will bring more problems than you see by now. Try not to mix JS and PHP code outputs as JS does not see any PHP, just it's output (PHP first outputs code and only later HTML and JS is executed)

5. Use single PHP loop to output all answers instead of writing repetitive code.

Justinas
  • 41,402
  • 5
  • 66
  • 96
  • Thanks for this, it's really helpful. I use SQL at work a lot so the first part I totally understand, I was just being lazy I think! With the second part of your answer, I'm not clear on the alternative to mixing the JS/PHP to get the same result, can you elaborate or point me in the right direction for a tutorial? – darossi Apr 29 '20 at 09:55
  • 1
    I saw lot's of code from "lazy" people that later on brings multiple times more time wasted just to fix "lazy"/"temporary"/"quick fix" code – Justinas Apr 29 '20 at 09:57
  • 1
    @darossi Usually people stating with JS and PHP thinks that JS can execute PHP or PHP can execute JS. That's totally wrong thinking. Click `CTRL+U` to see source code and you will see that between your quotes there is literal string and not dynamic one. – Justinas Apr 29 '20 at 09:59
  • Thank for the info. So what would you say is the best method to achieve what I'm trying to do? i.e. load a question, user clicks an answer, it is either correct or incorrect, then they go to the next question? – darossi Apr 29 '20 at 10:01
  • Also I see what you mean with Ctrl-U, looking at the source, a user can easily cheat and see the correct answer! – darossi Apr 29 '20 at 10:03
  • 1
    With your task it would be best to use Ajax request to check if answer is correct. – Justinas Apr 29 '20 at 10:04
  • Thanks - I did take an AJAX tutorial a while back and have saved the materials so I;ll go check that out. Thanks! – darossi Apr 29 '20 at 10:04