Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

PHP Form Fields on Back

Posted on 2014-09-30
28
Medium Priority
?
149 Views
Last Modified: 2015-01-24
I have a form on one page and when I submit the form and then go back, I get the following message in Firefox:
Document Expired

This document is no longer available.

The requested document is not available in Firefox's cache.

    As a security precaution, Firefox does not automatically re-request sensitive documents.
    Click Try Again to re-request the document from the website.
Is there a way to have this not happen???
0
Comment
Question by:rgranlund
  • 9
  • 8
  • 5
  • +2
27 Comments
 
LVL 58

Expert Comment

by:Gary
ID: 40353218
Was something posted to this page - browsers will not reload a page where it contains posted data or the page is set to no cache.
0
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 40353221
What is the URL of the page?  Have you tried making this page with a GET-method request?  For that matter, is it an idempotent request that is susceptible to using GET?
0
 
LVL 7

Author Comment

by:rgranlund
ID: 40353247
Yes, there is POSTed information.
http://spokeinsurance.com/product/bike-insurance/
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 58

Expert Comment

by:Gary
ID: 40353263
Then that is the reason, automatically reloading a page with POSTed data could lead to problems and that is why browsers will not automatically reload it - you have do the reload yourself.
0
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 40353416
But does it have to be POSTed?  This is an important concept in computer science.
http://en.wikipedia.org/wiki/Idempotence

If the request does not change the state of the server beyond the initial action of the request it is idempotent and can be made with GET.
0
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 40353471
You may also want to address some of these issues.  Without valid markup it's very hard to get CSS formatting to work correctly, and though I cannot verify it, I've heard that SEO is penalized when you have invalid markup.
http://validator.w3.org/check?uri=http%3A%2F%2Fspokeinsurance.com%2Fproduct%2Fbike-insurance%2F&charset=%28detect+automatically%29&doctype=Inline&group=0
0
 
LVL 35

Accepted Solution

by:
gr8gonzo earned 2000 total points
ID: 40353561
As others have said, this is due to the POST data. It makes a lot of sense, though. Web browsers really need a way to avoid re-sending the same data. Imagine if your form automatically sent a email message upon submission (or charged a credit card). If someone hit the back button and it just re-submitted and showed the results page again, you'd have bigger problems (duplicate emails or duplicate credit card charges, etc).

So browsers do not automatically re-POST the data to the submission page in order to avoid this kind of situation. However, since they don't re-POST the data, they cannot tell what the page looked like, so you get that message / prompt.

Now, one common way around this is to post your form via AJAX to some AJAX controller (jQuery makes this easy to do). Let the AJAX controller return a URL for the "thank you" page, and then redirect your user to that URL with Javascript.

This way, the POST is sent in such a way that the submission processing page never gets into the browser's history. So when someone uses their back button, they'll go to the thank you page first, and hitting the back button again will take them back to the form.
0
 
LVL 35

Expert Comment

by:gr8gonzo
ID: 40353565
You can also simulate the same type of thing with an iframe instead of AJAX (just change the target of the <form> to point to a hidden iframe), and have the iframe push a Javascript redirection command back to its parent window when the processing is done.
0
 
LVL 60

Expert Comment

by:Julian Hansen
ID: 40353625
It depends on how you are going back. If by clicking the browser back button then the behaviour is by design. If you want to provide a Back button then you can do so by pointing the button to the URL of the page and then handling the button click to re-render the form as needed pulling the form data from whatever server side storage you are using.

I am assuming that if you implemented your own back button you probably did something like window.history.back(). If you implemented your back button as

<a href="urltoformpage.php">Back</a>

You won't have the problem - you would just need to implement a check to see if this is a back request and populate form accordingly.
0
 
LVL 7

Author Comment

by:rgranlund
ID: 40355742
@juliaH Can you explain this further:
"You won't have the problem - you would just need to implement a check to see if this is a back request and populate form accordingly."
0
 
LVL 60

Expert Comment

by:Julian Hansen
ID: 40355806
What I meant is if you implement your back button (on the form) as a url pointing back to the page you want to go to then you will no experience the Document expired issue.

But you will need to modify your script to fill in whatever field values where filled in on the form.

For instance - a form that asks for name and surname
<?php
   // Assumes that posts from this form saved data to the SESSION
   // You would need to modify for however you are storing the data

   $firstname = empty($_SESSION['firstname']) ? '' : $_SESSION['firstname'];
   $surname = empty($_SESSION['surname']) ? '' : $_SESSION['surname'];
