Modifying $_POST variable before submitting - php

I'm making a quiz generator, and I have an HTML form with radio buttons for multiple choice answers. Right now, when I submit my form, the contents of the $_POST variable looks like this when I submit it:
Array ( [a1] => Bob [a2] => Bobby )
(Bob and Bobby are the radio button choices I picked)
I'm generating this form using a PHP function, which returns an array of answers in addition to echoing the HTML form. Is there a way to modify the $_POST variable to have an 'answer' field (for checking my answers), like this:
Array( [a1] => Bob [a2] => Bobby [answers] => Array( [0] => Bob [1] => Bilbo ))
The above was one way I thought of to check answer array with $_POST array.
Edit: More info on what I have so far:
I have a PHP function getTest() that echoes the HTML form, and returns an array with the correct answers.
getTest() generates each question randomly, and as such the correct answers are random.
The main problem is that I have two separate PHP files, questions.php and verify.php.
questions.php echoes the form using getTest(), and has the array of answers.
verify.php only has the contents of $_POST, BUT NOT the array of correct answers.
Is there a better way to check the results of the form submission in general? Thanks!

The best way to do a quiz is to have an answers array and a user input array. Loop through one and compare to the other using the same increment.
You can take all of your post variables and create an array print_r($_POST); Then, loop through this.
$inputArray = //the post data into an array
$answerArray = array('a','b','a');
$numCorrect = 0;
for($a = 0; $a < count($inputArray); $a++)
{
if($inputArray[$a] == $answerArray[$a])
{
$numCorrect++;
}
}

If you want to transmit the answers when submitting the form, you could use inputs of hidden type (like ) which are invisible on the page. However it only takes the user checking the source HTML of the page to see these answers, so it might not be good for your use. Hope this helps

I think what you need to do is a have a look at sessions.
That way on questions.php you can save the answers to a session variable,
Then on verify.php you can read the answers from the session variable and compare them to answered supplied by the $_POST variable

If you really wanted to, you could probably just use a hidden field in your form for submitting an answer array. However, anyone can change your source and modify what the correct answer is.
The best way is to just have an array in your processing script with the same keys (a1, a2), but with the correct answers.
Your processing script would look like this:
$answers = array('a1'=>'Robert', 'a2'=>'Hobo');
foreach($_POST as $key => $value)
{
if (!array_key_exists($key, $answers))
{
continue;
}
if (trim($value) == $answers[$key])
{
// correct
}
else
{
// incorrect
}
}

If you want $_POST to contain an array you can simply use the bracket array notation on the name field of your form.
For example:
<fieldset class="Question1">
<input type="radio" name="answers[]" value="Question1Answer1">Question1Answer1<br>
<input type="radio" name="answers[]" value="Question1Answer2">Question1Answer2<br>
<input type="radio" name="answers[]" value="Question1Answer3">Question1Answer3<br>
</fieldset>
<fieldset class="Question2">
<input type="radio" name="answers[]" value="Question2Answer1">Question2Answer1<br>
<input type="radio" name="answers[]" value="Question2Answer2">Question2Answer2<br>
<input type="radio" name="answers[]" value="Question2Answer3">Question2Answer3<br>
</fieldset>
<fieldset class="Question3">
<input type="radio" name="answers[]" value="Question3Answer1">Question1Answer1<br>
<input type="radio" name="answers[]" value="Question3Answer2">Question1Answer2<br>
<input type="radio" name="answers[]" value="Question3Answer3">Question1Answer3<br>
</fieldset>
(Note that the fieldset tag is optional, I just included it to group things together)
The output in post will be an array $_POST['answers'] that will have one element for each question. So if you selected answer 1 for question 1, answer 2 for question 2, and answer 2 for question 3 you'd have:
$_POST['answers'] = [ 'Question1Answer1', 'Question2Answer2', 'Question3Answer2' ]

