displaying random q and their random ans - php
***i am making a quiz app using php and mysql and i have to display random questions..but i have defined static indexes for the answers..my program shows random question by refreshing the window but the answers index dont refresh according to question as they are static
<?php
$con=mysql_connect('localhost','root','test123');
mysql_select_db("quiz",$con);
?>
<html>
<body>
<form method="get" action="result.php">
<?php
$query="select m_question,a,b,c,d,e from mcq ORDER BY RAND()";
$result=mysql_query($query);
$rows=mysql_num_rows($result);
$a=1;
for($j=0;$j<$rows;$j++)
{
echo "<br> $a." .mysql_result($result,$j,'m_question')."<br>" ;
echo "<input type = radio name=$a value='a'>" .mysql_result($result,$j,'a');
echo "<input type = radio name=$a value='b'>" .mysql_result($result,$j,'b');
echo "<input type = radio name=$a value='c'>" .mysql_result($result,$j,'c');
echo "<input type = radio name=$a value='d'>" .mysql_result($result,$j,'d');
echo "<input type = radio name=$a value='e'>" .mysql_result($result,$j,'e');
$a++;
}
?>
<br>
<br>
<input type = "submit" value ="submit result">
</body>
</html>
and this is my result file where i am comparing results .ans of 1 questions is "b" option and and 2nd is "a" and so on...
<?php
$result=0;
if ($_GET[1]=='b')
{$result++;}
if ($_GET[2]=='a')
{$result++;}
if ($_GET[3]=='b')
{$result++;}
if ($_GET[4]=='b')
{$result++;}
echo "your score::".$result;
?>
I'm not sure what you mean by 'Static indexes for the answers', but you should remember that your database schema should always reflect the data stored in such a way that you could answer any questions you might have just by looking at the data available. Since I don't exactly know what you have based only on your code (you don't specify your schema, for example), I'll assume we're starting from scratch - and you can compare what you have to what I come up with.
The Schema
First, you have two sets of data: Questions, and Answers. Since this is a quiz app, I'm presuming that the format of the quiz is 'Multiple Choice'; that is, each Question has two or more possible answers, and only one of them is correct.
This means that we should split the questions and the answers into two tables; lets call them 'questions' and 'answers' respectively.
Questions
In the 'questions' table, we need a few things:
A unique, numeric identifier for each question. This is needed to set up any relationships in the future, so that we can point to any particular question easily (sure the text strings in the question are probably unique already, but when you want to quickly point to a specific item in the table, computers are much faster at comparing and searching through numbers than they are at comparing and searching through text). This will be our primary key.
The question itself. This is rather obvious.
So far, our schema looks something like this (primary keys in bold):
questions
q_id
question
Note: 'q_id' (or whatever you name your primary key) should also be labeled as 'AUTO_INCREMENT'. When you enter each question into the database, you leave that field 'null', and it'll automatically assign it the next available number.
Answers
Now for the 'answers' table, we'll need some different things. We'll need to identify each answer individually (to be able to point to each one they can choose), the question the answer belongs to, and we'll also have to be able to identify which one is the correct answer.
We can do this by having, along with an 'answer id' primary key, a 'foreign key' referencing the 'q_id' column in the 'questions' table, since it's the primary key for that table and thus identifies each row (each question) uniquely. Then all we need is the answer itself, and whether or not it's the correct answer. The end result is something like this:
answers
a_id
q_id (foreign key: questions.q_id)
answer
correct (enum: 'yes', 'no')
This also allows for questions to have no right answer, or multiple right answers. You'd have to take care of your data to make sure it's in line with the quiz. If you want to restrict only one right answer per question, you can add a 'UNIQUE' index that encompasses both 'q_id' and 'correct'. In MySQL, it'd look something like:
UNIQUE INDEX (q_id, correct),
That would go inside of your CREATE TABLE statement, or into a separate ALTER TABLE statement.
Note: 'q_id' in 'answers' should not *use either AUTO_INCREMENT* or be a primary key. If you feel it is causing a bottleneck, put an index on it.
Example Data Set
To help see this schema in action, lets make a simple quiz:
questions
1, "How many inches are in a mile?";
2, "Why do people breathe air?";
3, "Why is Monty Python popular?";
answers
1, 1, "63,360", 'yes';
2, 1, "5,280", 'no';
3, 1, "Over a million", 'no';
4, 1, "Several Hundred", 'no';
5, 2, "So they don't die", 'yes';
6, 2, "Because it's cool", 'no';
7, 2, "Because it's polite", 'no';
8, 2, "So they can laugh at people who don't", 'no';
9, 3, "Because people find it funny", 'yes';
10, 3, "Because it is", 'no';
11, 3, "Because of the French", 'no';
12, 3, "It's popular?", 'no';
Querying in PHP
There are two sets of queries to worry about here: grabbing the questions, and grabbing the answers. I would like to first point out that in your code examples, you're using the old, antiquated 'mysql' set of functions ('mysql_query', 'mysql_result', and so forth).
This is HIGHLY discouraged, and you should learn to use either the newer 'Mysqli' library, or the more abstracted 'PDO' library. I will be using Mysqli.
Method 1: All at once.
The first way you could run the queries, is to select all the questions, and then all the answers at once, put them into a data structure (your own class, or just a nested array), and then randomize the order in which they're displayed. Here is some code showing this. The comments are worth reading:
<?php
//Connect to MySQL:
$con = new mysqli("localhost", "tynach", "505.2.0", "quiz");
//Grab the question list:
$get_questions = $con->prepare("SELECT q_id, question FROM questions");
$get_questions->execute();
$get_questions->bind_result($q_id, $question);
$questions = array();
while ($get_questions->fetch()) {
// We use $q_id twice because if you scramble the array, the first one
// changes. However, we still might want to keep track of the original
// question ID number.
// The reason we use it in that first spot to begin with is so that we
// know for sure that we can associate the answers to the correct
// questions.
$questions[$q_id] = array($q_id, $question, array());
}
// Grab the answer list:
$get_answers = $con->prepare("SELECT a_id, q_id, answer, correct FROM answers");
$get_answers->execute();
$get_answers->bind_result($a_id, $q_id, $answer, $correct);
while ($get_answers->fetch()) {
$questions[$q_id][2][$a_id] = array($a_id, $answer, $correct);
}
// Scramble the array, and print it out:
shuffle($questions);
var_dump($questions);
?>
The output to that is:
array(3) {
[0]=>
array(3) {
[0]=>
int(1)
[1]=>
string(30) "How many inches are in a mile?"
[2]=>
array(4) {
[1]=>
array(3) {
[0]=>
int(1)
[1]=>
string(6) "63,360"
[2]=>
string(3) "yes"
}
[2]=>
array(3) {
[0]=>
int(2)
[1]=>
string(5) "5,280"
[2]=>
string(2) "no"
}
[3]=>
array(3) {
[0]=>
int(3)
[1]=>
string(14) "Over a million"
[2]=>
string(2) "no"
}
[4]=>
array(3) {
[0]=>
int(4)
[1]=>
string(15) "Several Hundred"
[2]=>
string(2) "no"
}
}
}
[1]=>
array(3) {
[0]=>
int(2)
[1]=>
string(26) "Why do people breathe air?"
[2]=>
array(4) {
[5]=>
array(3) {
[0]=>
int(5)
[1]=>
string(17) "So they don't die"
[2]=>
string(3) "yes"
}
[6]=>
array(3) {
[0]=>
int(6)
[1]=>
string(17) "Because it's cool"
[2]=>
string(2) "no"
}
[7]=>
array(3) {
[0]=>
int(7)
[1]=>
string(19) "Because it's polite"
[2]=>
string(2) "no"
}
[8]=>
array(3) {
[0]=>
int(8)
[1]=>
string(37) "So they can laugh at people who don't"
[2]=>
string(2) "no"
}
}
}
[2]=>
array(3) {
[0]=>
int(3)
[1]=>
string(28) "Why is Monty Python popular?"
[2]=>
array(4) {
[9]=>
array(3) {
[0]=>
int(9)
[1]=>
string(28) "Because people find it funny"
[2]=>
string(3) "yes"
}
[10]=>
array(3) {
[0]=>
int(10)
[1]=>
string(13) "Because it is"
[2]=>
string(2) "no"
}
[11]=>
array(3) {
[0]=>
int(11)
[1]=>
string(21) "Because of the French"
[2]=>
string(2) "no"
}
[12]=>
array(3) {
[0]=>
int(12)
[1]=>
string(13) "It's popular?"
[2]=>
string(2) "no"
}
}
}
}
I had more to write, but I'm about to go to a Superbowl party, so I'll edit this post with more info later.
Related
How do I get all GET values from a URL? (Missing Values)
I am looping through GET values and only getting 13 values, not matter what URL I submit. Also, it is not getting the values in sequential order... When I loop through I only get 13 values, as well as when I use a var_dump on $_GET itself; even though there are many more values to retrieve. Here is the URL: website.com/Questionaire.php?SurveyName=TV%20Quiz&SurveyType=MultipleChoice&Q1=Choose%20a%20character%20off%20of%20Happy%20Days?&A1=Benny%20the%20bull&A2=The%20Fonz&A3=Jack%20Cracker&Q3=Favorite%20Friends%20character?&A1=Ross&A2=Monica&A4=Joey&A5=Rachel&A6=Chandler&A7=Phoebe&Q8=Favorite%20Nickelodeon%20show?&A1=Hey%20Arnold!&A2=Rugrats&A8=Ahhhh!%20Real%20Montsters Here are my results: SurveyName: TV Quiz SurveyType: MultipleChoice Q1: Choose a character off of Happy Days? A1: Hey Arnold! A2: Rugrats A3: Jack Cracker Q3: Favorite Friends character? A4: Joey A5: Rachel A6: Chandler A7: Phoebe Q8: Favorite Nickelodeon show? A8: Ahhhh! Real Montsters As you can see the results are not in sequential order and some values are even missing. var_dump($_GET); foreach ($_GET as $key => $value) { echo $key.": ".$value."<br/>\n"; } I expect these results: SurveyName=TV Quiz SurveyType=MultipleChoice Q1=Choose a character off of Happy Days? A1=Benny the bull //<- missed A2=The Fonz //<- missed A3=Jack Cracker Q3=Favorite Friends character? A1=Ross //<- missed A2=Monica //<- missed A4=Joey A5=Rachel A6=Chandler A7=Phoebe Q8=Favorite Nickelodeon show? A1=Hey Arnold! A2=Rugrats A8=Ahhhh! Real Montsters
You cannot have identical parameter names in your query string, otherwise the last value will overwrite the previous ones. You need to have unique answer names or you will lose data. You can imagine PHP adding the parameters to $_GET with the following pseudo-code: foreach($param as $key=>$val) { $_GET[$key] = $val; } Because of this, parameters appear in the order in which they first show up in the request. So the query string ?A=1&B=2&A=3&C=4 will have A appear first, then B, and finally C. The last value for an identical parameter is the one used, so we get the following $_GET result: array( 'A'=>3, 'B'=>2, 'C'=>4 ); Consider adding the question identifier as a prefix for each answer. For example, instead of A1 do Q1A1 and Q2A1. This will ensure that your data is not overwritten.
I would suggest using array notation for query string parameter names so that order is maintained. Something like: ?SurveyName=TV Quiz &SurveyType=MultipleChoice &Q[1]=Choose a character off of Happy Days? &A[1][1]=Benny the bull &A[1][2]=The Fonz &A[1][3]=Jack Cracker &Q[3]=Favorite Friends character? &A[3][1]=Ross &A[3][2]=Monica &A[3][4]=Joey &A[3][5]=Rachel &A[3][6]=Chandler &A[3][7]=Phoebe &Q[8]=Favorite Nickelodeon show? &A[8][1]=Hey Arnold! &A[8][2]=Rugrats &A[8][8]=Ahhhh! Real Montsters When you name query string parameter like that, PHP will parse them into arrays: array(4) { ["SurveyName"]=> string(7) "TV Quiz" ["SurveyType"]=> string(14) "MultipleChoice" ["Q"]=> array(3) { [1]=> string(37) "Choose a character off of Happy Days?" [3]=> string(27) "Favorite Friends character?" [8]=> string(26) "Favorite Nickelodeon show?" } ["A"]=> array(3) { [1]=> array(3) { [1]=> string(14) "Benny the bull" [2]=> string(8) "The Fonz" [3]=> string(12) "Jack Cracker" } [3]=> array(6) { [1]=> string(4) "Ross" [2]=> string(6) "Monica" [4]=> string(4) "Joey" [5]=> string(6) "Rachel" [6]=> string(8) "Chandler" [7]=> string(6) "Phoebe" } [8]=> array(3) { [1]=> string(11) "Hey Arnold!" [2]=> string(7) "Rugrats" [8]=> string(21) "Ahhhh! Real Montsters" } } }
PHP: Incorrect value after assignment
I have really no idea what's happening. The story: I use PDO for a SELECT statement on a database. $sql = "SELECT a,b,c,performance,points,compare FROM normvalues WHERE x=:x AND y=1 AND z=:z"; $stmt = $GLOBALS['PDO']->prepare($sql); $stmt->bindParam(":x",$x); $stmt->bindParam(":z",$z); $stmt->execute(); $res=$stmt->fetchAll(PDO::FETCH_ASSOC); So that's fine and it is working. When I var_dump the $res variable I get something like: array(6) { ["a"]=> string(2) "44" ["b"]=> string(4) "1176" ["c"]=> string(4) "1166" ["performance"]=> string(4) "50.1" ["points"]=> string(1) "1" ["compare"]=> string(2) "-1" } [1]=> array(6) { ["a"]=> string(2) "57" ["b"]=> string(4) "1176" ["c"]=> string(4) "1166" ["performance"]=> string(4) "47.7" ["points"]=> string(1) "2" ["compare"]=> string(2) "-1" } [2]=> array(6) { ["a"]=> string(2) "70" ["b"]=> string(4) "1176" ["c"]=> string(4) "1166" ["performance"]=> string(4) "44.7" ["points"]=> string(1) "3" ["compare"]=> string(2) "-1" } ... That's also okay. But I have to sort the result another way. So I am doing: foreach($res as $e){ $this->normTable[$e['a']][$e['points']]=$e['performance']; $this->normTable[$e['a']]['compare']=$e['compare']; } And now I am completely lost. By assigning $e['performance'] I get wrong values. Actually this should be the performance values. [1176]=> array(4) { [1]=> string(2) "50" ["compare"]=> string(2) "-1" [2]=> string(2) "48" [3]=> string(2) "45" } I already checked the values in the database and they are correct. By doing doubleval() I'd get the right values, but the problem is that not every value is a double but also integer or string. I also tried to typecast with (string) but it's the same result. I have no explanation. Update: It's a very big project and I just tried to minimize it as possible and to make my problem as clear as possible. But now I have figured out something new: I do an 'echo()' of my first variable in the normTable during the loop: foreach($res as $e){ $this->normTable[$e['a']][$e['points']]=$e['performance']; echo "a:".$e['a']." pt: ".$e['points']." perf: ".$e['performance']."-".$this->normTable[1176][1]."\n"; $this->normTable[$e['a']]['compare']=$e['compare']; } and the value is changing from '50.1' to '50'. Still can't figure out the reason. Is there a size limitaion of arrays in PHP? UPDATE 2 and a big SORRY! As I said, it is a big project. So the table I read out, has some values for some attributes twice or more. Actually such a case should not happen. That's why the answer is simple: It became 50 because 50 was assigned. I'm so sorry for having waisted your time. But I totally excluded this case and since I am also coding in C, my first thought was: memory leak - clear case! Thanks for your help.
Meh, I don't have 50 reputation; can't comment only answer. If you replace a with be in your loop, you should get your expected result (given your data sample). I.e.: foreach($res as $e){ $this->normTable[$e['b']][$e['points']]=$e['performance']; $this->normTable[$e['b']]['compare']=$e['compare']; } But I'm not sure this really solves your problem. YMMV.
Adding user's choices to test results
This is a little tricky to explain, so bear with me... I've put together a database-driven test script that works pretty nicely. After a user selects their answers and pushes a submit button, they're forwarded to a page (grade.php) that displays their score. Beneath the score is a copy of the test they just took, with the correct answers highlighted. I would simply like to modify it so that the answers users chose are also highlighted. For example, if a user chose answer A, and that's the correct answer, then it might have a yellow background (indicating it's the correct answer) plus a gold star (indicating a user chose that correct answer). If a user chose B, then it might have a black background (indicating it's an incorrect choice), plus it might have an image depicting a checkmark, indicating that the user chose that incorrect answer. Let's start with the form at the bottom of the test page: <form action="grade.php" method="post" id="quiz"> <input type="hidden" name="PreviousURL" id="url" /> <input type="hidden" name="grade" value="<?php echo $grade; ?>" /> <input type="hidden" name="user_token" value="<?php echo isset($_POST['user_token']) ? $_POST['user_token'] : '' ; ?>" /> <input type="submit" value="Submit Quiz" /> </form> After clicking submit, we're forwarded to grade.php, which has a switch containing answer keys for various tests. In this example, we took a ten-question quiz identified by its URL - px-intro-4. Here's the answer key: $answers = array(1 => array('D'), 2 => array('A'), 3 => array('C'), 4 => array('A'), 5 => array('Libya'), 6 => array('B'), 7 => array('B'), 8 => array('B'), 9 => array('C', 'D'), 10 => array('D')); $total = count($answers); Most are multiple choice questions, where users select the one best answer. In this example, they have to type in an answer for #5, and they have to select TWO options (checkboxes) for #9. If they get every answer correct, echoing var_dump($_POST); displays the following: array(13) { ["q1"]=> array(1) { [0]=> string(1) "D" } ["q2"]=> array(1) { [0]=> string(1) "A" } ["q3"]=> array(1) { [0]=> string(1) "C" } ["q4"]=> array(1) { [0]=> string(1) "A" } ["q5"]=> array(1) { [0]=> string(5) "Libya" } ["q6"]=> array(1) { [0]=> string(1) "B" } ["q7"]=> array(1) { [0]=> string(1) "B" } ["q8"]=> array(1) { [0]=> string(1) "B" } ["q9"]=> array(2) { [0]=> string(1) "C" [1]=> string(1) "D" } ["q10"]=> array(1) { [0]=> string(1) "D" } ["PreviousURL"]=> string(25) "http://g1/test/px-intro-4" ["grade"]=> string(147) " } If they take the test again and miss #9 and don't answer #10 at all, the array changes to this: array(12) { ["q1"]=> array(1) { [0]=> string(1) "D" } ["q2"]=> array(1) { [0]=> string(1) "A" } ["q3"]=> array(1) { [0]=> string(1) "C" } ["q4"]=> array(1) { [0]=> string(1) "A" } ["q5"]=> array(1) { [0]=> string(5) "Libya" } ["q6"]=> array(1) { [0]=> string(1) "B" } ["q7"]=> array(1) { [0]=> string(1) "B" } ["q8"]=> array(1) { [0]=> string(1) "B" } ["q9"]=> array(2) { [0]=> string(1) "B" [1]=> string(1) "D" } ["PreviousURL"]=> string(25) "http://g1/test/px-intro-4" ["grade"]=> string(147) " } To make it more clear, imagine the following text on the results page (grade.php): Where do penguins live? A. Africa B. Antarctica (yellow background, indicating it's the correct answer + a gold star indicating the user chose this correct answer) C. France D. California My page already displays correct and incorrect answers. Can anyone tell me how to superimpose the USER's CHOICES? I'll probably have to jump through a few hoops to make this work, but if you can just point me in the right direction, then I can play with it and maybe ask some more focused questions. I should mention that I have a little experience with jQuery, though I'm working primarily with PHP - just in case there's a jQuery solution.
PHP dynamically load data into a multidimensional array to use in ajax
I'm currently trying to get my php ldap backend to parse the ldap array into a normal array with the following layout (this is to pass back to an ajax call to then output into a table underneath a live directory search): --NA --(dynamic row entry) --name --office address --telephone number --mail I manage to get my code : //NEW ARRAY FOR COLUMN AND ROW $na = array( array( )); //MAKES IT EASIER TO RUN THROUGH ARRAY $barray = array( cn , physicaldeliveryofficename , telephonenumber , mail ); //GOES THROUGH EACH ENTRY OUTPUTTING THAT ROW for ($row=0; $row<$entries['count']; $row++) { echo '<br />'; $na[] = $row; //ADD EACH COL TO ARRAY AND DATA INTO COL for ($col=0; $col<5; $col++) { $na[$row][] = $col; $na[$row][$col] = $entries[$row][$barray[$col]][0]; echo $na[$row][$col] . ' '; } } Working to get the first row of names to output, then the for loop continues and outputs the correct amount of rows (for the parameter I tested with anyway, checked with a series of echo statements). Can anyone give me tips as to why my code isn't working, and how to improve the code. Lastly any more efficient pointers would help as I'm more used to java than PHP. (summer job want it doing in PHP though) Thanks in advance, Joe EDIT - VAR_DUMP array(18) { [0]=> array(5) { [0]=> string(14) "Steven Johnson" [1]=> string(7) "Heywood" [2]=> string(11) "01706694297" [3]=> string(29) "Steven.Johnson#yearsley.co.uk" [4]=> NULL } [1]=> int(0) [2]=> int(1) [3]=> int(2) [4]=> int(3) [5]=> int(4) [6]=> int(5) [7]=> int(6) [8]=> int(7) [9]=> int(8) [10]=> int(9) [11]=> int(10) [12]=> int(11) [13]=> int(12) [14]=> int(13) [15]=> int(14) [16]=> int(15) [17]=> int(16) } **EDIT 2 - SOLUTION: After Barbara's comment I output the var_dump above, this lead me to see that the problem at hand was that the array was being declared in numerous different instances which was affecting the end array. Since I was instantiating the first row as a single array, then instantiating it as a multidimensional array then finally adding the data into the array. To solve the problem I simply removed the $na[] = $row and $na[$row][] = $col parts to correctly make the array. **
A list of arrays contained in a master array PHP
I hope I can make this question clear enough. I'm looking to put a list of arrays inside one master array, dynamically, so that it looks like this: masterarray { array1 { [0]=>VAL1 [1]=>VAL2 } array2 { [0]=>VAL1 [1]=>VAL2 } array3 { [0]=>VAL1 [1]=>VAL2 } } I've tried, but I could only get it to look like this: array(1) { [0]=> array(2) { [0]=> string(1) "1" [1]=> string(13) "CODE" } } array(2) { [0]=> array(2) { [0]=> string(1) "1" [1]=> string(13) "CODE" } [1]=> array(2) { [0]=> string(1) "1" [1]=> string(13) "CODE" } } array(3) { [0]=> array(2) { [0]=> string(1) "1" [1]=> string(13) "CODE" } [1]=> array(2) { [0]=> string(1) "1" [1]=> string(13) "CODE" } [2]=> array(2) { [0]=> string(1) "1" [1]=> string(13) "CODE" } } And that's definitely not what I'm aiming for. Nothing seems contained. I need the format specified above. I'm using the explode function on a string pulled from a file to make this table of arrays (I think you call it that) Here is the code I'm using that's not working. $variabledebugging = file("FILE.TXT");//LOOK IN THIS FILE FOR THE NUMBER AND SET IT TO A VAR. $i=0; foreach($variabledebugging as $placeholder){ $variabledebuggingtbl[] = explode("\t",$variabledebugging[$i]); var_dump($variabledebuggingtbl); $i++; } I've tried a couple of different variations, but that's the one I'm using now. To be clear, that file being pulled (each line as a value in an array) has 2 things written to each line, separated by a tab character, so that's the system I'm going on. Thank you! I'm sure this is a simple task, I just can't think it through. Oh and while I'm at is there a way to make debugging more readable?
You ARE getting the right result. The reason it seems wrong is that you are running var_dump inside the loop. And why don't you use the $placeholder variable? $variabledebugging = file("FILE.TXT"); foreach($variabledebugging as $placeholder){ $variabledebuggingtbl[] = explode("\t", $placeholder); } var_dump($variabledebuggingtbl); I'm not sure what you mean by "making debugging more readable", but if you want some linebreaks and indentation you should just look in the generated HTML code. var_dump do add spacing to make it readable but it is ignored by the web browser. If you don't want to read the HTML source, just add your var_dump to a <pre> element.