How to prevent form resubmission when page is refreshed (F5 / CTRL+R)

397,291

Solution 1

Use the Post/Redirect/Get pattern. http://en.wikipedia.org/wiki/Post/Redirect/Get

With my website, I will store a message in a cookie or session, redirect after the post, read the cookie/session, and then clear the value of that session or cookie variable.

Solution 2

I would also like to point out that you can use a javascript approach, window.history.replaceState to prevent a resubmit on refresh and back button.

<script>
    if ( window.history.replaceState ) {
        window.history.replaceState( null, null, window.location.href );
    }
</script>

Proof of concept here: https://dtbaker.net/files/prevent-post-resubmit.php (Link no longer works)

I would still recommend a Post/Redirect/Get approach, but this is a novel JS solution.

Solution 3

You can prevent form resubmission via a session variable.

First you have to set rand() in a textbox and $_SESSION['rand'] on the form page:

<form action="" method="post">
  <?php
   $rand=rand();
   $_SESSION['rand']=$rand;
  ?>
 <input type="hidden" value="<?php echo $rand; ?>" name="randcheck" />
   Your Form's Other Field 
 <input type="submit" name="submitbtn" value="submit" />
</form>

After that check $_SESSION['rand'] with textbox $_POST['randcheck'] value like this:

if(isset($_POST['submitbtn']) && $_POST['randcheck']==$_SESSION['rand'])
{
    // Your code here
}

Make sure you start the session on every file you are using it with session_start()

Solution 4

This method works for me well, and I think this is the simplest one to do this job.

The general idea is to redirect the user to some other pages after the form submission, which would stop the form resubmission on page refresh. Still, if you need to hold the user on the same page after the form is submitted, you can do it in multiple ways, but here I am describing the JavaScript method.


JavaScript Method

This method is quite easy and blocks the pop up asking for form resubmission on refresh once the form is submitted. Just place this line of JavaScript code at the footer of your file and see the "magic".

<script>
if ( window.history.replaceState ) {
  window.history.replaceState( null, null, window.location.href );
}
</script>

Solution 5

I use this javascript line to block the pop up asking for form resubmission on refresh once the form is submitted.

if ( window.history.replaceState ) {
  window.history.replaceState( null, null, window.location.href );
}

Just place this line at the footer of your file and see the magic

Share:
397,291

Related videos on Youtube

user701510
Author by

user701510

Updated on December 15, 2021