Not sure, but looks like you are asking for solution Y, whereas your problem is X (XY Problem)
The XY problem is when you need to do X, and you think you can use Y
to do X, so you ask about how to do Y, when what you really should do
is state what your X problem is. There may be a Z solution that is
even better than Y, but nobody can suggest it if X is never mentioned.
Usually it is not recommended to modify $_POST array, and also not to transmit Answers with the questions to client-side. Instead, the approach should be that because questions.php dont need answers, but verify.php does, so only verify.php shoul have access to answers.
For example, answer-lists are never transported to examination halls along with the question papers on the occasion of exams.
I have taken the liberty to modify your code structure. If you still want to go with your own code, please post it, and then you can get the answers you want.
Try to use this:
question.php:
<form action="verify.php" method="POST">
<fieldset class="Question1"> Complete this: ___<b>bar</b>
<input type="radio" name="answers[]" value="foo">Foo<br>
<input type="radio" name="answers[]" value="too">Too<br>
<input type="radio" name="answers[]" value="cho">Cho<br>
</fieldset>
<fieldset class="Question2"> Complete this: ___<b>overflow</b>
<input type="radio" name="answers[]" value="stack">Stack<br>
<input type="radio" name="answers[]" value="stock">Stock<br>
<input type="radio" name="answers[]" value="stick">Stick<br>
</fieldset>
</form>
answers.php:
//correct answers
$answers = array("foo", "stock");
verify.php:
include("answers.php");
$user_answers = $_POST["answers"];
$user_answers_count = count($user_answers);
$error = "";
for($i=0;$i<$user_answers_count;$i++)
if($user_answers[$i] !== $answers[$i]) //verify
$error[] = "Answer for Question ".($i+1)." is wrong!";
if(empty($error))
//Notify that user has passed the Quiz
else
//Notify that user has NOT passed the Quiz
//print the $error array
Couple of Notes:
I have used answers.php as a different file, but if there is no special requirement, consider merging answers.php & verify.php (put answers.php code on top of verify.php) Even better, you could also merge all these three files into one.
I have assumed that $_POST is sanitized.
Sequence of Questions & answers array is same. i.e. answers[foo] is correct answer for $_POST["answers"][foo]

Related

get input from html form in PHP by iterations

I am creating a webpage which display a form with 16 questions, each row of input looks like:
<li>*question 1*</li>
<input type="text" name="answer1" style="height: 40px;" size="50" dir="rtl">
<li>*question 2*</li>
<input type="text" name="answer2" style="height: 40px;" size="50" dir="rtl">
and so on - i have 16 (html) lines like that
(by the way, is there a way to prevent this code duplication? this code smells...) and in the end a 'submit' button.
my php script should receive these answers, and put every answer in a variable called "answer(i)" e.g I can write 16 lines of this kind:
if (isset($_POST['submit'])) {
$answer1 = $_POST['answer1'];
$answer2 = $_POST['answer2'];
...ect.
...
}
this (also) feels like a lot of code duplication. is there a way to make it more general and efficient so that if i'm looking to add some new question I won't have to goo through all this again?
I am new to PHP and HTML, and I though of declaring some functions and call them everytime but when I googled keywords like 'html functions' etc. I didn't find and helping info.
edit: The answers labels maybe different than 'answer1, answer2...' and can be a set of different words ('age', 'gender'...)
For the HTML use something like this:
$questions = array(
'question1',
'question2',
//...
);
foreach($question as $id => $qText){
?>
<li>
<?php echo $qText ?>
<input type="text" name="answers[]" style="height: 40px;" size="50" dir="rtl">
</li>
<?php
}
On PHP side you would have your answers in $_POST['answers'], it would be an array. And believe me, if you want to put this values from array into separate variables, it is a red flag: something wrong with your code. You do not want to have a set of answers as independent variables.
You could run a loop to go through the POST array and extract the information into another array.
foreach ($_POST as $k => $v) {
$$k = $v;
}
That will put all of the $_POST data into PHP variables named the same as the form fields generating them (beware you will also get a $submit as well from the button triggering the form).
Is this what you are looking for?
foreach (range(0,16) as $i)
{
${'answer'.$i} = $_POST['answer'.$i];
}
or use extract(), If you apply on your $_POST, keys in your $_POST variable gets assigned as variable.
Here is official documentation.

Updating hidden input depending on what user has checked

