I’m testing with this code:
<?php
$db = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
if(filter_has_var(INPUT_POST, 'submit')) {
$r = $db->query('SELECT * FROM test WHERE value="'.$_POST['value'].'"');
$n = $r->rowCount();
for ($i=0; $i<=10000000; $i++) {
// do nothing
}
if (!$n) {
$db->query('INSERT INTO test (id, value) VALUES (NULL, "'.$_POST['value'].'")');
}
}
?>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<input type="text" name="value" value="">
<input type="submit" name="submit" value="Submit">
</form>
When testing the above form in safari I am able to submit the same value into my database multiple times by rapidly clicking the submit button.
But, when I test with this code:
<?php
$db = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
if(filter_has_var(INPUT_POST, 'submit')) {
for ($i=0; $i<=10000000; $i++) {
// do nothing
}
$r = $db->query('SELECT * FROM test WHERE value="'.$_POST['value'].'"');
$n = $r->rowCount();
if (!$n) {
$db->query('INSERT INTO test (id, value) VALUES (NULL, "'.$_POST['value'].'")');
}
}
?>
The conditional works and I’m unable to submit the same value multiple times no matter how fast I click the submit button.
Is there a reliable way to prevent duplicate database inserts from occurring with the first code snippet so that it behaves just like the second snippet?
Generally a client side
onsubmithandler can help stop accidental rapid-submissions, but I usually opt for a server side solution using_SESSIONvariables. Just create a hash of the$_POSTarray, store it as a session variable, and then compare the next submitted_POSTto the hashed version:If you only want to stop repeat-submissions for a short period of time, you can also have a second
$_SESSIONvariable store the time of the last hash, so you can expire it after a second or two.