mysqli_fetch_array how to get one row at a time?

2 answers

My php code is as follows: This is part of a quiz where I am displaying one question and 4 multiple choices in html page via ajax jQuery. I know how to run while loop and display all data one after the other but how do I just display one question at a time?

So after one question is answered, I would like to view the next question. Is it possible to run a counter and pull one result at a time and next result and so on.. ?

<?php  header("Access-Control-Allow-Origin: *"); require 'db.php'; // making empty variable $createTable = "";          $test_id=$_POST["test_id"];         $sql=mysqli_query($con,"select * from mst_question where test_id='$test_id' ");     $counter = 0;  while($row=mysqli_fetch_array($sql))         {        $counter++;         $createTable .= '<div class="text-subhead-2 text-center" style="background-color:#42A5F5">Question ';         $createTable .= $counter;         $createTable .= ' of 25</div>';         $createTable .= '<div class="panel panel-default paper-shadow" data-z="0.5">';          $createTable .= '<div class="panel-body">';         $createTable .= '<p class="text-body-2">';         $createTable .= $row['que_desc'];         $createTable .= '</p>';        $createTable .= '</div>';         $createTable .= '</div>';          $createTable .= '<div class="text-subhead-2 text-light">Your Answer</div>';         $createTable .= '<div class="panel panel-default paper-shadow" data-z="0.5">';         $createTable .= '<div class="panel-body">';         $createTable .= '<div class="radio radio-success">';         $createTable .= '<input type="radio" name="radio';         $createTable .= $counter;         $createTable .= '" id="radio1';         $createTable .= $counter;         $createTable .= '" value="';         $createTable .= $row['ans1'];         $createTable .= '" >';         $createTable .= '<label for="radio1';         $createTable .= $counter;         $createTable .= '">';         $createTable .= $row['ans1'];         $createTable .= '</label>';         $createTable .= '</div>';         $createTable .= '<div class="radio radio-success">';         $createTable .= '<input type="radio" name="radio';         $createTable .= $counter;         $createTable .= '" id="radio2';         $createTable .= $counter;         $createTable .= '" value="';         $createTable .= $row['ans2'];         $createTable .= '" >';         $createTable .= '<label for="radio2';         $createTable .= $counter;         $createTable .= '">';         $createTable .= $row['ans2'];         $createTable .= '</label>';         $createTable .= '</div>';         $createTable .= '<div class="radio radio-success">';         $createTable .= '<input type="radio" name="radio';         $createTable .= $counter;         $createTable .= '" id="radio3';         $createTable .= $counter;         $createTable .= '" value="';         $createTable .= $row['ans3'];         $createTable .= '" >';         $createTable .= '<label for="radio3';         $createTable .= $counter;         $createTable .= '">';         $createTable .= $row['ans3'];         $createTable .= '</label>';         $createTable .= '</div>';         $createTable .= '<div class="radio radio-success">';         $createTable .= '<input type="radio" name="radio';         $createTable .= $counter;         $createTable .= '" id="radio4';         $createTable .= $counter;         $createTable .= '" value="';         $createTable .= $row['ans4'];         $createTable .= '" >';         $createTable .= '<label for="radio4';         $createTable .= $counter;         $createTable .= '">';         $createTable .= $row['ans4'];         $createTable .= '</label>';         $createTable .= '</div>';         $createTable .= '</div>';         $createTable .= '</div>';                          }      echo $createTable;     mysqli_close($con);     ?> 
Received answers to this question:
The best answer according to the author of the question:

Firstly, your code is dangerous because can be hacked via sql injection. You always should use parameter bindings.

The simplest way is passing an id of the question stored in mst_question and selecting one by WHERE clause (like test_id).

//... $test_id=$_POST["test_id"]; $questionId = filter_var($_POST['question_id'],FILTER_VALIDATE_INT); if (!$questionId){    die('done'); }  $stmt= mysqli_prepare($con,"select * from mst_question where test_id='$test_id' AND id=?"); mysqli_stmt_bind_param(**$stmt**, 'd',$questionId); mysqli_stmt_execute(**$stmt**); // work with $stmt.  // f.e. your loop but now there will be only one execution mysqli_stmt_close($stmt); //... $createTable .= '<input type="hidden" name="nextQuestionId" value="'.$nextQuestionId.'"/>'; //... 

With input field you will return id of the next question which can be passed in url argument within javascript code.

if you are worried about quiz-cheaters, you can increase security by hashing an nextQuestionId.

//... $stmt = mysqli_prepare($con,"select * from mst_question where test_id='$test_id' AND sha1(CONCAT('slat_',id))=?"); //... $createTable .= '<input type="hidden" name="nextQuestionId" value="'.sha1('salt_'.$nextQuestionId).'"/>'; //... 

It's not the best solution but requiring minimal changes of your code.

I would like to suggest switching to PDO - very friendly and powerful way to interact with database. See an example.

PHP is a server-side language so you would have to reload the page each time and change your DB query to get a different question using just PHP.

I think the easiest solution would be to initialize a counter variable and have each loop iteration create a container element like:

<div id="question-num$counter"> 

This will initially output all the questions your a query returns with no where clause - then you can use JavaScript/jquery to hide completed questions and show the next using the display or visibility styles.

The following would hide all questions by default.

<div id="question-num$counter" style="display:none;"> 

This JavaScript code would make the first question visible:

document.getElementById("question-num1").style.display = "block"; 

JQuery equivalent:

$("#question-num1").css("display", "block"); 

You could add a button with an 'onclick' event that hides the current question and shows the next.

You could also skip the counter and identifier route and try your luck with this instead (if your brain works better this way):