I've created a test system that has multiple steps (using jquery) allowing users to check checkboxes to select their answers, with a summary page and a final submission button... all within a form. I now want to create the scoring system.
1) Firstly this is the code (within a loop) that grabs the answers from Wordpress for each question:
<input type="checkbox" name="answer<?php echo $counter; ?>[]" value="<?php echo $row['answer']; ?>" />
2) In Wordpress next to each answer is a dropdown with a yes or no option to mark whether the answer is right or wrong. This is output in the following way:
<?php $row['correct']; ?>
3) Each correct answer the user checks should be worth 1 point. The passmark is determined by the field:
<?php the_field('pass_mark'); ?>
4) I want it to update a hidden field with the score as the user checks the correct answer:
<input type="hidden" value="<?php echo $score; ?>" name="test-score" />
How can I update the hidden field with the user score as the user is checking the correct answer? I'm not sure what to try with this to even give it a go first!
Ok, everyones spotted a big hole in this. I'm completely open to doing it a hidden way so people can't check out the source. The type of user this is targeted at wouldn't have a clue how to look at the source but might as well do it the right way to start with!
The whole test is within a form so could it only update the hidden field on submit?
I still need some examples of how to do it.
In my opinion you should use sessions for that purpose, because any browser output may be saved and viewed in ANY text editor. This is not right purpose oh hidden input elements. You use hidden inputs when you need to submit something automatically, but never use it when processing some important data.
Mapping your questions and answers via id will allow you not to reveal real answers and scores in HTML.
Just a very simple example how to do that:
<?php
$questions = array(
125 => array("text"=>"2x2?", "answer"=>"4", 'points'=>3),
145 => array("text"=>"5x6?", "answer"=>"30", 'points'=>2),
);
?>
<form method="post">
<?php foreach ($questions as $id => $question): ?>
<div><?php echo $question['text'] ; ?></div>
<input type="text" name="question<?php echo $id ; ?>"/>
<?php endforeach ; ?>
<input type="submit" value="Submit"/>
</form>
/* In submission script */
<?php
if (isset($_POST['submit'])){
foreach($questions as $id => $question){
if (isset($_POST["question{$id}"])){
$answer = $_POST["question{$id}"] ;
if ($answer === $question['answer']){
$_SESSION['score'] += $question['points'] ;
}
}
}
}
Spokey is right - the user would be able to cheat if your score it on the client side like using the method you suggested.
Instead, either user a JQuery $.post call to post each answer and then store the score in a PHP Session. Or just wait until the entire form is submitted and evaluate the score of the form as a whole on the server side.
* Update *
You have to submit the form to a script that can evaluate the form. So say it gets submitted to myForm.php
In myForm.php, get the post vars:
$correct_answers = $however_you_get_your_correct_answers();
//Assuming $correct_answers is a associative array with the same keys being used in post -
$results = array();
if($_POST){
foreach ($_POST as $key=>$value) {
if ($_POST[$key] == $correct_answers[$key]){
$results[$key] = 'correct';
}
else $results[$key] = 'incorrect';
}
}
This is untested, but it should work.

accessing dynamic variables from a form

I used to have register_globals turned ON (I know - bad bad bad horribly bad) and now I'm changing it up and the specific application is my DVD collection. Adding a DVD presents a set of checkboxes for genres/categories (i.e. drama, comedy, etc). Each genre is coming out of a database table so I can add new genres as needed. The problem here is that it generates its fieldname (checkbox name) from an abbreviation in this db table.
IE I'll have:
<input type="checkbox" name="drama" />Drama
<input type="checkbox" name="bio" />Biography
(etc)
So what I was doing before was, with the script that made the entries, it would run through the list of abbreviation names and if it matched the input ($_POST['drama']), it would indicate that this DVD falls into that category.
The present problem now is, with global variables turned off, how can I dynamically gather those $_POST values? I tried looping through the database and spitting out a concatenated variable trying to declare them in this format:
$drama=$_POST['drama'];
This didn't work because I'm mixing up functions with variables and it made a horrible mess.
I hope someone has an answer on how I can read in the $_POST array and use it.
Given some checkboxes like this:
<input type="checkbox" name="genre[]" value="drama" />
<input type="checkbox" name="genre[]" value="comedy" />
<input type="checkbox" name="genre[]" value="mystery" />
you'd end up with $_POST['genre'] being an array. Asuming drama and mystery are checked off, you'd end up with
$_POST['genre'] = array(
0 => 'drama',
1 => 'mystery'
);
Remember that unchecked checkboxes do not submit with the form, so if you get an entry in $_POST['genre'], it was selected in the form.
To check if a category in your DB was selected, you could do something like
if (in_array('drama', $_POST['genre'])) {
... drama is selected
}
See this example:
foreach ($_POST as $key => $value) {
echo "name: $key, value: $value<br />";
}

PHP avoiding a long POST