Comments

  • user701510
    user701510 over 2 years

    I have a simple form that submits text to my SQL table. The problem is that after the user submits the text, they can refresh the page and the data gets submitted again without filling the form again. I could redirect the user to another page after the text is submitted, but I want users to stay on the same page.

    I remember reading something about giving each user a unique session id and comparing it with another value which solved the problem I am having but I forgot where it is.

    • Marcel
      Marcel almost 13 years
    • Adam
      Adam almost 8 years
      Why do you not want to redirect user to another page?
    • Eugen Konkov
      Eugen Konkov over 6 years
      @Adam: Because this is excess to do another request to the server which in turn will fetch some data from DB again. But this is resource wasting because we already fetch all required data while processing POST request
    • Adam
      Adam over 6 years
      @EugenKonkov in the PRG pattern, you would just redirect to a page that shows a success message. No further fetching from DB needed.
    • Eugen Konkov
      Eugen Konkov over 6 years
      @Adam: You also may display the whole record which is created by POSTing data. In this case you need to SELECT it from DB. For example when you create the invoice you are redirected to /invoices/53 which display the whole invoice instead of just 'success'
    • ICW
      ICW over 4 years
      @Marcel OP wants to stay on the same page. Redirect is not an option as it is literally the act of leaving the page.
    • Ricky Levi
      Ricky Levi about 2 years
      I used your comments and made the redirect with the same URL as the form uses. since this is a POST request there's nothing in the query string, therefor i use Location: https://domain/same_script_path ... - and i stay in the same page just w/o the form data
  • jacoz
    jacoz over 11 years
    Take a look at en.wikipedia.org/wiki/Post/Redirect/Get ! This is the right approach
  • aLearner
    aLearner almost 11 years
    Thanks for sharing but this doesn't seem to work. Refreshing the page does indeed resubmit the form for me. Perhaps I'm missing something?
  • Moob
    Moob almost 11 years
    Refreshing the page will resubmit everything but we choose only to process the submission data if its different from the data sent last time (which we store in the session var 'messageIdent'). Are you processing your form submission within the 'if messageIdents are different' clause (ie where 'do_your_thang()' is)?
  • aLearner
    aLearner almost 11 years
    Thanks for your reply. I ended up just implementing the Post / Redirect / Get pattern, so, I don't remember now what exactly was tripping me up. Thanks again for circling back, though.
  • Gavin
    Gavin almost 10 years
    Unsetting $_POST doesn't affect form resubmission at all, at least not in Chrome.
  • Fernando Silva
    Fernando Silva over 9 years
    I actually just wrote something similar to this, but didn't go through the trouble to create a password, I just enumerated my forms (eg: steps 1-5), so if they're equal we're cool to move on, else don't save to db or send emails. But let the user land wherever it takes him.
  • JWP
    JWP over 9 years
    This makes chrome unusable for development where business is requiring only a post!
  • Nick Rice
    Nick Rice over 9 years
    This is just repeating the same answer that someone else gave years earlier. (In fact two others!)
  • TheSatinKnight
    TheSatinKnight over 8 years
    This method is not meant to block resubmission ... but to Detect resubmission so you can alter your code to not "do" whatever you would do if this were a fresh submission. In other words: With this method you can detect the "original" submission and place your data. If it's NOT original, don't place your data. Either show a "dupe attempt" warning or perhaps show a "confirmation" instead.
  • Julio Popócatl
    Julio Popócatl over 8 years
    I think this is a better solution than reload the page, since i show a message when post succesfull and reloading the page will delete the message. this works grate for me, you also can use a uniqid
  • Adam
    Adam almost 8 years
    If you use the PRG pattern, then you actually leave the page right? Wasn't the question how to make things work when not redirecting?
  • Sandhu
    Sandhu over 7 years
    It will not work. When user go to back page it perform the setting up of POST variables once again.
  • Nikolay Bronskiy
    Nikolay Bronskiy over 6 years
    we can use <input type="hidden" name="randcheck" id="randcheck" value="<?php echo microtime(); ?>" /> instead
  • Savoo
    Savoo over 6 years
    Yes we can use microtime() as well as time() also instead of rand() , whatever function or variable that gives different value we can use it. BUT make sure that you set that value to SESSION variable. here SESSION is must to check with randcheck field and to prevent from resubmit form.
  • wkille
    wkille about 6 years
    For this to work you must have started a session by adding session_start(); at the beginning of the file. w3schools.com/php/php_sessions.asp says Note: The session_start() function must be the very first thing in your document. Before any HTML tags.
  • Csongor Halmai
    Csongor Halmai over 5 years
    Unfortunately, with PRG, when the user opens more tabs from the same session then they can send Content#1 from the first tab and the Content #2 from the second tab. Now the session stores only the most recently sent content so Content #1 can be sent again from the first tab and Content #2 again from the second one, and so on. So, you should store the hash of not just the most recent conent but that of all of them while the session lasts. Or, you can delete the stored hashes after a tolerance period or if there are too many of them.
  • Péter Vértényi
    Péter Vértényi about 5 years
    Would be nice a version of this that can't be disabled from the client side, but it is short, easy, fast... and do what it needs to do. Keeps the history so the user can navigate back, without resending post.
  • Gufran Hasan
    Gufran Hasan about 5 years
    Thanks, @dtbaker, it's awesome :)
  • donutguy640
    donutguy640 about 5 years
    It seems to me that if you redirect to the same page, then $_POST is cleared. As I understand it, that was the desired effect. That was MY desired effect, anyway. I think the answer would be better if it made that explicit, though.
  • tess hsu
    tess hsu almost 5 years
    Tks, this is work perfect for me, it just had to create 404 page avoid user missunderstanding
  • user4906240
    user4906240 almost 5 years
    Simply Amazing. Thankyou
  • Maurice
    Maurice over 4 years
    Works well, my only recommendation is to make sure you enable strict error testing so you're catching errors locally while developing, otherwise they can go unnoticed.
  • ICW
    ICW over 4 years
    Doesn't answer the question. Not sure why it's the accepted answer.
  • ICW
    ICW over 4 years
    It makes no sense to say "You should use PRG" to answer this question when it is literally impossible to use PRG and also stay on the same page.
  • Vo Thanh Tung
    Vo Thanh Tung over 4 years
    it doesn't work in safari, it changed href but still keep the data with post request to submit
  • denoise
    denoise over 4 years
    shouldn't the session variable be cleared after checking if the session and post vars match?
  • Jassar
    Jassar over 4 years
    This worked for me thank you! Why do you recommend the PRG approach?
  • Hmerman6006
    Hmerman6006 over 4 years
    @denoise I believe the idea by @Savoo is that after $_POST of the form data the same page reloads re-setting the session and post variables. Also creation of variables should takes place after checking if the variables match. Therefore unset is not needed.
  • garry man
    garry man about 4 years
    Another solution is to add a location header in your backend POST handler, which will automatically redirect to your POST callee page. For example if you're on PHP you could do header('location: yourpage.php')
  • megyptm
    megyptm about 4 years
    Thanks, it's Amazing, i test its working very well with google chrome
  • Nico Haase
    Nico Haase almost 4 years
    Please add some explanation to your answer such that others can learn from it - where does $everything_fine come from?
  • Nico Haase
    Nico Haase almost 4 years
    Please add some explanation to your answer such that others can learn from it - why is that unset call needed? What would happen if you skipped it?
  • Nico Haase
    Nico Haase almost 4 years
    If you duplicate other people's answers, you should at least add some explanation to your answer to make it interesting
  • Nico Haase
    Nico Haase almost 4 years
    What's the reason for using unset? Please add some explanation to your answer such that others can learn from it
  • Loenix
    Loenix over 3 years
    Using PRG, you lose context, it's a bad solution for me. We should not do that.
  • David
    David over 3 years
    @NicoHaase $everything_fine is the boolean result of form-validation. If the form is not validating then it shall be usually displayed again with a hint what to correct, so that the user can send it again. Therefore the $_SESSION['uniq'] is created again too if a corrected form is desired.
  • Nico Haase
    Nico Haase over 3 years
    Please add all explanation to your answer by editing it
  • David
    David over 3 years
    @NicoHaase It's not my answer, what I did describe is obvious in the code of the answer.
  • BodgeIT
    BodgeIT over 3 years
    Worked perfectly on a system where we couldn't get the post/redirect/get approach to work. Very nice, thanks.
  • Haider Ali J Al-Rustem
    Haider Ali J Al-Rustem over 3 years
    That solved the issue for me. Does this method have any downsides though?
  • amarinediary
    amarinediary about 3 years
    I presumed that, anybody using a browser without javascript would still encounter the same issue. Perhaps stackoverflow.com/a/38768140/3645650 is more suiting.
  • NcXNaV
    NcXNaV almost 3 years
    I am currently using this kind of method, with tokens. However, this will create a problem on multi-tab submission. Since it will create new rand() on each tab, and overwrite the session value, this means older tabs opened is no longer valid. Any suggestion?
  • Utmost Creator
    Utmost Creator over 2 years
    Could you please compare these approaches? 1 AJAX request 2 Post-Redirect-Get(PRG) pattern 3 JS window.history.replaceState IMHO: 1 AJAX is probably the best solution (but requires some time to prepare the form validation to work with the DOM elements) 2 PRG is not always suitable(if you have validation, then you will need to use the intermediary thing to pass the errors with a session that is not that good) 3 JS solution seems like a crutch,isn't it? I would do appreciate any comments/critic about it. Let me know the pros/cons of each. Are there any downfalls using AJAX?
  • cmd05
    cmd05 about 2 years
    this is so much neater