ok, i'm trying to do a quiz...all good by now. but when i'm trying to send the collected data(radio buttons values) through pages i can't get the logic flow. I have the main idea but i can;t put it into practice.
i want to collect all radio values
create an array containing this values
serialize the array
put the serialized array into a hidden input
the problem is that i want to send data on the same page via $_SERVER['PHP_SELF'] and i don;t know when in time to do those things.(cause on "first" page of the quiz i have nothing to receive, then on the "next" page i receive the S_POST['radio_names'] and just after the second page i can get that hidden input). i hope i made myself understood (it's hard even for me to understand what my question is :D )
You could try to use the $_SESSION object instead... For each page of your quiz, store up the results in the $_SESSION array. On the summary page, use this to show your results.
To accomplish this, on the beginning of each page, you could put something like:
<?
session_start();
foreach ($_POST as $name => $resp) {
$_SESSION['responses'][name] = $resp;
}
?>
Then, on the last page, you can loop through all results:
<?
session_start();
foreach ($_SESSION['responses'] as $name => $resp) {
// validate response ($resp) for input ($name)
}
?>
Name your form fields like this:
<input type="radio" name="quiz[page1][question1]" value="something"/>
...
<input type="hidden" name="quizdata" value="<?PHP serialize($quizdata); ?>"/>
Then when you process:
<?PHP
//if hidden field was passed, grab it.
if (! empty($_POST['quizdata'])){
$quizdata = unserialize($_POST['quizdata']);
}
// if $quizdata isn't an array, initialize it.
if (! is_array($quizdata)){
$quizdata = array();
}
// if there's new question data in post, merge it into quizdata
if (! empty($_POST)){
$quizdata = array_merge($quizdata,$_POST['quiz']);
}
//then output your html fields (as seen above)
As another approach, you could add a field to each "page" and track where you are. Then, in the handler at the top of the page, you would know what input is valid:
<?
if (isset($_POST['page'])) {
$last_page = $_POST['page'];
$current_page = $last_page + 1;
process_page_data($last_page);
} else {
$current_page = 1;
}
?>
... later on the page ...
<? display_page_data($current_page); ?>
<input type="hidden" name="page" value="<?= $current_page ?>" />
In this example, process_page_data($page) would handle reading all the input data necessary for the given page number and display_page_data($page) would show the user the valid questions for the given page number.
You could expand this further and create classes to represent pages, but this might give you an idea of where to start. Using this approach allows you to keep all the data handling in the same PHP script, and makes the data available to other functions in the same script.
You want to use a flow such as
if (isset $_POST){
//do the data processing and such
}
else {
/show entry form
}
That's the most straight forward way I know of to stay on the same page and accept for data.
Related
I have a site based on wordpress. I need to allow people to create posts from frontend so I have made a multi-part form which works pretty well. There are three parts of the form and each part of the form is validated before moving to the next part. Data is passed to another page through hidden inputs.
My form template looks somewhat like this ( complete code is pretty massive and irrelevant here, so just showing just the relevant parts ) which I hope is enough to give an idea how the form works.
MULTI-PART FORM WP-TEMPLATE SAMPLE CODE :
<?php
global $wpdb;
$this_page = $_SERVER['REQUEST_URI'];
$page = $_POST['page'];
if ( $page == NULL ) { ?>
<?php include_once('multiparts/form-files/first_part.php'); ?>
<?php } else if ( $page == 1 ) { ?>
<?php include_once('multiparts/validation/validate_first_part.php');
if (isset($_POST['submit-1']) && (!empty($error))) { ?>
<div class="error-head">Cannot continue registration. Error/s highlighted below.</div><br/>
<?php echo $error . '</br>'; ?>
<?php } else {
include_once('multiparts/form-files/second_part.php');
}
?>
<?php
} else if ( $page == 2 ) { ?>
//SO ON AND SO FORTH
<?php
}
?>
Recently, I have a added several checkbox fields in the form with an intention to display values of selected checkboxes, in the created posts. So here is a relevant html form code that I am currently using.
<fieldset class="work-areas">
<label for="areas" class="label">INTERESTED IN :</label></br>
<div class="work-class">
<input type="checkbox" name="workareas[]" value="administration"/>administration</br>
<input type="checkbox" name="workareas[]" value="technical"/>technical</br>
<input type="checkbox" name="workareas[]" value="creative"/>creative</br>
<input type="checkbox" name="workareas[]" value="fieldwork"/>fieldwork</br>
<input type="checkbox" name="workareas[]" value="marketing"/>marketing</br>
</div>
</fieldset>
I insert the values of these checkboxes into the post just like any other custom fields using this code: add_post_meta($pid, 'areas', $workareas, true );. In the processing part it is assigned a meta_key areas. I display it in the single.php with the code below :
<?php $areas = get_post_meta($post->ID, 'areas', true); ?>
<?php if (is_array($areas)) : ?>
<h4>INTERESTED AREAS OF WORK:</h4>
<?php if (is_array($areas)) {
foreach($areas as $area) {
echo '<li>'.$area.'</li>';
}
}
?>
<?php endif;?>
ISSUE: All this works well when the above given html form code for checkboxes is in the last/third part of the form. But it does work when the same checkbox fields is in the second part of the form. I guess it simply does not pass the array values of the selected checkboxes to the third part. Print_r shows an empty array and obviously does not display anything in the single.php too. Although I understand that the trouble is just the array of selected checkbox values, NOT being carried to the third part properly, I need help as I am noob to all this.
So the bottomline question is how do I save the array of the selected
checkboxes' values in the second part and carry it to the third part
and finally assign it to a variable which will hold the array values.
That which can be displayed in post using the code above.
THINGS TRIED : I have looked into this thread here and I am confused where I will insert my checkbox fields and not even sure it applies to my situation. I have been able to pass other text input values from one part to another part of the from using something like this :
<input type="hidden" name="eligible" value="<?php echo $eligible;?>" />
So, I tried using name="workareas[]" but did not work. I am doing print_r() for everything I am trying and till now have only been getting empty array. I am still going through tons of other threads looking for possible hints. In the meanwhile if you can help, that will be great. Thanks in advance.
UPDATE : Solved, please check the answer.
Not a WP user but your checkboxes are named "workareas" but you seem to refer to them as "areas" everywhere else.
Thanks for the suggestions in the comments but I have found a graceful and robust solution in my opinion, that is using sessions. I followed the basic idea from here which actually deals with a multipart form with sessions. Now I have the following code in my third/last part of the form, at the very beginning of the document. At this time please remember that the html checkbox fields as illustrated above in the question are in the second part.
<?php
session_start();
$_SESSION['workareas'] = $_POST['workareas'];
$result=$_POST['workareas'];
?>
The code is that is repeated during the validation of the third part is the same but this way the variable $result is still holding the values of the array of the selected checkboxes from the second part of the form.
session_start();
$result=$_SESSION['workareas'];
You can do a print_r($result) at this point and check. Furthermore, if you want to insert these array values to post in order for them to show up in the post just assign meta_key eg. areas to $result and use the code below to add it as a custom field :
add_post_meta($pid, 'areas', $result, true);
In the single.php you can use the code below to pull values from the array and show. Do not avoid if(is_array) statement else wordpress might throw an error warning: invalid arguments supplied foreach(). Goodluck.
<?php $areas = get_post_meta($post->ID, 'areas', true); ?>
<?php if (is_array($areas)) : ?>
<h4>INTERESTED AREAS OF WORK:</h4>
<?php if (is_array($areas)) {
foreach($areas as $area) {
echo '<li>'.$area.'</li>';
}
}
?>
<?php endif;?>
Is there any way to know if the page was refreshed or data was posted data on the same page?
To be little more specific:
I have to post data on the same page.
This affects the where condition of the query.
If the page was refreshed, then the where condition must be 1.
Otherwise, where condition contains some id to get specific data from
the table.
Your best bet is to use PHP sessions, along with your submitted data in $_POST. Let's presume for this example you have the following form:
<form action="this_page.php" method="post">
<input type="text" name="important-info" />
<input type="submit" value="Submit" />
</form>
Then elsewhere in the same page is the PHP code:
<?php
// example code
session_start();
if (!isset($_SESSION['previousVisitor']) && isset($_POST['important-info'])) {
// this is a new visitor who has submitted the form
$_SESSION['previousVisitor'] = true;
// where is based on $_POST['important-info']
} else () {
// where is 1
}
// close the session after you do what you need - this stops large pages causing hang
session_destroy();
Please note that they can clear this session variable by deleting their cookies.
on the top of the page just include
if(isset($_POST['name']) && $_POST['name']!=''){
//your code goes here
}
I suggest you to check request
//Here goes the code
session_start();
$counter = 0;
$counter = (isset($_SESSION['param'])) ? $counter++ : 0;
if($counter == 0)
echo "data GET or POST";
else
echo "refreshed";
** If you want only POST param, use $_POST instead of $_REQUEST
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.
i have 3 pages
Page1.php,page2.php,page3.php
In page1.php, i have some hidden values, for example 'name'
After the submission of page1.php, it will go to page2.
Then after some process in page2.php, it should need to automatically submit to page3.php(where page3.php is in another sever)
Finally,when i print the $_POST variables in page3.php, i need to get the variable 'name'
you could stick it in the session
<?php
session_start();
if (!isset($_SESSION['count'])) {
$_SESSION['count'] = 0;
} else {
$_SESSION['count']++;
}
?>
or you could pass them in hidden vars on page2.php if it has a form...
You will want to look into sessions.
If you need them in POST, try this:
$display = "";
$saveFields = array('one', 'two'); // whitelist of fields to add to the form hidden
foreach ($_POST as $key => $val) {
if (!empty($val) && in_array($key, $saveFields))
$display .= '<input type="hidden" name="'.$key.'" value="'.$val.'" />';
}
echo $display;
Should get you where you want to go. The whitelist just ensure's that random stuff is not injected that does not need to be.
(1) Option is to add hidden input on page2 too.
(2) Option is to set the value from page1's name into session and use it on page3
There are several solutions:
PHP sessions
cookies
passing arguments as GET/POST parameters
storing data in database
In simple cases passing arguments as GET parameter page2.php?name=... or using hidden form field is the best solution
This seems straightforward to me, page one has a hidden value called name. Page 2 should retrieve the post $_POST['name'] and print it on page 2 as a hidden field. Once you post it to Page 3 you can retrieve it the same way $_POST['name'].
Realistically if the data is exactly the same and is being carried all the way to page 3, why do you even need it? Can you not just declare it on page 3?
Okay, the way I read this is that on your first page you have a UI with a form. The form is then submitted for processing to page 2. After processing is done, you want to redirect, if you will, the user to another site (or server, doesn't necessarily have to make a difference).
If I got that right, here is what you should do; instead of using the header(); function (php), print an empty page with a hidden form with all of the details you want to send over and use javascript to emulate the user 'submitting' the form.
< div style="display: none;">
< form action="https://mywebpage.com/myscript.php" method=POST>
< input type=hidden name="key_1" value="value_1">
< input type=hidden name="key_2" value="value_2">
< input type=hidden name="key_3" value="value_3">
< input type=submit id="formButton" style="visibility: hidden; ">
< script language="javascript">
document.getElementById("formButton").click()
< /form>
< /div>
I am having problems figuring out how to retain users data when the validation fails. I am somewhat new to PHP so I might be making some huge mistakes in my logic.
Currently if the validation fails all the fields are wiped clean and $_Post data is also gone.
Here is some code assuming the user enters an invalid email I want the Name field to be retained. This code is not working.
<?php
if($_POST['doSubmit'] == 'Submit') {
$usr_name = $data['Name'];
$usr_email = $data['Email'];
if (isEmail($usr_email)==FALSE){
$err = "Email is invalid.");
header("Location: index.php?msg=$err");
exit();
}
//do whatever with data
}
if (isset($_GET['msg'])) {
$msg = mysql_real_escape_string($_GET['msg']);
echo "<div class=\"msg\">$msg</div><hr />";
}
if (isset ($_POST['Name'])){
$reusername = $_POST['Name'];}
else{$reusername = "NOTHING";}//to test
?>
<form action="index.php" method="post" >
<input name="UserName" type="text" size="30" value="<?echo $reusername;?>">
<input name="Email" type="text" size="30">
<input name="doSubmit" type="submit" value="submit">
</form>
}
You can use AJAX to submit your form data to your PHP script and have it return JSON data that specifies whether the validation was successful or not. That way, your fields won't be wiped clean.
Another way is to send back the recorded parameters to the posting page, and in the posting page, populate the fields using PHP.
However, I think the first solution is better.
UPDATE
The edit makes your code clearer and so I noticed something. Your input field is called UserName in the HTML, but you are referring to Name in PHP. That's probably why it's not working. Is your field always being filled with the value NOTHING? Make sure the name of the input field and the subscript you are using in $_POST are the same.
Also, there's no need to redirect to another page (using header) if you have an error. Maintain an $errors array or variable to print error messages in the same page. But like I mentioned before, it's probably better to use the JSON approach since then you can separate your view layer (the html) from the PHP (controller layer). So you'd put your HTML in one file, and your PHP in another file.
EDIT:
Vivin had commented that my assumption regarding the header was incorrect and he was right in that. Further more it looks like what the OP is doing is essentially what i layed out below albeit in a less structured fashion. Further Vivin - caught what is likely the actual problem here - the html name and the array key $_POST do not match.
Its wiped clean because you are using header to redirect to another page. Typicaly you would have a single page that validates the data and if ok does something with it and returns a success view of some sort, or that returns an error view directly showing the form again. By using header youre actually redirecting the browser to another page (ie. starting up an entirely new request).
For example:
// myform.php
if(strtolower($_SERVER['REQUEST_METHOD']) == 'get')
{
ob_start();
include('form.inc.php'); // we load the actual view - the html/php file
$content = ob_get_clean();
print $content; // we print the contents of the view to the browser
exit;
}
elseif(strtolower($_SERVER['REQUEST_METHOD']) == 'post')
{
$form = santize($_POST); // clean up the input... htmlentities, date format filters, etc..
if($data = is_valid($form))
{
process_data($data); // this would insert it in the db, or email it, etc..
}
else
{
$errors = get_errors(); // this would get our error messages associated with each form field indexed by the same key as $form
ob_start();
include('form.inc.php'); // we load the actual view - the html/php file
$content = ob_get_clean();
print $content; // we print the contents of the view to the browser
exit;
}
}
so this assumes that your form.inc.php always has the output of error messages coded into it - it just doesnt display them. So in this file you might see something like:
<fieldset>
<label for="item_1">
<?php echo isset($error['item_1']) ? $error['item_1'] : null; ?>
Item 1: <input id="item_1" value="<?php echo $form['item_1'] ?>" />
</label>
</fieldset>
Could do something similar to if failed then value=$_POST['value']
But vivin's answer is best. I don't know much about AJAX and wouldn't be able to manage that.
Ok, firstly header("Location: index.php?msg=$err"); is not really required. It's best practice not to redirect like this on error, but display errors on the same page. Also, redirecting like this means you lose all of the post data in the form so you can never print it back into the inputs.
What you need to do is this:
<input name="Email" type="text" size="30" value="<?php print (!$err && $usr_email ? htmlentities($usr_email, ENT_QUOTES) : '') ?>">
Here I'm checking whether any errors exist, then whether the $usr_email variable is set. If both these conditions are matched the post data is printed in the value attribute of the field.
The reason I'm using the function htmlentities() is because otherwise a user can inject malicious code into the page.
You appear to be processing the post on the same page as your form. This is an OK way to do things and it means you're nearly there. All you have to do is redirect if your validation is successful but not if it fails. Like this
<?php
if( isset( $_POST['number'] ) ) {
$number = $_POST['number'];
// validate
if( $number < 10 ) {
// process it and then;
header('Location: success_page.php');
} else {
$err = 'Your number is too big';
}
} else {
$number = '';
$err = '';
}
?>
<form method="POST">
Enter a number less than 10<br/>
<?php echo $err ?><br/>
<input name="number" value="<?php echo $number ?>"><br/>
<input type="submit">
</form>