This is more of a technique question rather than maybe code. I am having a php form with many fields (items to select). Naturally some of the items might be selected and some not. How do I know which ones are selected when i post the data from page 1 to page 2? I thought of testing each one if empty or not, but there are just too many fields and it doesn't feel at all efficient to use or code.
Thanks,
UPDATE EDIT:
I've tried the following and maybe it will get me somewhere before I carry on testing the repliers solutions...
<html>
<body>
<form name="test" id="name" action="testprocess.php" method="POST">
<input type="text" name="choices[shirt]">
<input type="text" name="choices[pants]">
<input type="text" name="choices[tie]">
<input type="text" name="choices[socks]">
<input type="submit" value="submit data" />
</form>
</body>
</html>
and then second page:
<?php
$names = $_POST['choices'];
echo "Names are: <br>";
print_r($names);
?>
This gives out the following:
Names are: Array ( [shirt] => sdjalskdjlk [pants] => lkjlkjlk [tie]
=> jlk [socks] => lkjlkjl )
Now what I am going to try to do is iterate over the array, and since the values in my case are numbers, I will just check which of the fields are > 0 given the default is 0. I hope this works...if not then I will let you know :)
I think what you're looking for is this:
<form action="submit.php" method="POST">
<input type="checkbox" name="checkboxes[]" value="this" /> This
<input type="checkbox" name="checkboxes[]" value="might" /> might
<input type="checkbox" name="checkboxes[]" value="work" /> work
<input type="submit" />
</form>
And then in submit.php, you simply write:
<?php
foreach($_POST['checkboxes'] as $value) {
echo "{$value} was checked!";
}
?>
The square brackets in the name of the checkbox elements tell PHP to put all elements with this name into the same array, in this case $_POST['checkboxes'], though you could call the checkboxes anything you like, of course.
You should post your code so we would better understand what you want to do.
But from what I understood you are making a form with check boxes. If you want to see if the check boxes are selected, you can go like this:
if(!$_POST['checkbox1'] && !$_POST['checkbox2'] && !$_POST['checkbox3'])
This looks if all the three check boxes are empty.
Just an idea:
Create a hidden input field within your form with no value. Whenever any of the forms fields is filled/selected, you add the name attribute of that field in this hidden field (Field names are saved with a comma separator).
On doing a POST, you can read this variable and only those fields present in this have been selected/filled in the form.
Hope this helps.
Try this.....
<?php
function checkvalue($val) {
if($val != "") return true;
else return false;
}
if(isset($_POST['submit'])) {
$values = array_filter(($_POST), "checkvalue");
$set_values = array_keys($values);
}
?>
In this manner you can get all the values that has been set in an array..
I'm not exactly sure to understand your intention. I assume that you have multiple form fields you'd like to part into different Web pages (e.g. a typical survey form).
If this is the case use sessions to store the different data of your forms until the "final submit button" (e.g. on the last page) has been pressed.
How do I know which ones are selected when i post the data from page 1 to page 2?
is a different question from how to avoid a large POST to PHP.
Assuming this is a table of data...
Just update everything regardless (if you've got the primary / unique keys set correctly)
Use Ajax to update individual rows as they are changed at the front end
Use Javascript to set a flag within each row when the data in that row is modified
Or store a representation of the existing data for each row as a hidden field for the row, on submission e.g.
print "<form....><table>\n";
foreach ($row as $id=>$r) {
print "<tr><td><input type='hidden' name='prev[$id]' value='"
. md5(serialize($r)) . "'>...
}
...at the receiving end...
foreach ($_POST['prev'] as $id=>$prev) {
$sent_back=array( /* the field values in the row */ );
if (md5(serialize($sent_back)) != $prev) {
// data has changed
update_record($id, $sent_back);
}
}

How to retrieve information from Check Box?

My problem is a little bit complicate. (I use PHP)
I have two arrays, (simple arrays array[0] = string, array[1] = string...)
OK, now I will display the content of two arrays in a webpage.
The first array contain names and the second images URL.
Images and names are already displayed (my problem isn't here).
But now I want to do something else, add a check box near every image, those checkbox r active by default. Ok, now the user can uncheck some inbox;
The final aim, is to get a new array containing only the values of the names and images that had been checked.
I have thought of something simple, crawl the keys (number) of unchecked checkboxes and unset them from my array. But the problem that I didn't know how to deal with the check boxes
To receive inputs as arrays in PHP, you have to set their name using brackets in HTML:
<label><input type="checkbox" name="thename[]" value="" /> The text</label>
Then, when you access $_REQUEST['thename'] you'll get an array. Inspect it to see its format and play with it :)
first of all i recomend having just one array:
$array = array (0 => array('name' => '....', 'url' => '....'))
i think this will make your life much easier.
Also in the HTML you could also send the array key
foreach ($yourArray as $key=>$value) {
...
<INPUT type="checkbox" name="chkArr[<?php echo $key ?>]" value="1" checked/>
then in your form action you itarate the intial array and remove the unchecked ones.
foreach ($yourArray as $key=>$value) {
if (!isset($_POST['chkArr'][$key]) OR $_POST['chkArr'][$key]!='1') {
unset($yourArray[$key]);
}
}
<INPUT type="checkbox" name="chkArr[]" value="$num" checked/>
After the form is submitted, you'll have array $_REQUEST['chkArr'], in which you'll have numbers of the checkbox that are still checked.
To see which have been unchecked use array_diff($listOfAllNums, $chkArr)

Categories