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
Add a hidden field with a random string (produced by md5(uniqid())
for example), make a field in the database for that string and make it UNIQUE.
The best way to avoid duplicate record insertion on page refresh is, after inserting records in the database on button click, just add this line:
Response.Write("<script>location.href='yourpage.aspx'</script>");
You have to pass an uniqid variable into your html inside the showAddProductForm() method and the same uniqid into your $_SESSION forexample:
public function showAddProductForm()
{
$uniId = uniqid();
$_SESSION['token'][$uniId] = '1';
$fields['token'] = 'token['.$uniId.']';
$this->fileName = 'product.add.form.php';
$this->template($fields);
die();
}
Then you have to put a hidden input in HTML code inside your form with the value of the uniqid that has been passed into the HTML from showAddProductForm method.
<input type="hidden" name="<?=$list['token']?>" value="1">
right after the submit event you will analyze it in the beginning of the addProduct() method. If the token exists in the $_SESSION and it has an equal value inside that array, then this is the new reques. Redirect him to the proper page and unset the token and continue insert. Else it is from the reloading page or a repetitive request, redirect him to addProdeuct page
public function addProducts($fields)
{
$token_list = array_keys($fields['token']);
$token = $token_list['0'];
if (isset($_SESSION['token'][$token]) and $_SESSION['token'][$token] == '1') {
unset($_SESSION['token'][$token]);
} else {
$this->addAnnounceForm($fields, '');
}
}
Maybe you ask why an array of tokens why not a single variable. Because in admin Panel users open multi tabs and inserting in multi tabs so this algorithm will fail if they use multi tabs.
Special thanks to who figure out this method malekloo
To state the obvious (I have not seen it here yet...): Never use GET to post data, always use POST, that way the user at least gets a warning if he or she tries to refresh /re-post the page (at least in Firefox, but I suppose in other browsers as well).
By the way, if you cannot afford to have the same data twice, you should also consider a MySQL solution with a unique key (can be a combination of fields) and:
INSERT INTO ... ON DUPLICATE KEY UPDATE ...
POE (Post Once Exactly) is an HTTP pattern aimed at warning the client to block double submits using a proprietary header ...
GET /posts/new HTTP/1.1
POE: 1
...
... but is still in specification.
http://www.mnot.net/drafts/draft-nottingham-http-poe-00.txt
I think the above nonce is a good solution. Though storing the nonce as a discrete session variable will introduce some errors if the client is attempting to perform simultaneous posts from multiple tabs. Maybe better to ...
$_SESSION['nonces'][] = $nonce;
... and ...
if (in_array($_POST['nonce'], $_SESSION['nonces'])) {
... to allow for multiple nonces (nonci? noncei?).
Well, first of all, to minimize, you should make it so they have to do form post to insert the data. That way, at least they will get that nice little confirmation dialog asking if they really want to resubmit it.
To get more complicated than that, you could put a hidden one time use key in each form, and once the form with that key has been submitted, display an error when they try to submit a form with the same key. To create this key, you probably want to use something like a GUID.