Basically here is the scenario:
I am trying to generate a test from a database. Each test has many questions(items) each item is of a certain type (multi-choice etc), each question has multiple answers attached to it.
(I'm not looking for somebody to tell me im going about it all wrong)
I currently, loop through my query results and print out every question there. Within that loop I execute a function (present_question) for every question. Within this function is a switch case, which identifies the item type. Within each case, I run another loop to print out all the answers attached to that question.
What I am trying to do, is insert each question into a unique <div> so that I toggle the display etc between each question as they select a button for each so 1,2,3,4 etc.
However, it would appear I am struggling with this. My questions all print out, however It appears they are not within individual <divs> as I tried testing it by changing some attributes of the class and its doing nothing. :(
Here is the main code covering the whole procedure:
main loop:
//loop through every question present in query results and run function to present the different question structures
while ($qs = mysql_fetch_assoc($get_questions))
{
$type = $qs['item_type'];
$item_id = $qs['item_id'];
$question = $qs['question_text'];
echo "<div class='q_center' id='q_$q_num'>"; // insert each question into its own div
echo "<h2>Question No.$q_num </h2><br>";
echo "$question <br>"; // print out actual question
present_question($item_id, $type);
$q_num ++;
}
present_question function
function present_question($ID, $type){
// grab all the answers attached to the question
$get_answers = mysql_query("SELECT * FROM answers_tb WHERE item_id='$ID'");
echo "<form>";
// switch for different structured questions. (switched by question type)
switch ($type)
{
case "1":
multi_choice($get_answers); // just working on this type at the moment
break;
case "2":
echo "this type hasnt been done yet";
break;
}
echo "</div>";
echo "</form>";
return;
}
function for multiple choice type
function multi_choice($get_answers){
while ($answers = mysql_fetch_assoc($get_answers))
{
$as = $answers['text_value'];
echo "<input type='radio' name='1' value='$as'>$as<hr />";
}
return;
}
hopefully you guys can help me.
I am a beginner, so I do apologise if my code is an abomination :D
thanks,
rough version (untested)
$i = 0; //declares the counter $i
//loop through every question present in query results and run function to present the different question structures
while ($qs = mysql_fetch_assoc($get_questions))
{
$type = $qs['item_type'];
$item_id = $qs['item_id'];
$question = $qs['question_text'];
$i++; // adds 1 to $i
echo "<div class='q_center' id='q_$q_num'>"; // insert each question into its own div
echo "<h2>Question No.$q_num </h2><br>";
echo "<div class=question" .$i. ">"; //appends $i to the div name creating question[$i]
echo "$question <br>"; // print out actual question
echo "</div>";
present_question($item_id, $type);
$q_num ++;
}
should make div's named question1, question2, etc
Related
I'm creating a website using PHP for the logic part of it.
It is a dynamic test. A set of questions are presented to the user and depending on his answers, a new set of questions will appear, thus, the questions will always be different if the answers are different.
In the form of the test, I have used POST to get the answers of the user and the action is empty because I want the page to reload but with different arguments (POST) every time. I also use a recursive function that takes the ID's of the next questions to be presented and the level (set of questions) just to not get lost. This recursive function also uses the arguments in POST to, again, obtain the user's answers so it can get the next questions at my DB.
function searchTree($arrNodes, $nivel){
$nxtQ = array(); $j=1;
$arr=getPreguntas($arrNodes,$nivel); //arr has "question" objects
$numPreg=count($arr);
for ($i=0; $i < count($arr); $i++) {
$arrayA[$i] = treeRule($arr[$i]->idPreg); //Array[i] is the set of related rules
}
echo '<form action="" method="post">';
for ($i=0; $i < $numPreg; $i++) {
echo $arr[$i]->pregunta .'</br>';
insertHTML($arr[$i]->idPreg, $numPreg, $j, $nivel); //Add HTML
$j++;
}
echo '</br><input type="submit" id="buttonSend'.$nivel.'" name="buttonSend'.$nivel.'" value="Enviar respuesta">';
echo '</form>';
$button= 'buttonSend'.$nivel;
if(isset($_POST[$button])){ //If the user answered
for ($i=0; $i < count($arrayA); $i++) { //arrayA has all related rules
if(!empty($arrayA[$i])){ //At least one related rule
$radio = 'valorRadio'.($i+1).'_'.$nivel;
$node = 'idNode'.($i+1).'_'.$nivel;
$answ[$i] = analize($_POST[$radio],$_POST[$node],$arrayA[$i],$i+1, $nivel); //$answ is the set of related rules which happened to be true
if($answ[$i]!=null){
echo 'True related rule: '.$answ[$i].' </br> ';
}else{
echo 'Answer all questions';
}
}else{ //End of analysis
echo 'No related rules </br>';
}
}
$relatedMR = getmetaRules($arrayA);
for ($i=0, $j=0; $i < count($relatedMR); $i++) {
$res = analizeMR($relatedMR[$i], $arrayA);
if($res=='1'){
$nxtQ[$j] = getNxtQ($relatedMR[$i]); //nxtQ is the set of next questions' IDs
$j++;
}
}
if($nxtQ!=NULL){
$_POST=array();
$arrNodes = array();
searchTree($nxtQ,($nivel+1));
}else{
echo 'End of test';
}
}else{
time_sleep_until($_POST);//Wait for an answer
}
}
I call this function at the beginning of my program like this:
searchTree(initialNodes(1),1);
initialNodes() function only enters the DB and gets the questions with level 1.
The first and second set of questions are presented (kind of) correctly (the first set of questions is always present and the second one appears under it, but that can be fixed at front-end.), however, the third one if not working anymore. The POST arguments are there but the new questions and radio buttons do not appear.
First set and POSTFirst and second set and POSTThird attempt and POST
I created an easier example of this by not using "sets of questions" but only one question each time. The first and second questions work as I previously mentioned but for the third one, the second one is replaced by the third and the third by the fourth and so on.
I don't know if my program is getting confused by the names of my HTML elements, if my recursive function is wrong or something else.
I'm just starting out with php and wanted to do a fun project to get better with it. I created a text file that starts with the question, then has the answer choices, and then has the answer index:
What does charmander evolve to?#Charmeleon:charizard:squirtle#0
Who is the main character in Pokemon?#Misty:Ash:Brock#1
How can I generate radio buttons based on the number of questions there are?
<?php
$quizStuff = file("quiz1.txt");
foreach ($quizStuff as $questions) {
$questionParse = explode("#", $question);
$answerChoices = explode(":",$questionParse[1]);
echo "$questionParse[0] ? <br />";
foreach ($answerChoices as $answerChoice) {
# create radio button and print answer choice next to it
}
}
?>
Since radio buttons are a type of form, I was thinking that I would have a submit button at the end of the question and the next question would pop up after a user pressed submit. General design input would be great too!
I am not used to making text file as a database but here is what i see a solution. I put a counter to identify which question is where the choices are included.
$ctr = 1;
foreach ($quizStuff as $questions) {
$questionParse = explode("#", $question);
$answerChoices = explode(":",$questionParse[1]);
echo "$questionParse[0] ? <br />";
foreach ($answerChoices as $answerChoice) {
echo "<input type='radio' id='".$answerChoice.$ctr."' name='question$ctr' value='$answerChoice'> <label for='".$answerChoice.$ctr."'>".$answerChoice."</label><br>"
}
}
I am using Jquery UI Selectable. The user has the option to dynamically add new list items to the original setup.
I would like to include a 'clear' button that will give the user the ability to clear each individual item they created by clicking on an X input submit (img).
HTML (php)
if ($this->session->userdata('inactivefilter') == true) {
$inactivefilter = $this->session->userdata('inactivefilter');
$i=0;
foreach ($inactivefilter as $filter)
{
$filterdash = implode('-', explode(' ', $filter));
echo "<li class='ui-state-default' id='$filterdash'>$filter</li>";
echo "<div id=clear>
<form method='POST' action='".base_url()."main/clear_filter'>
<input type='image' name='filtervalue' value='$i' src='".base_url()."img/board/icons/clear.png'></input>
</form>
</div>";
$i++;
}
}
This is where the list is created. specifically the clear_filter action form.
Clear_filter currently 'attempts' to grab the value of '$i' but I don't know how to pass that correctly.
here is the controller:
public function clear_filter()
{
$i = $_POST['filtervalue'];
$this->thread_model->clear_filter($i);
}
I'll omit the clear_filter model due to its irrelevance to the problem.
Essentially, I just need $i to be picked up based on whatever value is clicked on in the dynamic form on the actual page.
Any help would be appreciated!
Well, it seems like I just had things a bit backwards.
The code was more or less correct.
For Codeigniter, you catch the passed input value=$i by using the name ="filtervalue"
Change the controller code to :
$i = $this->input->post('filtervalue');
and $i is set to whatever value was clicked on.
I've previously made a text file and turned it into multidimensional array to display as the questions for my quiz.
Note: I am unable to insert images therefore I cannot provide any example so I'll try to be as descriptive as I can.
I'm trying to display only one question at a time, every time a user clicks on my quiz.
This is my code so far. The main.php page:
<h2>ONLINE QUIZ</h2>
<ul>
<li><a href='question.php'>Take quiz</a></li>
<li><a href='module.php'>Admin Module</a></li>
</ul>
<?php
$file = fopen('data.txt', 'r');
$array = array();
while ($line = fgetcsv($file)) {
$array[] = $line;
}
fclose($file);
session_start();
$_SESSION["questions_array"]=$array;
?>
And the question.php page:
<?php
session_start();
$array=$_SESSION["questions_array"];
foreach ($array as $q => $data) {
echo '<p>'.array_shift($data).'</p>';
foreach ($data as $a => $answer) {
echo
' <input type="radio" name="question-'.$q.'" id="question-'.$q.'"'.
' value="'.$a.'"/>'.
' <label for="question-'.$q.'">'.$answer.'</label>'.
'<br>';
}
}
?>
When the Take quiz link is clicked, the user is taken to the question page where only one question is shown. The user then picks an answer and hits submit. This submit button will take the user to the result page where they can then hit continue.
The Continue link will redirect them back to the question page where the next question is displayed.
From stuff that I've done before, I am attempting to use the isset() function to make this happen. However, the problem is that I'm not sure how exactly to write my isset().
I've found this snippet from this site, I'm not sure if it's useful, but:
if (!isset($_SESSION['FirstVisit'])) {
//show site for the first time part
$_SESSION['FirstVisit] = 1;
header("Location: http://example.com/index.php");
// Don't forget to add http colon slash slash www dot before!
} else { Show normal site }
But once again I found myself blank. How exactly do I use the isset() to display only one question?
I kinda get what your asking, Ive jotted out the basic structure. This can all be done on one page, hope it helps.
EDIT:
As im such a nice guy heres a complete script, using my prev suggestion ;p
<?php
session_start();
echo '<h2>ONLINE QUIZ</h2>';
//Scores
if($_SERVER['REQUEST_METHOD']=='GET' && isset($_GET['scores'])){
echo 'Basic output for scores';
echo '<pre>';
print_r($_SESSION['answers']);
echo '</pre>';
unset($_SESSION['answers']);
unset($_SESSION['question']);
}
//Session question/array is set
if(isset($_SESSION['question']) && isset($_SESSION['questions_array'])){
//Handle prev question post
if($_SERVER['REQUEST_METHOD']=='POST'){
//process prev question
$_SESSION['answers'][$_SESSION['question']-1]=(0+$_POST['answer']);
}
if($_SESSION['question'] < $_SESSION['total_question']){
$q=$_SESSION['question'];
//EDIT - Shuffle answers for output
//Hold the question into a var
$question = $_SESSION['questions_array'][$q][0];
//unset the question from the array
unset($_SESSION['questions_array'][$q][0]);
//put all the pos answers into a new array
$answers = $_SESSION['questions_array'][$q];
//shuffle the answers
shuffle($answers);
echo '<form method="POST" action="">
<h3>'.$question.'</h3>';
//loop through the answers
foreach($answers as $key=>$value){
//if the value is nothing cont to next, removed question key 0
if($value==''){continue;}else{
echo '<p><input type="radio" value="'.$value.'" name="answer">'.$value.'</p>';
}
}
echo '<p><input type="submit" value="Submit"></p>
</form>';
}else{
//Quiz Complete
echo 'Test Complete Check scores';
}
//Assign next question to session
$_SESSION['question']++;
}else{
//Pages first load so show quiz index
$_SESSION['question']=0;
get_questions();
?>
<ul>
<li><a href='<?=basename($_SERVER["SCRIPT_FILENAME"]);?>'>Take quiz</a></li>
<li><a href='module.php'>Admin Module</a></li>
</ul>
<?php
}
//Function to put questions in session
function get_questions(){
$file = fopen('data.txt', 'r');
$array = array();
while ($line = fgetcsv($file,1000,',')) {
$array[] = $line;
}
fclose($file);
$_SESSION['questions_array']=$array;
$_SESSION['total_question']=count($array);
return;
}
?>
Okay so the solution to your problem to do another array shift on the outter array. By this you can pull off one question and print it out. The quiz is preserved in the session, so the next time the page loads (i.e. the continue button is clicked) it pulls off the next question.
Questions Page:
<?php
session_start();
if(sizeof($_SESSION['questions_array']) > 0 )
{
// Get the next question off of the Quiz in our SESSION
$data = array_shift($_SESSION["questions_array"]);
echo '<p>'.array_shift($data).'</p>'; // pop the question
//list out the possible answers
foreach ($data as $a => $answer)
{
echo
' <input type="radio" name="question-'.$q.'" id="question-'.$q.'"'.
' value="'.$a.'"/>'.
' <label for="question-'.$q.'">'.$answer.'</label>'.
'<br>';
}
}
else
{
//questions array is empty, show quiz complete page
}
?>
Now your questions page only brings back one question. When submit is clicked they go to the answers page. When continue is clicked they come back. Our system then does as follows:
1) Are there questions left in our array?
A)Yes
A.1) Okay pop the next question with array_shift($_SESSION['questions_array'])
A.2) Pop the question then list the answers.
B)No
B.1) No more questions, our quiz is over.
Note: There are some draw backs. If the person refreshes the page they get a new question and the other one goes unanswered. You could alternatively pass a $counter variable that updates each time the answer page loads. Then pass that counter to the $_SESSION array to bring back the next question. It's up to you.
I have a personal message system in my website done simply with php/sql. Actually I am facing the trouble to display them using jquery. The db has as fields: message_id, message_from, message_to, message_topic, message_subject and message_status. The way I am showing the message_topic is repeating eight times the following:
echo '<table><tr><td>';
retrieve_msg_topic($result);
echo '</td></tr>'; //of course I won't make 8 tables!!!
the function called is:
function retrieve_msg_topic($result)
{
if($row = mysql_fetch_assoc($result))
{
echo $row['usernombre'];
$message_topic = stripslashes($row['message_topic']);
echo '<div id="msg'.$row['message_id'].'">';
echo $message_topic;
echo '</div>';
//this will return: <div id="msgN">message topic (title, commonly subject)</div>
}
} //end function retrieve msg topic
So far I have a list on a table with the last eight messages sent to the user. The following row is reserved for pagination (next/prior page) and, after that, another row showing the message I select from the list presented, like we see in Outlook. Here is my headache. My approach is to call another function (8 times) and have all of them hidden until I click on one of the messages, like this:
echo '<tr><td>';
retrieve_msg_content($result);
retrieve_msg_content($result); //repeat 8 times
echo '</td></tr></table>';
the function this time would be something like this:
function retrieve_msg_content($result)
{
if($row = mysql_fetch_assoc($result))
{
echo '<script type="text/javascript">
$(document).ready(function(){
$("#msg'.$row['message_id'].'").click(function(){
$(".msgs").hide(1000);
$("#'.$row['message_id'].'").show(1000);
});
});
</script>';
echo '<div class="msgs" id="'.$row['message_id'].'" style="display: none">'
.$row['message_subject'].
'</div>';
}
/* This function returns:
// <script type="text/javascript">
// $(document).ready(function(){
// $("#msgN").click(function(){
// $(".msgs").hide(1000);
// $("#N").show(1000);
// });
// });
// </script>
// <div class="msgs" id="N" style="display: none">Message subject (body of message)</div>
*/
} //end function retrieve msg content/subject
I could simply explain that the problem is that it doesn't work and it is because I do if($row = mysql_fetch_assoc($result)) twice, so for the second time it doesn't have any more values!
The other approach I had was to call both the message_topic and message_subject in the same function but I end up with a sort of accordion which is not what I want.
I hope I was clear enough.
The easiest way to fix your troubles would be to copy the results of the MySQL query into an array
while($row = mysql_fetch_assoc($result)) {
$yourArray[] = $row;
}
And then use that to build your tables.
edit: What I meant was more along the lines of this:
while($row = mysql_fetch_assoc($result)) {
$yourArray[] = $row;
}
echo '<table>';
foreach($yourArray as $i) {
retrieve_msg_topic($i);
}
echo '<tr><td>';
foreach($yourArray as $i) {
retrieve_msg_content($i);
}
echo '</tr></td></table>';
And then removing everything to do with the SQL query from those functions, like this:
function retrieve_msg_topic($result) {
echo '<tr></td>'$result['usernombre'];
echo '<div id="msg'.$result['message_id'].'">';
echo stripslashes($result['message_topic']);
echo '</div><td></tr>';
}
Right now you're doing some weird key mojo with ret[0] being the topic and $ret[1] being the message, which isn't a good practise. Also, I don't see the declaration of $i anywhere in that code.
The error suggests that the result is empty or the query is malformed. I can't be sure from the code I've seen.
A few other notes: it seems weird that you're using stripslashes() on data that's directly from the DB. Are you sure you're not escaping stuff twice when inserting content into the DB?
Always use loops instead of writing something out x times (like the 8 times you said in your question). Think of a situation where you have to change something about the function call (the name, the parameters, whatever). With loops you have to edit 1 place. Without, you need to edit 8 different places.
BTW, another solution to this problem would be using AJAX to load content into the last cell. If you're curious, I could show you how.
more edits:
For AJAX, build your message list as usual and leave the target td empty. Then, add a jQuery AJAX call:
$('MSG_LIST_ELEMENT').click(function() {
var msgId = $(this).attr('id').replace('msg','');
$.get(AJAX_URL+'?msgID='+msgId,function(data) {
$('TARGET_TD').html(data);
})
});
Replace the capitalized variables with the ones you need. As for the PHP, just echo out the contents of the message with the ID $_GET['msgID'].
However, make sure you authenticate the user before echoing out any messages, so that someone else can't read someone's messages by switching the id number. Not sure how authentication works on your site, but this can be done by using session variables.