dan_bsb Posted January 7, 2014 Share Posted January 7, 2014 Hey, I made the following code that checks the answers of a form: <?PHP include 'connect.php'; $points = 0; foreach($_POST as $id => $answer){ $result = mysql_query("SELECT id, ans FROM questions WHERE id = '".$id."'"); $row = mysql_fetch_array($result); if($answer == $row['ans']) { $points++; } } echo "Your score: $points"; ?> The problem is that it makes a sql query for every question, which makes the script a bit slow... Is there a way to make a single sql query that select all the answers? Link to comment https://forums.phpfreaks.com/topic/285182-help-improving-code/ Share on other sites More sharing options...
ginerjm Posted January 7, 2014 Share Posted January 7, 2014 try using the in clause as in: $result = mysql_query("SELECT id, ans FROM questions WHERE id in ['$id']"); (Note how I used single quotes) where you build $vals in your loop and execute the query outside the loop. and $vals is a comma-separated string of values. Link to comment https://forums.phpfreaks.com/topic/285182-help-improving-code/#findComment-1464343 Share on other sites More sharing options...
dan_bsb Posted January 7, 2014 Author Share Posted January 7, 2014 try using the in clause as in: $result = mysql_query("SELECT id, ans FROM questions WHERE id in ['$id']"); (Note how I used single quotes) where you build $vals in your loop and execute the query outside the loop. and $vals is a comma-separated string of values. @ginerjm, thanks for your answer! But can you show an example of how to do this? I'm relatively new to php... Link to comment https://forums.phpfreaks.com/topic/285182-help-improving-code/#findComment-1464345 Share on other sites More sharing options...
Psycho Posted January 7, 2014 Share Posted January 7, 2014 First, change your form so all the 'answers' are in a sub-key of the $_POST array, e.g. $_POST['answers'], rather than putting them in the root of $_POST. This way if there was any other information included in the POST data (for example a user ID) it will be logically separated from the answers. Then, you can easily get the list of the questions and the answers. <?php //Get the POSTed answers $answersAry = $_POST['answers']; //Get the array of question IDs $questionIDsAry = array_keys($_POST['answers']); //Convert all ID values to integers (make safe for SQL query) $questionIDsAry = array_map('intval', $questionIDsAry); //Remove invalid values $questionIDsAry = array_filter($questionIDsAry); //Convert remaining IDs to comma separated string for use in query $questionIDsSQL = implode(', ', $questionIDsAry); //Create and run query $query = "SELECT id, ans FROM questions WHERE id IN({$questionIDsSQL})"; $result = mysql_query($query); //Iterate through the query results and compare to the POSTed answers $points = 0; while($row = mysql_fetch_assoc($result)) { if($answersAry[$row['id']] == $row['ans']) { $points++; } } echo "Your score: $points"; ?> Link to comment https://forums.phpfreaks.com/topic/285182-help-improving-code/#findComment-1464349 Share on other sites More sharing options...
Barand Posted January 7, 2014 Share Posted January 7, 2014 Single query to read all the answers into an array $res = $db->query("SELECT id,ans FROM questions"); while ($row = $res->fetch_assoc()) { $ans[$row['id']] = $row['ans']; } Gives something like $ans = array ( 1 => 'A', 2 => 'C', 3 => 'D' ); Then you have your POST array like $post = array ( 1 => 'A', 2 => 'B', 3 => 'D' ); Now use array_intersect_assoc() $correct = array_intersect_assoc($ans,$post); /* $correct array ********** Array ( [1] => A [3] => D ) ****************************/ Link to comment https://forums.phpfreaks.com/topic/285182-help-improving-code/#findComment-1464352 Share on other sites More sharing options...
dan_bsb Posted January 7, 2014 Author Share Posted January 7, 2014 First, change your form so all the 'answers' are in a sub-key of the $_POST array, e.g. $_POST['answers'], rather than putting them in the root of $_POST. This way if there was any other information included in the POST data (for example a user ID) it will be logically separated from the answers. Then, you can easily get the list of the questions and the answers.<?php //Get the POSTed answers $answersAry = $_POST['answers']; //Get the array of question IDs $questionIDsAry = array_keys($_POST['answers']); //Convert all ID values to integers (make safe for SQL query) $questionIDsAry = array_map('intval', $questionIDsAry); //Remove invalid values $questionIDsAry = array_filter($questionIDsAry); //Convert remaining IDs to comma separated string for use in query $questionIDsSQL = implode(', ', $questionIDsAry); //Create and run query $query = "SELECT id, ans FROM questions WHERE id IN({$questionIDsSQL})"; $result = mysql_query($query); //Iterate through the query results and compare to the POSTed answers $points = 0; while($row = mysql_fetch_assoc($result)) { if($answersAry[$row['id']] == $row['ans']) { $points++; } } echo "Your score: $points"; ?> My form is like this: <?PHP $select = "SELECT * FROM questions"; $result = mysql_query($select); echo "<form id='questions' method='post' action='check.php'>"; while($result2 = mysql_fetch_array($result)) { echo "<p>Question: $result2[question]</p> <p>a) <input name='$result2[id]' type='radio' value='1'> $result2[option1]</input></p> <p>b) <input name='$result2[id]' type='radio' value='2'> $result2[option2]</input></p> <p>c) <input name='$result2[id]' type='radio' value='3'> $result2[option3]</input></p> <p>d) <input name='$result2[id]' type='radio' value='4'> $result2[option4]</input></p>"; } echo "<input type='submit' name='Submit' value='Check!' /> </form> </div>"; ?> So how do I "change my form so all the 'answers' are in a sub-key of the $_POST array"? Thanks! Link to comment https://forums.phpfreaks.com/topic/285182-help-improving-code/#findComment-1464355 Share on other sites More sharing options...
Barand Posted January 7, 2014 Share Posted January 7, 2014 Instead of name = '$result2[id]' have name = 'answers[$result2[id]]' Link to comment https://forums.phpfreaks.com/topic/285182-help-improving-code/#findComment-1464358 Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.