kadin
asked on
Preventing multiple form submissions.
Use only PHP, no JavaScript.
A single form page. <form action="<?php $_SERVER['PHP_SELF'] ?>"
After form subitted a new page appears. (Thank you, your form has been submitted.)
After researching the books I have and google I have found two ways to do this. I am not convinced either way works.
The first inputs a unique random number into the database and also keeps it as a hidden value. When the user clicks submit they are redirected to a thank you page. If they click the back button they will see their sticky form again already filled out. If they click submit again the (pdo) database throws an error and they are redirected to a page that says already submitted. Great it seems to work except if they were to click the back and then click reload or refresh the page, a new unique hidden value is created and they can successfully resubmit the same form info again.
Is there a way to do this that really works?
The first example. The forms action is to self.
if (strlen($_POST['stamp']) == 32) {$stamp = ($_POST['stamp']);}
else {$message = '<p>This page has been accessed in error.</p>'; $stamp = FALSE;}
$sql = "INSERT INTO table (id, f_name, l_name, email, stamp) VALUES(' ', $f_name, $l_name, $email, $stamp)";
// This creates 32 character random number
<input type="hidden" name="stamp" value="<?php echo md5(uniqid(rand(),true)); ?>" />
CREATE TABLE `table` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`f_name` varchar(50) DEFAULT NULL,
`l_name` varchar(50) DEFAULT NULL,
`stamp` char(32) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE (stamp)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
The second way uses sessions and the forms action takes the user to a second page.
Here is the tutorial. phpro dot org/tutorials/Preventing-M ultiple-Su bmits
I have not made this work yet and don't know if it will work after refreshing the page.
session_start();
$form_token = uniqid();
$_SESSION['form_token'] = $form_token;
if($_POST['form_token'] != $_SESSION['form_token'])
{
$message = 'Access denied';
}
<input type="hidden" name="form_token" value="<?php echo $form_token; ?>" />
A single form page. <form action="<?php $_SERVER['PHP_SELF'] ?>"
After form subitted a new page appears. (Thank you, your form has been submitted.)
After researching the books I have and google I have found two ways to do this. I am not convinced either way works.
The first inputs a unique random number into the database and also keeps it as a hidden value. When the user clicks submit they are redirected to a thank you page. If they click the back button they will see their sticky form again already filled out. If they click submit again the (pdo) database throws an error and they are redirected to a page that says already submitted. Great it seems to work except if they were to click the back and then click reload or refresh the page, a new unique hidden value is created and they can successfully resubmit the same form info again.
Is there a way to do this that really works?
The first example. The forms action is to self.
if (strlen($_POST['stamp']) == 32) {$stamp = ($_POST['stamp']);}
else {$message = '<p>This page has been accessed in error.</p>'; $stamp = FALSE;}
$sql = "INSERT INTO table (id, f_name, l_name, email, stamp) VALUES(' ', $f_name, $l_name, $email, $stamp)";
// This creates 32 character random number
<input type="hidden" name="stamp" value="<?php echo md5(uniqid(rand(),true)); ?>" />
CREATE TABLE `table` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`f_name` varchar(50) DEFAULT NULL,
`l_name` varchar(50) DEFAULT NULL,
`stamp` char(32) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE (stamp)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
The second way uses sessions and the forms action takes the user to a second page.
Here is the tutorial. phpro dot org/tutorials/Preventing-M
I have not made this work yet and don't know if it will work after refreshing the page.
session_start();
$form_token = uniqid();
$_SESSION['form_token'] = $form_token;
if($_POST['form_token'] != $_SESSION['form_token'])
{
$message = 'Access denied';
}
<input type="hidden" name="form_token" value="<?php echo $form_token; ?>" />
ASKER CERTIFIED SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
What I meant by 'per session or per user' was could the user (actually I was thinking in the context of a member) only fill that form out once and never again (or only once per day / month / year), because obviously that is a little different than once and then refreshing the page type thing.
As for sticky forms that's a good way to go and very usual. If your sticky forms were working and aren't now then that's another issue, but the example that I gave worked perfectly as retained the session information.
As for the meaning of "sticky forms" as I understand it it just means that the form retains user information on a error event etc, it doesn't have a particular definition on what method should be used to retain the information (i.e cookies, sessions, $_POST, $_GET or select the info from the db).
Let me know how the examples go.
As for sticky forms that's a good way to go and very usual. If your sticky forms were working and aren't now then that's another issue, but the example that I gave worked perfectly as retained the session information.
As for the meaning of "sticky forms" as I understand it it just means that the form retains user information on a error event etc, it doesn't have a particular definition on what method should be used to retain the information (i.e cookies, sessions, $_POST, $_GET or select the info from the db).
Let me know how the examples go.
ASKER
Your little e1 and e2 program works well as it is, however when I integrate it into my form page it shows no sign of working.
I think I might know why.
Your e1 forms action refers to e2. So if(isset($_POST['submit']) ) on e2.php collects the submit word from the form on e1.php.
My forms action refers to its own self page to process the form and then send and email. After sending the email the page is redirected
header('Location: http://localhost/confirm_sent.php'); exit;
confirm_sent.php is equivalent to your e2.php where I have this.
session_start();
if(isset($_POST['submitted ']))
{
$_SESSION['prevSet']=true;
}
echo "A confirmation mail has been sent.";
Can it grab $_POST['submitted'] if the action from the previous page is to itself instead of to this confirm_sent.php?
I put these on confirm_sent.php and they seem to be empty.
print_r($_POST['submitted' ]);
print_r($_SESSION['prevSet ']);
I think I might know why.
Your e1 forms action refers to e2. So if(isset($_POST['submit'])
My forms action refers to its own self page to process the form and then send and email. After sending the email the page is redirected
header('Location: http://localhost/confirm_sent.php'); exit;
confirm_sent.php is equivalent to your e2.php where I have this.
session_start();
if(isset($_POST['submitted
{
$_SESSION['prevSet']=true;
}
echo "A confirmation mail has been sent.";
Can it grab $_POST['submitted'] if the action from the previous page is to itself instead of to this confirm_sent.php?
I put these on confirm_sent.php and they seem to be empty.
print_r($_POST['submitted'
print_r($_SESSION['prevSet
Here is how I prevent multiple submissions. Install this and run it to see how it works. HTH, ~Ray
<?php // RAY_multi_submit.php
error_reporting(E_ALL);
// ALWAYS START SESSION ON EVERY PAGE
session_start();
// PREVENT MULTIPLE SUBMISSIONS DUE TO REPEATED CLICKS ON SUBMIT BUTTON
// EXAMPLE:
// if ( multi_submit() )
// {
// handle error
// }
// else
// {
// normal processing
// }
function multi_submit($type="post")
{
// MAKE THE FUNCTION WORK FOR EITHER GET OR POST SUBMITS
$input_array = ($type == "get") ? $_GET : $_POST;
// GATHER THE CONTENTS OF ALL THE SUBMITTED FIELDS AND MAKE A MESSAGE DIGEST
$string = "";
foreach ($input_array as $val) { $string .= $val; }
$string = md5($string);
// IF THE SESSION VARIABLE IS NOT SET, THIS IS NOT A MULTI-SUBMIT
if (!isset($_SESSION["_multi_submit"]))
{
// SAVE THE SUBMITTED DATA MESSAGE DIGEST
$_SESSION['_multi_submit'] = $string;
return FALSE;
}
// IF THE SESSION DATA MATCHES THE MESSAGE DIGEST, THIS IS A MULTI-SUBMIT
if ($_SESSION['_multi_submit'] === $string)
{
return TRUE;
}
else
{
// SAVE THE MESSAGE DIGEST
$_SESSION['_multi_submit'] = $string;
return FALSE;
}
}
// SHOW HOW THIS IS DONE
if (!empty($_POST))
{
if (multi_submit())
{
die("ALREADY GOT THAT");
}
}
// END OF PHP - PUT UP THE FORM
?>
<form method="post">
ENTER SOMETHING, THEN REENTER IT
<input name="foo" />
<input type="submit">
</form>
ASKER
I seem to have got it working and I learned more about sessions in the process.
The challenge was how to access $_POST from page two when page ones action="<?php $_SERVER['PHP_SELF'] ?>" does not send $_POST info to page two.
I tried adding two addresses to action="<?php $_SERVER['PHP_SELF'] ?>, page_two.php"
That did not work, so built from MichaelT's example program. I have three pages involved now. Form page1, thank you page2, and home page3.
Form page starts a session
session_start();
if(isset($_POST['submitted ']))
{
$_SESSION['nprevSet']=true ;
}
and then header(redirect to thank you page);
Thank you page
session_start();
if(isset($_SESSION['nprevS et']))
{
$_SESSION['prevSet']=true;
unset($_SESSION['nprevSet' ]); // comment this out to persist the session being set
}
The challenge was how to access $_POST from page two when page ones action="<?php $_SERVER['PHP_SELF'] ?>" does not send $_POST info to page two.
I tried adding two addresses to action="<?php $_SERVER['PHP_SELF'] ?>, page_two.php"
That did not work, so built from MichaelT's example program. I have three pages involved now. Form page1, thank you page2, and home page3.
Form page starts a session
session_start();
if(isset($_POST['submitted
{
$_SESSION['nprevSet']=true
}
and then header(redirect to thank you page);
Thank you page
session_start();
if(isset($_SESSION['nprevS
{
$_SESSION['prevSet']=true;
unset($_SESSION['nprevSet'
}
ASKER
I pressed the tab and space bar and my comment automatically posted before I could finish it.
Any way while on the thank you page, click the back button to go back to the form page where a new session variable is set, the old one is unset and another header redirect, this time to the home page. The home page unsets the last session variable and the user is now free to navigate to the form page.
Thanks Ray for your example. I will save it and try to learn from it a little later. Right now in my stage of learning it is like a juggling act. It is hard to take on something new until my current understanding gets a little more stable.
Any way while on the thank you page, click the back button to go back to the form page where a new session variable is set, the old one is unset and another header redirect, this time to the home page. The home page unsets the last session variable and the user is now free to navigate to the form page.
Thanks Ray for your example. I will save it and try to learn from it a little later. Right now in my stage of learning it is like a juggling act. It is hard to take on something new until my current understanding gets a little more stable.
Glad to hear you got it working, and you learnt a few things along the way :)
ASKER
I am not quite sure what you mean by (Is this a per session or per user restriction?)
As it is, all someone has to do to re-input or upload the same info is click four buttons over and over.
Click submit, click the back button, click reload, click submit again. (Clicking reload generates a new uniqid() stamp and sticky forms holds the original info, making it convenient and quick to resubmit the same info).
I will allow the user to fill out multiple forms, but only if they start from scratch and type everything in. I want to prevent or discourage vandals or the accident prone from making unnecessary submissions.
I am using sticky forms in case the user forgets to fill out every field, the form will display a PHP (not JavaScript) message near the empty field. While this happens the page is being reloaded.
I tried using sessions earlier today for the first time ever and noticed my sticky forms were no longer sticky. Is this normal?
I thought sessions were a replacement for sticky forms, however it was my understanding it required putting a cookie on someones computer. I really don't want to do that.
I will try out your examples.