?>
<form ...>
   Name <input type="text" name="firstname" value="<?php echo $firstname;?>" /><br/>
   SurnName <input type="text" name="surname" value="<?php echo $surname;?>" /><br/>
   ...
</form>

Open in new window

You would modify the above code to fetch the relevant values from where ever you are storing them on the server (if not the SESSION as in the above example).

Basically what the above code is trying to demonstrate is that you can link back to your original form but you would need to write script to put the form values back in.
0
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 40356151
No matter what you implement in the HTML form, you can't really prevent the client from hitting the browser "back" button.  Still waiting to hear if the request is idempotent, in which case you can use GET and not be bothered by the issues associated with duplicate POST requests... While you're figuring that out, here is an example of a way to receive and validate values.  It seems to work OK in most browsers.
http://iconoun.com/demo/form_highlight_errors.php

<?php // demo/form_highlight_errors.php
error_reporting(E_ALL);

/**
 * DEMONSTRATE HOW TO HIGHLIGHT ERRORS IN FORM INPUT, AND REMEMBER VALID INPUTS
 * CLIENT IS ASKED TO PUT IN A VALUE
 * IF THE VALUE FAILS OUR TEST WE SHOW AN ERROR MESSAGE
 * WE PUT A MARKER NEXT TO THE INPUT CONTROL ON THE FORM
 * WE TURN THE FORM BORDER RED
 * SEE http://www.w3schools.com/CSS/pr_class_visibility.asp
 */


// THESE STYLE ELEMENTS ARE SET FOR THE SCRIPT INITIALIZATION
$error_abc = $error_xyz = $error_any = 'hidden';
$boxer_abc = $boxer_xyz              = 'black';


// CAPTURE AND NORMALIZE THE POST VARIABLES - ADD YOUR OWN SANITY CHECKS HERE
$abc = (isset($_POST["abc"])) ? trim(strtoupper($_POST["abc"])) : NULL;
$xyz = (isset($_POST["xyz"])) ? trim(strtoupper($_POST["xyz"])) : NULL;


// IF ANYTHING WAS POSTED, VALIDATE IT
if (!empty($_POST))
{
    // VALIDATE THE 'abc' FIELD
    if ($abc != 'ABC')
    {
        // VALIDATION FAILED
        $error_abc = $error_any = 'visible';
        $boxer_abc = 'red';

        // BECAUSE THIS FAILED VALIDATION, REMOVE IT FROM THE FORM
        $abc       = NULL;
    }

    // VALIDATE THE 'xyz' FIELD
    if ($xyz != 'XYZ')
    {
        // VALIDATION FAILED
        $error_xyz = $error_any = 'visible';
        $boxer_xyz = 'red';

        // BECAUSE THIS FAILED VALIDATION, REMOVE IT FROM THE FORM
        $xyz       = NULL;
    }

    // DO WE HAVE INPUT FREE FROM ANY ERRORS?
    if ($error_any != 'visible')
    {
        echo "CONGRATULATIONS";
        die();
    }

    // OTHERWISE... OOPS - WE HAVE ERRORS AND MUST SHOW THE FORM AGAIN
}

// IF NOTHING WAS POSTED, OR IF THERE ARE ERRORS, WE NEED NEW CLIENT INPUT
$form = <<<ENDFORM
<style type="text/css" media="all">
.error_any { visibility:$error_any; }
.error_abc { visibility:$error_abc; }
.error_xyz { visibility:$error_xyz; }
</style>
<pre>
<form method="post">
<span class="error_any">PLEASE CORRECT THE FOLLOWING ERRORS</span>
<span class="error_abc">YOU MUST ENTER 'abc' IN THIS FIELD</span>
PLEASE ENTER "ABC" HERE: <input style="border-color:$boxer_abc;" name="abc" value="$abc" />
<span class="error_xyz">YOU MUST ENTER 'xyz' IN THIS FIELD</span>
PLEASE ENTER "XYZ" HERE: <input style="border-color:$boxer_xyz;" name="xyz" value="$xyz" />
<input type="submit" />
</form>
ENDFORM;

// WRITE THE FORM WITH THE APPROPRIATE CSS STYLES ON THE ERROR MESSAGE FIELDS
echo $form;

Open in new window

0
 
LVL 7

Author Comment

by:rgranlund
ID: 40360165
@Both Julian and Ray.  I understand where both of you are going.  However, what if you have an input or select field that is dynamically populated?
<select name="addon-28-bicycle-info[type-of-material]" id="addon-28-bicycle-info[type-of-material]" onchange="findSum(); findMed()" required="">

						<option value="">Select Material Type</option>

			<?php

				foreach ($mat as $mt)	{

					$um = $mt->unit_material;	

					echo '<option value="'.$um.'"';

					if(isset($_POST['addon-28-bicycle-info[type-of-material']) && $_POST['addon-28-bicycle-info[type-of-material'] == $um) { echo 'Selected'; }

					echo '>'.$um.'</option>';

				}

			?>

						</select>

