Unset post variables after form submission
Asked Answered
C

11

10

Is there a way to do the above? Basically, I don't want the form to be submitted again if someone presses refresh after already submitting the form once. In which case the browser asks, do you want to submit the form again. Will unset($_POST['username']) be of any help is this case?

Cavernous answered 1/8, 2012 at 18:16 Comment(3)
The only thing I can think of is unset($_POST['username']), but I don't know that it will work -- why don't you try it?Philip
It would not. The refresh button on the browser resends the last HTTP request that was sent by the client; clearing the server-side $_POST wouldn't change that fact.Baudin
need clear? $_POST = array();Paleoecology
C
11

The post/redirect/get is a good option as some posters have already mentioned.

One another way I can think of is to set a session in the dostuff.php page to indicate that the posting has already been done. Check this session var each time to see if the page is being loaded again because of a page refresh.

<?php
    session_start();
    if(isset($_SESSION['indicator'])) 
    {
        /*
        dont do anything because session indicator says 
        that the processing was already done..

        you might want to redirect to a new url here..          
        */
    }   
    else
    {

        /*
        first set session indicator so that subsequent 
        process requests will be ignored
        */
        $_SESSION['indicator'] = "processed"; 

        //process the request here..
    }
    ?>

In the page you redirect to, unset the session var so that the form can be resubmitted again afresh, making it a new post operation. This will allow new form posts but will prevent post operations due to page refresh

Couthie answered 1/8, 2012 at 18:59 Comment(2)
sounds like an idea. a cookie may also help similarly.Cavernous
sorry for marking this as the right answer so late. just going through my old questions/answers after a long time. thanks.Cavernous
L
3

Use an intermediate page to do the operations and then redirect.

For example:

mypage.php --> the page with the form

dostuff.php --> receives the form data and makes operations, then redirects to any other page.

To do a redirect:
Put this line on the top of "dostuff.php": header("Location: mypage.php");

Larcener answered 1/8, 2012 at 18:18 Comment(4)
that leaves open ends for hackers, imo. The url (dostuff.php) will obviously be visible in the form action param. anyone can then fiddle with the url through the browser ( example.com/dostuff.php ). Correct me if I am wrong.Cavernous
Yes, you're wrong. Even if you send the form with javascript, there's always a page receiving the data. It doesn't matter if it's the same page or another (dostuff.php). You are sending the same data. An attacker would just keep track of the HTTP requests.Larcener
yep. exaclty where my question comes in. how to prevent the fiddling even though the submit php link is visible?Cavernous
You can't. The only way to prevent automated form sending is using a captcha.Larcener
L
2

You need to use the POST/REDIRECT/GET pattern for this.

Post/Redirect/Get (PRG) is a web development design pattern that prevents some duplicate form submissions, creating a more intuitive interface for user agents (users). PRG supports bookmarks and the refresh button in a predictable way that does not create duplicate form submissions.

When a web form is submitted to a server through an HTTP POST request, a web user that attempts to refresh the server response in certain user agents can cause the contents of the original POST request to be resubmitted, possibly causing undesired results, such as a duplicate web purchase.

To avoid this problem, many web developers use the PRG pattern—instead of returning a web page directly, the POST operation returns a redirection command. The HTTP 1.1 specification introduced the HTTP 303 ("See other") response code to ensure that in this situation, the web user's browser can safely refresh the server response without causing the initial POST request to be resubmitted. However most common commercial applications in use today (new and old alike) still continue to issue HTTP 302 ("Found") responses in these situations.

Here's an example in PHP:

header('Location: /yourpage.php', true, 303);
exit;
Loyce answered 1/8, 2012 at 18:19 Comment(0)
A
2

The problem you are facing above specifically can (and should) be solved with Post/Redirect/Get. Unsetting _POST on the php side would be ineffective since the problem is it is a separate request.

You also have to deal with double-clicking of submission buttons. You can solve this on the client side by disabling form submission after the button click, or by putting a random token in the form and storing that token in the session. The token will be accepted only once (session keeps track of whether the token has been posted).

Adjoining answered 1/8, 2012 at 18:20 Comment(0)
S
2

Here's a nice method I use to keep users from submiting the same data twice, which will also prevent the page from adding the same record to the database when reload.

