01/14/2009 Updated CanProcessAction - left out where it creates an ID!
Here's something that comes up periodically, "how do you prevent the dreaded double-click?" From something as common as a banking or purchasing transaction getting run twice or more because of overzealous clicking, to batch processing for the night - to pushing items through workflow. How do you prevent it?
A typical strategy is to disable the button in javascript. This works, somewhat, but doesn't prevent someone from hitting refresh once they get to the next page.
My strategy, certificated submits:
- A Table (in MySQL here):
CREATE TABLE CLICK_CERTIFICATES ( certificate_id varchar(40) not null, primary key (certificate_id) )
- A way to create a GUID or unqiue id:
function CreateGUID(){ srand((double)microtime()*1000000); $r = rand ; $u = uniqid($r); $m = md5 ($u); return($m); } - A function that tells us if we can process the action:
function CanProcessAction($certificate_id){ $certificate_id = addslashes($certificate_id); if(trim($certificate_id)!=""){ $fetch = mysql_query("select count(*) from CLICK_CERTIFICATES where certificate_id='$certificate_id'"); $row = mysql_fetch_row($fetch); $exists = ($row[0]!=0); } else { $exists = false; $certificate_id=CreateGUID();} if(!exists){ mysql_unbuffered_query("insert into CLICK_CERTIFICATES (certificate_id) values ('$certificate_id')"); } return !$exists; } - Now, just use a hidden variable on your form that creates the value of the certificate:
<input type="hidden" name="certificate_id" value="<? echo CreateGUID(); ?>">
- And then just wrap your action on the receiving page like so:
$certificate_id = $_POST["certificate_id"]; if (CanProcessAction($certificate_id)){ //do something only this once, even if they clicked twice, or refreshed the page. }You can also put other things in the table to "re-allow" an attempt after a certain amount of time, or log the extra clicks so you can nag your users. By doing the time control, you can prevent users from re-running resource intensive reports for a given interval, and caching the results.