1

Further to my previous question, here's what I decided to implement; it may not be pure P-R-G, but it seems ok. Care to comment?

The form.php has an action; let's call it validate.php.

validate.php is never seen by the user; if validates all $_GET and, if valid writes it to database and generates the HTML of a confirmation page / if not valid, it generates the HTML of an error page explaining what is wrong.

Whichever HTML is generated get stored in a $_SESSION variable and then validate.php does a header('Location: <as appropriate>);

Finally a page called submitted.php of invalid_input.php (in case the user reads the URL) consists only of echo $_SESSION['form_html'];

That seems to me like is proff against both page reload and back button problems.

Or did I goof by trying to reinvent the wheel?

Community
  • 1
  • 1
Mawg says reinstate Monica
  • 38,334
  • 103
  • 306
  • 551

2 Answers2

1

As long as you use a php redirect at the end of your validate you cannot reload or back button into the validate.php

austinbv
  • 9,297
  • 6
  • 50
  • 82
1

Firstly, you're better off storing the form data, which means you can perform the validation again. It will also be less html. The problem with the method you're employing now is that it doesn't protect against multiple tabs, since $_SESSION is universal to a browser session.

One way I've used to prevent against duplicate submission (without PRG) is to generate a unique id for every page load (where a form is involved). When I generate that unique id, I add it to a $_SESSION['form_unique_ids'] array, and I include it as a hidden field in every form I generate. Then before I take action on a form submission, I check to see if that unique id is in the session. If it is, this is the first time that form has been submitted, and I remove it from the session. That way if I try to resubmit that page, I will know because that id is not in the session not to process the results.

This could be extended so that instead of storing a single id, you use the id as the key in the array, and let the value be the result of the transaction. Then:

  1. If there are errors, you store the $_POST data as well. Then, redirect to original_form.php?id=unique_id and display the validation results. You can either store them or recalculate them there.
  2. If there is success, store the success message and redirect to success_page.php?id=unique_id. Display the success message prominently there. If you like, you can remove it from the page.

You have the option of removing the session data when you display it, but that would mean if they refreshed the edit page they'd lose the validation messages and saved form data. I'd rather find a way to get rid of data that is old enough that they're not likely to need it anymore.

Anyway, some of those ideas might be useful. Then again, maybe it's way too much effort for the problem. Your call :)

theazureshadow
  • 9,499
  • 5
  • 33
  • 48
  • +1 thanks, I like your suggestion (although I'm not sure what you mean by storing the data (where? d/b or $_SESSION?) to validate it again (why again? if it's valid once and not changed ... what did I miss?) Thanks, shadow (say, who was that masked man?) – Mawg says reinstate Monica Nov 12 '10 at 04:04
  • 1
    I was thinking `$_SESSION`, myself. Storing the data takes less room (since storing the html includes both the data and the printed form around it), and it is more direct to print the form on the page where it's going to displayed rather than somewhere else. If you don't want to re-do the validation, just store the validation errors along with the `$_POST` data. Ideally you will be able to use the same printing code as you originally used to print the form (e.g. if it's an edit form). – theazureshadow Nov 12 '10 at 04:08
  • +1 but why would I ant to store the data? Why not validate it one single time and write it to the d/b? – Mawg says reinstate Monica Nov 12 '10 at 06:40
  • 1
    You should only store the data if there are errors, in which case you wouldn't want to write it to the db anyway. I think if there are errors, then storing the validation errors (so you only have to do it once) in the session is probably better than validating it a second time. You will still need to store the `$_POST` data in that situation, so that you can fill in the form on the error/edit page you redirect to. – theazureshadow Nov 12 '10 at 06:46
  • +1 ah, gotcha. Yes, I move the $_POST to $_SESSION id there are errors, then route back to the input form and use that data again, prompting to fix the invalid input – Mawg says reinstate Monica Nov 12 '10 at 07:15