// First IF
if ($_SESSION['dup_comment_body'] == $_POST['comment_body']) { 
    echo 'You already entered that.';
} else {
    // Second IF
    if ($_POST['comment_body']) {

        // Run your query here

    $_SESSION['dup_comment_body'] = $_POST['comment_body']; 
    header('location:'.$_SERVER['REQUEST_URI'].'');
    }
} 

The first IF checks to see if the $_POST is equal to the last thing they typed ($_SESSION). If it's not the same it runs the next IF to test if the $_POST variable is not empty. Inside the last IF towards the bottom it sets $_SESSION['dup_comment_body'] to equal the $_POST. So next time the first IF runs and the $_POST is the same, they will get the message "You already entered that.". Hope this helps!

Scarabaeoid answered 30/3, 2013 at 12:2 Comment(0)
M
2

Use this code

    if(isset($_POST)){
      header('location:'.$_SERVER['PHP_SELF']);
      die();
     }
Mammary answered 4/11, 2015 at 9:9 Comment(2)
From what I am able to understand from the code, you are sending GET request to the same url in case there is a non-empty post request. But wouldn't this cancel my first request itself?Cavernous
no it won't cancel your first request . If you just want to disable form submitting after first submission , you can use javascript for that . This code will clear the current post variables only , So browser will not ask for form submission again because there is no post values now.Mammary
S
0

My solution for this is doing a meta refresh if a post variable is set the $_POST do not follow it after the refresh.

<head>
<?php
  if (isset($_POST['Task'])){
  echo' <meta http-equiv="refresh" content="0; url=./ThisFile.php">';
  }
  ?>
</head>
Sourwood answered 3/10, 2017 at 13:17 Comment(0)
C
0

If your form is going to be updating a database, then you can update or insert only if record does not exist. Simply do a select statement first. This will prevent duplicate records due to refresh.

Coupling answered 6/9, 2018 at 16:30 Comment(0)
G
0

If you are inserting the contents of this form to database, simply use the php/sql SELECT statement to check if "username" has already been submitted. If yes, throw an error. Like so:

//Database Values: servername, dbname, username and password;
//Also set ($_POST['username']) = $username or anything you like; 
$usererror = ""; //Will be filled later.
try { 
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$stmt1 = $conn->prepare("SELECT * FROM yourdb WHERE username=:username");
$stmt1->bindParam(':email', $email);
$stmt1->execute();
$stmt1->fetch();

$querycheck = $stmt1->rowCount();
if ($querycheck >= 1) {
$usererror = "User already exists.";
}
}
catch(PDOException $e) {
// roll back the transaction if something failed
$conn->rollback();
echo "Critical Error. Contact admin immediately.";
error_log("Error: " . $e->getMessage(), 0); //logs connection errors instead of echoing the errors (for security reasons.)
}
$conn = null;

Then you can now insert only the form has no error:

If (empty($usererror)) {
//insert command 
}

Notice I used prepared statements, because on many articles, it is said to be the safest method to operate on Databases using php+sql. You can as well use the normal method if you don't really have security concerns, it'll save you more code lines too.

Also notice the $querycheck >= 1, it is very essential to ensure 1 insertion and never more than 1 even if the user refreshes 2,000 times, clicks back button and submit again etc. The mistake that tied me down and drove me mad for days was using $querycheck > 1 instead of $querycheck >= 1, that way, my forms kept submitting twice before throwing "Already Exists" error. Finally, I've been able to fix it. Hope this helps people that will visit this question later.

Guevara answered 12/4, 2020 at 10:58 Comment(0)
V
0

You can just reset the $_POST array after processing form data, for example like below code

<?php
if( isset($_POST['submit']))
{
//do some processing related to form;
//after done.....
$_POST = array(); //this declares post as empty array 
//which is global variable anyways.
}
?>

Or the second way is to use the hidden form thing....

<?php
if( isset($_POST['submit']))
{
//do some processing related to form;

//create a form with hidden field
?>
<form method="post" name="myform" action="actionpage">
<input type="hidden" name="somename" value="">
</form>
<?php
echo "<script> document.forms['myform'].submit();</script>";
}
?>

This will basically submits the form with 1 field with null value, I don't know if this is optimal but it fulfills need here.

Vardhamana answered 2/6, 2021 at 15:56 Comment(0)
E
-2

Instead, you could use a captcha such as Recaptcha that doesn't allow post submission without doing the captcha. This is what I used and it works perfectly.

Expectoration answered 29/9, 2017 at 21:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.