Solved

PHP Form Fields on Back

Posted on 2014-09-30
28
144 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 8
  • 5
  • +2
28 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 110

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
Technology Partners: 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 110

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 110

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 500 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 57

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 57

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 110

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 57

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 57

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 57

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 110

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 110

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 110

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 110

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

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
deprecated mysql extensions 1 55
php hashing methods 3 50
What is key combo for a b with a forward slash through it? 12 66
Php variable to be sent back 3 35
Foreword (July, 2015) Since I first wrote this article, years ago, a great many more people have begun using the internet.  They are coming online from every part of the globe, learning, reading, shopping and spending money at an ever-increasing ra…
Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…

710 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