Solved

PHP Form Fields on Back

Posted on 2014-09-30
28
133 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
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 108

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
 
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 108

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 108

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 34

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 34

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 51

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 51

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 108

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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 51

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 51

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 51

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 108

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 108

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 108

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 108

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

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Generating table dynamically is the most common issue faced by php developers.... So it seems there is a need of an article that explains the basic concept of generating tables dynamically. It just requires a basic knowledge of html and little maths…
Since pre-biblical times, humans have sought ways to keep secrets, and share the secrets selectively.  This article explores the ways PHP can be used to hide and encrypt information.
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn how to count occurrences of each item in an array.

758 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

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now