Open in new window

How would I get:
<?php $type = empty($_SESSION['addon-28-bicycle-info[type-of-material]']) ? '' : $_SESSION['addon-28-bicycle-info[type-of-material]']; ?>

OR
<?php $type = (isset($_POST['addon-28-bicycle-info[type-of-material]'] )) ? trim(strtoupper($_POST['addon-28-bicycle-info[type-of-material]')) : NULL; ?>
0
 
LVL 60

Expert Comment

by:Julian Hansen
ID: 40360443
Not sure what you mean by "How would I get"

If the form populates dynamically based on SESSION values - when you return to the form those SESSION variables should still be set should they not? Not sure I understand the problem
0
 
LVL 7

Author Comment

by:rgranlund
ID: 40360447
Does this line:
 $type = empty($_SESSION['addon-28-bicycle-info[type-of-material]']) ? '' : $_SESSION['addon-28-bicycle-info[type-of-material]'];

Does that need to be set in the head or can it be in the body of the page?
0
 
LVL 60

Expert Comment

by:Julian Hansen
ID: 40360515
The question has no meaning.

PHP runs before the page is interpreted - it does not run anywhere in the page.

Think of it as PHP writing the page just before the browser loads and renders it.

The line in question is part of an output string so by this stage the script should have output the head section but not sure why that is relevant to this discussion.
0
 
LVL 7

Author Comment

by:rgranlund
ID: 40360562
OK, still, from above: However, what if you have an input or select field that is dynamically populated?

How do I handle select fields that are dynamically populated?
0
 
LVL 60

Expert Comment

by:Julian Hansen
ID: 40360605
You populate them as you would normally - after the form is submitted the value from that select is saved somewhere right?

When you come back to the page simply check in the loop that creates the option if the option value matches the saved value and output the selected attribute if it is - which is what your code appears to be doing anyway which is why I am confused.
0
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 40360610
handle select fields that are dynamically populated?
The same way you would handle any other PHP variables.  When you generate the HTML document, you refer to the variables that define the conditions you want in your <select> options.  You generate the "selected" attribute for those that you want to pre-select for the client.  Checkboxes and radio buttons are different.
0
 
LVL 58

Expert Comment

by:Gary
ID: 40360614
This question has gone way off track from that originally asked - the answer to which is - it's by design and cannot be changed when the page contains posted data, the only  solution as Ray has said is use GET instead
0
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 40360761
@Gary: Yes, we're still waiting to find out if the request is idempotent!
0
 
LVL 7

Author Comment

by:rgranlund
ID: 40382410
I have gone dark on this question but will be coming back to it shortly.
0
 
LVL 7

Author Comment

by:rgranlund
ID: 40404202
OK, @Ray , Yes the operation is idempotent.  It can be run many times without harm.
0
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 40404254
That's an indicator that you would want to use a GET-method request instead of POST.  Try it with GET and let us know if that solves the problem.
0
 
LVL 7

Author Comment

by:rgranlund
ID: 40406816
@Ray, I'm using wordpress / Woocommerce and I am Posting to the checkout page, from a product page.  Are you suggesting that I "Post" the Form to the checkout page with "GET"?
0
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 40406853
No, of course not.  That is why I asked if the request was idempotent.  If it's adding products to a shopping cart it is changing the state of the data model on the server.  If you run the request and add a product, then you run the request again and add another product, it is not an idempotent request.
http://en.wikipedia.org/wiki/Idempotence
0
 
LVL 7

Author Comment

by:rgranlund
ID: 40407191
The Wordpress Woocommerce Subscription will not allow you to add more than on item to the cart.  Once there is something there it won't add anything else.
0

Featured Post

Ask an Anonymous Question!

Don't feel intimidated by what you don't know. Ask your question anonymously. It's easy! Learn more and upgrade.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Author Note: Since this E-E article was originally written, years ago, formal testing has come into common use in the world of PHP.  PHPUnit (http://en.wikipedia.org/wiki/PHPUnit) and similar technologies have enjoyed wide adoption, making it possib…
It’s a season to be thankful, and we’re thankful for users like you who engage on site, solve technology problems, and network with others in the industry. What tech are we most thankful for? Keep reading.
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …
Suggested Courses

876 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question