I was wondering what methods/preventions other programmers use to stop data being entered twice into a MySQL database when a user refreshes on the same page as a form? Obvio
Ilya's answer is correct, I just wanted to add a little more than would fit in a comment:
If resubmission is dangerous (going back and submitting again, reloading the result page [if you haven't taken Ilya's advice], etc.) I use a "nonce" to make sure the form can only go through once.
On the form page:
<?php
@session_start(); // make sure there is a session
// store some random string/number
$_SESSION['nonce'] = $nonce = md5('salt'.microtime());
?>
// ... snip ...
<form ... >
<input type="hidden" name="nonce" value="<?php echo $nonce; ?>" />
</form>
In the processing page:
<?php
if (!empty($_POST)) {
@session_start();
// check the nonce
if ($_SESSION['nonce'] != $_POST['nonce']) {
// some error condition
} else {
// clear the session nonce
$_SESSION['nonce'] = null;
}
// continue processing
After the form has been submitted once, it cannot be submitted again, unless the user intentionally fills it out a second time.
I call this a golden rule of web programming:
Never ever respond with a body to a POST-request. Always do the work, and then respond with a Location: header to redirect to the updated page so that browser requests it with GET.
This way, refreshing will not do you any harm.
Also, regarding a discussion here in comments. To protect from double posting from, say, accidental doubleclicking the Submit button, store an md5() of your form in a text file, and compare the new form’s md5 to the stored one. If they are equal, you are having a double post.
I usually rely on the sql UNIQUE index Constraint. http://dev.mysql.com/doc/refman/5.0/en/constraint-primary-key.html
My two cents:
if(isset($_POST['submit'])
Other useful information for similar cases:
Give a look to LOCK TABLES in MySQL
Disable buttons via JavaScript after the first click
You might want to check out the POST/Redirect/GET pattern most modern web apps implement, see http://en.wikipedia.org/wiki/Post/Redirect/Get
In addition to the good suggestions already mentioned about taking the user away from the posting page so a refresh and back button are harmless, another layer in improving your data storage is to use UUIDs as keys in your table and let your applications generate them.
These are also known as GUIDs in the Microsoft world and in PHP you can generate one via uniqid() in PHP. This is a 32 character hex value which you should store in a hex/binary column format but if the table isn't going to be heavily used than CHAR(32) will work.
Generate this ID when you display your form as a hidden input, and make sure to mark the database column is marked as the primary key. Now if the user does manage to go all the way back to a posting page, the INSERT will fail because you can't have duplicate keys.
An extra bonus to this is, if you generate the UUID in code, then after you perform an insert you'll never need to use wasteful queries retrieving the key that was generated because you'll already know it. This is a nice benefit when you need to INSERT child items into other tables.
Good programming is based upon layering your work, not relying on 1 thing to work. Despite how common it is for coders to rely on incremental IDs, they are one of the laziest ways to build a table.