Related
I have a simple form that submits text to my SQL table. The problem is that after the user submits the text, they can refresh the page and the data gets submitted again without filling the form again. I could redirect the user to another page after the text is submitted, but I want users to stay on the same page.
I remember reading something about giving each user a unique session id and comparing it with another value which solved the problem I am having but I forgot where it is.
I would also like to point out that you can use a javascript approach, window.history.replaceState to prevent a resubmit on refresh and back button.
<script>
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
</script>
Proof of concept here: https://dtbaker.net/files/prevent-post-resubmit.php (Link no longer works)
I would still recommend a Post/Redirect/Get approach, but this is a novel JS solution.
Use the Post/Redirect/Get pattern. http://en.wikipedia.org/wiki/Post/Redirect/Get
With my website, I will store a message in a cookie or session, redirect after the post, read the cookie/session, and then clear the value of that session or cookie variable.
You can prevent form resubmission via a session variable.
First you have to set rand() in a textbox and $_SESSION['rand'] on the form page:
<form action="" method="post">
<?php
$rand=rand();
$_SESSION['rand']=$rand;
?>
<input type="hidden" value="<?php echo $rand; ?>" name="randcheck" />
Your Form's Other Field
<input type="submit" name="submitbtn" value="submit" />
</form>
After that check $_SESSION['rand'] with textbox $_POST['randcheck'] value
like this:
if(isset($_POST['submitbtn']) && $_POST['randcheck']==$_SESSION['rand'])
{
// Your code here
}
Make sure you start the session on every file you are using it with session_start()
I use this javascript line to block the pop up asking for form resubmission on refresh once the form is submitted.
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
Just place this line at the footer of your file and see the magic
When the form is processed, you redirect to another page:
... process complete....
header('Location: thankyou.php');
you can also redirect to the same page.
if you are doing something like comments and you want the user to stay on the same page, you can use Ajax to handle the form submission
You should really use a Post Redirect Get pattern for handling this but if you've somehow ended up in a position where PRG isn't viable (e.g. the form itself is in an include, preventing redirects) you can hash some of the request parameters to make a string based on the content and then check that you haven't sent it already.
//create digest of the form submission:
$messageIdent = md5($_POST['name'] . $_POST['email'] . $_POST['phone'] . $_POST['comment']);
//and check it against the stored value:
$sessionMessageIdent = isset($_SESSION['messageIdent'])?$_SESSION['messageIdent']:'';
if($messageIdent!=$sessionMessageIdent){//if its different:
//save the session var:
$_SESSION['messageIdent'] = $messageIdent;
//and...
do_your_thang();
} else {
//you've sent this already!
}
I found next workaround. You may escape the redirection after processing POST request by manipulating history object.
So you have the HTML form:
<form method=POST action='/process.php'>
<input type=submit value=OK>
</form>
When you process this form on your server you instead of redirecting user to /the/result/page by setting up the Location header like this:
$cat process.php
<?php
process POST data here
...
header('Location: /the/result/page');
exit();
?>
After processing POSTed data you render small <script> and the result /the/result/page
<?php
process POST data here
render the <script> // see below
render `/the/result/page` // OK
?>
The <script> you should render:
<script>
window.onload = function() {
history.replaceState("", "", "/the/result/page");
}
</script>
The result is:
as you can see the form data is POSTed to process.php script.
This script process POSTed data and rendering /the/result/page at once with:
no redirection
no rePOST data when you refresh page (F5)
no rePOST when you navigate to previous/next page through the browser history
UPD
As another solution I ask feature request the Mozilla FireFox team to allow users to setup NextPage header which will work like Location header and make post/redirect/get pattern obsolete.
In short. When server process form POST data successfully it:
Setup NextPage header instead of Location
Render the result of processing POST form data as it would render for GET request in post/redirect/get pattern
The browser in turn when see the NextPage header:
Adjust window.location with NextPage value
When user refresh the page the browser will negotiate GET request to NextPage instead of rePOST form data
I think this would be excelent if implemented, would not? =)
Use header and redirect the page.
header("Location:your_page.php"); You can redirect to same page or different page.
Unset $_POST after inserting it to Database.
unset($_POST);
A pretty surefire way is to implement a unique ID into the post and cache it in the
<input type='hidden' name='post_id' value='".createPassword(64)."'>
Then in your code do this:
if( ($_SESSION['post_id'] != $_POST['post_id']) )
{
$_SESSION['post_id'] = $_POST['post_id'];
//do post stuff
} else {
//normal display
}
function createPassword($length)
{
$chars = "abcdefghijkmnopqrstuvwxyz023456789";
srand((double)microtime()*1000000);
$i = 0;
$pass = '' ;
while ($i <= ($length - 1)) {
$num = rand() % 33;
$tmp = substr($chars, $num, 1);
$pass = $pass . $tmp;
$i++;
}
return $pass;
}
A refined version of Moob's post. Create a hash of the POST, save it as a session cookie, and compare hashes every session.
// Optionally Disable browser caching on "Back"
header( 'Cache-Control: no-store, no-cache, must-revalidate' );
header( 'Expires: Sun, 1 Jan 2000 12:00:00 GMT' );
header( 'Last-Modified: ' . gmdate('D, d M Y H:i:s') . 'GMT' );
$post_hash = md5( json_encode( $_POST ) );
if( session_start() )
{
$post_resubmitted = isset( $_SESSION[ 'post_hash' ] ) && $_SESSION[ 'post_hash' ] == $post_hash;
$_SESSION[ 'post_hash' ] = $post_hash;
session_write_close();
}
else
{
$post_resubmitted = false;
}
if ( $post_resubmitted ) {
// POST was resubmitted
}
else
{
// POST was submitted normally
}
Basically, you need to redirect out of that page but it still can make a problem while your internet slow (Redirect header from serverside)
Example of basic scenario :
Click on submit button twice
Way to solve
Client side
Disable submit button once client click on it
If you using Jquery : Jquery.one
PRG Pattern
Server side
Using differentiate based hashing timestamp / timestamp when request was sent.
Userequest tokens. When the main loads up assign a temporary request tocken which if repeated is ignored.
How to prevent php form resubmission without redirect. If you are using $_SESSION (after session_start) and a $_POST form, you can do something like this:
if ( !empty($_SESSION['act']) && !empty($_POST['act']) && $_POST['act'] == $_SESSION['act'] ) {
// do your stuff, save data into database, etc
}
In your html form put this:
<input type="hidden" id="act" name="act" value="<?php echo ( empty($_POST['act']) || $_POST['act']==2 )? 1 : 2; ?>">
<?php
if ( $_POST['act'] == $_SESSION['act'] ){
if ( empty( $_SESSION['act'] ) || $_SESSION['act'] == 2 ){
$_SESSION['act'] = 1;
} else {
$_SESSION['act'] = 2;
}
}
?>
So, every time when the form is submitted, a new act is generated, stored in session and compared with the post act.
Ps: if you are using an Get form, you can easily change all POST with GET and it works too.
The $_POST['submit'] variable would not exist on initial loading of page, and curl can be run only if below condition is true.
if($_POST['submit'] == "submit"){
// This is where you run the Curl code and display the output
$curl = curl_init();
//clear $post variables after posting
$_POST = array();
}
After inserting it to database, call unset() method to clear the data.
unset($_POST);
To prevent refresh data insertion, do a page redirection to same page or different page after record insert.
header('Location:'.$_SERVER['PHP_SELF']);
Using the Post/Redirect/Get pattern from Keverw answer is a good idea. However, you are not able to stay on your page (and I think this was what you were asking for?) In addition, it may sometimes fail:
If a web user refreshes before the initial submission has completed
because of server lag, resulting in a duplicate HTTP POST request in
certain user agents.
Another option would be to store in a session if text should be written to your SQL database like this:
if($_SERVER['REQUEST_METHOD'] != 'POST')
{
$_SESSION['writeSQL'] = true;
}
else
{
if(isset($_SESSION['writeSQL']) && $_SESSION['writeSQL'])
{
$_SESSION['writeSQL'] = false;
/* save $_POST values into SQL */
}
}
As others have said, it is not possible to out of using post/redirect/get. But at the same time it is quite easy to do what you want to do server side.
In your POST page you simply validate the user input but do not act on it, instead you copy it into a SESSION array. You then redirect back to the main submission page again. Your main submission page starts by checking to see if the SESSION array that you are using exists, and if so copy it into a local array and unset it. From there you can act on it.
This way you only do all your main work once, achieving what you want to do.
I searched for solution to prevent resubmission in a huge project afterwards.
The code highly works with $_GET and $_POST and I can't change the form elements behaviour without the risk of unforeseen bugs.
So, here is my code:
<!-- language: lang-php -->
<?php
// Very top of your code:
// Start session:
session_start();
// If Post Form Data send and no File Upload
if ( empty( $_FILES ) && ! empty( $_POST ) ) {
// Store Post Form Data in Session Variable
$_SESSION["POST"] = $_POST;
// Reload Page if there were no outputs
if ( ! headers_sent() ) {
// Build URL to reload with GET Parameters
// Change https to http if your site has no ssl
$location = "https://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
// Reload Page
header( "location: " . $location, true, 303 );
// Stop any further progress
die();
}
}
// Rebuilt POST Form Data from Session Variable
if ( isset( $_SESSION["POST"] ) ) {
$_POST = $_SESSION["POST"];
// Tell PHP that POST is sent
$_SERVER['REQUEST_METHOD'] = 'POST';
}
// Your code:
?><html>
<head>
<title>GET/POST Resubmit</title>
</head>
<body>
<h1>Forms:</h1>
<h2>GET Form:</h2>
<form action="index.php" method="get">
<input type="text" id="text_get" value="test text get" name="text_get"/>
<input type="submit" value="submit">
</form>
<h2>POST Form:</h2>
<form action="index.php" method="post">
<input type="text" id="text_post" value="test text post" name="text_post"/>
<input type="submit" value="submit">
</form>
<h2>POST Form with GET action:</h2>
<form action="index.php?text_get2=getwithpost" method="post">
<input type="text" id="text_post2" value="test text get post" name="text_post2"/>
<input type="submit" value="submit">
</form>
<h2>File Upload Form:</h2>
<form action="index.php" method="post" enctype="multipart/form-data">
<input type="file" id="file" name="file">
<input type="submit" value="submit">
</form>
<h1>Results:</h1>
<h2>GET Form Result:</h2>
<p>text_get: <?php echo $_GET["text_get"]; ?></p>
<h2>POST Form Result:</h2>
<p>text_post: <?php echo $_POST["text_post"]; ?></p>
<h2>POST Form with GET Result:</h2>
<p>text_get2: <?php echo $_GET["text_get2"]; ?></p>
<p>text_post2: <?php echo $_POST["text_post2"]; ?></p>
<h2>File Upload:</h2>
<p>file:
<pre><?php if ( ! empty( $_FILES ) ) {
echo print_r( $_FILES, true );
} ?></pre>
</p>
<p></p>
</body>
</html><?php
// Very Bottom of your code:
// Kill Post Form Data Session Variable, so User can reload the Page without sending post data twice
unset( $_SESSION["POST"] );
It only works to avoid the resubmit of $_POST, not $_GET. But this is the behaviour I need.
The resubmit issue doesn't work with file uploads!
What Works For Me is :
if ( !refreshed()) {
//Your Submit Here
if (isset( $_GET['refresh'])) {
setcookie("refresh",$_GET['refresh'], time() + (86400 * 5), "/");
}
}
}
function refreshed()
{
if (isset($_GET['refresh'])) {
$token = $_GET['refresh'];
if (isset($_COOKIE['refresh'])) {
if ($_COOKIE['refresh'] != $token) {
return false;
} else {
return true;
}
} else {
return false;
}
} else {
return false;
}
}
function createToken($length) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
?>
And in your Form
<form action="?refresh=<?php echo createToken(3)?>">
</form>
This form.php sample shows how to use PRG correct (when form is valid or not).
It redirects to the same page, only when form is valid and action was performed.
Redirection protects form from being resubmitted on page refresh.
It uses session to not loose success messages you want to show when form is valid.
There are two buttons for testing: "Valid submit", "Invalid submit". Try both and refresh page after that.
<?php
session_start();
function doSelfRedirect()
{
header('Location:'.$_SERVER['PHP_SELF']);
exit;
}
function setFlashMessage($msg)
{
$_SESSION['message'] = $msg;
}
function getFlashMessage()
{
if (!empty($_SESSION['message'])) {
$msg = $_SESSION['message'];
unset($_SESSION['message']);
} else {
$msg = null;
}
return $msg;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Validation primitive example.
if (empty($_POST['valid'])) {
$formIsValid = false;
setFlashMessage('Invalid form submit');
} else {
$formIsValid = true;
}
if ($formIsValid) {
// Perform any actions here.
// ...
// Cool!
setFlashMessage('Form is valid. Action performed.');
// Prevent form resubmission.
doSelfRedirect();
}
}
?>
<h1>Hello form</h1>
<?php if ($msg = getFlashMessage()): ?>
<div><?= $msg ?></div>
<?php endif; ?>
<form method="post">
<input type="text" name="foo" value="bar"><br><br>
<button type="submit" name="invalid" value="0">Invalid submit</button>
<button type="submit" name="valid" value="1">Valid submit</button>
</form>
if (($_SERVER['REQUEST_METHOD'] == 'POST') and (isset($_SESSION['uniq']))){
if($everything_fine){
unset($_SESSION['uniq']);
}
}
else{
$_SESSION['uniq'] = uniqid();
}
$everything_fine is the boolean result of form-validation. If the form is not validating then it shall be usually displayed again with a hint what to correct, so that the user can send it again. Therefore the $_SESSION['uniq'] is created again too if a corrected form is desired
Why not just use the $_POST['submit'] variable as a logical statement in order to save whatever is in the form. You can always redirect to the same page (In case they refresh, and when they hit go back in the browser, the submit post variable wouldn't be set anymore. Just make sure your submit button has a name and id of submit.
I have a simple form that submits text to my SQL table. The problem is that after the user submits the text, they can refresh the page and the data gets submitted again without filling the form again. I could redirect the user to another page after the text is submitted, but I want users to stay on the same page.
I remember reading something about giving each user a unique session id and comparing it with another value which solved the problem I am having but I forgot where it is.
I would also like to point out that you can use a javascript approach, window.history.replaceState to prevent a resubmit on refresh and back button.
<script>
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
</script>
Proof of concept here: https://dtbaker.net/files/prevent-post-resubmit.php (Link no longer works)
I would still recommend a Post/Redirect/Get approach, but this is a novel JS solution.
Use the Post/Redirect/Get pattern. http://en.wikipedia.org/wiki/Post/Redirect/Get
With my website, I will store a message in a cookie or session, redirect after the post, read the cookie/session, and then clear the value of that session or cookie variable.
You can prevent form resubmission via a session variable.
First you have to set rand() in a textbox and $_SESSION['rand'] on the form page:
<form action="" method="post">
<?php
$rand=rand();
$_SESSION['rand']=$rand;
?>
<input type="hidden" value="<?php echo $rand; ?>" name="randcheck" />
Your Form's Other Field
<input type="submit" name="submitbtn" value="submit" />
</form>
After that check $_SESSION['rand'] with textbox $_POST['randcheck'] value
like this:
if(isset($_POST['submitbtn']) && $_POST['randcheck']==$_SESSION['rand'])
{
// Your code here
}
Make sure you start the session on every file you are using it with session_start()
I use this javascript line to block the pop up asking for form resubmission on refresh once the form is submitted.
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
Just place this line at the footer of your file and see the magic
When the form is processed, you redirect to another page:
... process complete....
header('Location: thankyou.php');
you can also redirect to the same page.
if you are doing something like comments and you want the user to stay on the same page, you can use Ajax to handle the form submission
You should really use a Post Redirect Get pattern for handling this but if you've somehow ended up in a position where PRG isn't viable (e.g. the form itself is in an include, preventing redirects) you can hash some of the request parameters to make a string based on the content and then check that you haven't sent it already.
//create digest of the form submission:
$messageIdent = md5($_POST['name'] . $_POST['email'] . $_POST['phone'] . $_POST['comment']);
//and check it against the stored value:
$sessionMessageIdent = isset($_SESSION['messageIdent'])?$_SESSION['messageIdent']:'';
if($messageIdent!=$sessionMessageIdent){//if its different:
//save the session var:
$_SESSION['messageIdent'] = $messageIdent;
//and...
do_your_thang();
} else {
//you've sent this already!
}
I found next workaround. You may escape the redirection after processing POST request by manipulating history object.
So you have the HTML form:
<form method=POST action='/process.php'>
<input type=submit value=OK>
</form>
When you process this form on your server you instead of redirecting user to /the/result/page by setting up the Location header like this:
$cat process.php
<?php
process POST data here
...
header('Location: /the/result/page');
exit();
?>
After processing POSTed data you render small <script> and the result /the/result/page
<?php
process POST data here
render the <script> // see below
render `/the/result/page` // OK
?>
The <script> you should render:
<script>
window.onload = function() {
history.replaceState("", "", "/the/result/page");
}
</script>
The result is:
as you can see the form data is POSTed to process.php script.
This script process POSTed data and rendering /the/result/page at once with:
no redirection
no rePOST data when you refresh page (F5)
no rePOST when you navigate to previous/next page through the browser history
UPD
As another solution I ask feature request the Mozilla FireFox team to allow users to setup NextPage header which will work like Location header and make post/redirect/get pattern obsolete.
In short. When server process form POST data successfully it:
Setup NextPage header instead of Location
Render the result of processing POST form data as it would render for GET request in post/redirect/get pattern
The browser in turn when see the NextPage header:
Adjust window.location with NextPage value
When user refresh the page the browser will negotiate GET request to NextPage instead of rePOST form data
I think this would be excelent if implemented, would not? =)
Use header and redirect the page.
header("Location:your_page.php"); You can redirect to same page or different page.
Unset $_POST after inserting it to Database.
unset($_POST);
A pretty surefire way is to implement a unique ID into the post and cache it in the
<input type='hidden' name='post_id' value='".createPassword(64)."'>
Then in your code do this:
if( ($_SESSION['post_id'] != $_POST['post_id']) )
{
$_SESSION['post_id'] = $_POST['post_id'];
//do post stuff
} else {
//normal display
}
function createPassword($length)
{
$chars = "abcdefghijkmnopqrstuvwxyz023456789";
srand((double)microtime()*1000000);
$i = 0;
$pass = '' ;
while ($i <= ($length - 1)) {
$num = rand() % 33;
$tmp = substr($chars, $num, 1);
$pass = $pass . $tmp;
$i++;
}
return $pass;
}
A refined version of Moob's post. Create a hash of the POST, save it as a session cookie, and compare hashes every session.
// Optionally Disable browser caching on "Back"
header( 'Cache-Control: no-store, no-cache, must-revalidate' );
header( 'Expires: Sun, 1 Jan 2000 12:00:00 GMT' );
header( 'Last-Modified: ' . gmdate('D, d M Y H:i:s') . 'GMT' );
$post_hash = md5( json_encode( $_POST ) );
if( session_start() )
{
$post_resubmitted = isset( $_SESSION[ 'post_hash' ] ) && $_SESSION[ 'post_hash' ] == $post_hash;
$_SESSION[ 'post_hash' ] = $post_hash;
session_write_close();
}
else
{
$post_resubmitted = false;
}
if ( $post_resubmitted ) {
// POST was resubmitted
}
else
{
// POST was submitted normally
}
Basically, you need to redirect out of that page but it still can make a problem while your internet slow (Redirect header from serverside)
Example of basic scenario :
Click on submit button twice
Way to solve
Client side
Disable submit button once client click on it
If you using Jquery : Jquery.one
PRG Pattern
Server side
Using differentiate based hashing timestamp / timestamp when request was sent.
Userequest tokens. When the main loads up assign a temporary request tocken which if repeated is ignored.
How to prevent php form resubmission without redirect. If you are using $_SESSION (after session_start) and a $_POST form, you can do something like this:
if ( !empty($_SESSION['act']) && !empty($_POST['act']) && $_POST['act'] == $_SESSION['act'] ) {
// do your stuff, save data into database, etc
}
In your html form put this:
<input type="hidden" id="act" name="act" value="<?php echo ( empty($_POST['act']) || $_POST['act']==2 )? 1 : 2; ?>">
<?php
if ( $_POST['act'] == $_SESSION['act'] ){
if ( empty( $_SESSION['act'] ) || $_SESSION['act'] == 2 ){
$_SESSION['act'] = 1;
} else {
$_SESSION['act'] = 2;
}
}
?>
So, every time when the form is submitted, a new act is generated, stored in session and compared with the post act.
Ps: if you are using an Get form, you can easily change all POST with GET and it works too.
The $_POST['submit'] variable would not exist on initial loading of page, and curl can be run only if below condition is true.
if($_POST['submit'] == "submit"){
// This is where you run the Curl code and display the output
$curl = curl_init();
//clear $post variables after posting
$_POST = array();
}
After inserting it to database, call unset() method to clear the data.
unset($_POST);
To prevent refresh data insertion, do a page redirection to same page or different page after record insert.
header('Location:'.$_SERVER['PHP_SELF']);
Using the Post/Redirect/Get pattern from Keverw answer is a good idea. However, you are not able to stay on your page (and I think this was what you were asking for?) In addition, it may sometimes fail:
If a web user refreshes before the initial submission has completed
because of server lag, resulting in a duplicate HTTP POST request in
certain user agents.
Another option would be to store in a session if text should be written to your SQL database like this:
if($_SERVER['REQUEST_METHOD'] != 'POST')
{
$_SESSION['writeSQL'] = true;
}
else
{
if(isset($_SESSION['writeSQL']) && $_SESSION['writeSQL'])
{
$_SESSION['writeSQL'] = false;
/* save $_POST values into SQL */
}
}
As others have said, it is not possible to out of using post/redirect/get. But at the same time it is quite easy to do what you want to do server side.
In your POST page you simply validate the user input but do not act on it, instead you copy it into a SESSION array. You then redirect back to the main submission page again. Your main submission page starts by checking to see if the SESSION array that you are using exists, and if so copy it into a local array and unset it. From there you can act on it.
This way you only do all your main work once, achieving what you want to do.
I searched for solution to prevent resubmission in a huge project afterwards.
The code highly works with $_GET and $_POST and I can't change the form elements behaviour without the risk of unforeseen bugs.
So, here is my code:
<!-- language: lang-php -->
<?php
// Very top of your code:
// Start session:
session_start();
// If Post Form Data send and no File Upload
if ( empty( $_FILES ) && ! empty( $_POST ) ) {
// Store Post Form Data in Session Variable
$_SESSION["POST"] = $_POST;
// Reload Page if there were no outputs
if ( ! headers_sent() ) {
// Build URL to reload with GET Parameters
// Change https to http if your site has no ssl
$location = "https://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
// Reload Page
header( "location: " . $location, true, 303 );
// Stop any further progress
die();
}
}
// Rebuilt POST Form Data from Session Variable
if ( isset( $_SESSION["POST"] ) ) {
$_POST = $_SESSION["POST"];
// Tell PHP that POST is sent
$_SERVER['REQUEST_METHOD'] = 'POST';
}
// Your code:
?><html>
<head>
<title>GET/POST Resubmit</title>
</head>
<body>
<h1>Forms:</h1>
<h2>GET Form:</h2>
<form action="index.php" method="get">
<input type="text" id="text_get" value="test text get" name="text_get"/>
<input type="submit" value="submit">
</form>
<h2>POST Form:</h2>
<form action="index.php" method="post">
<input type="text" id="text_post" value="test text post" name="text_post"/>
<input type="submit" value="submit">
</form>
<h2>POST Form with GET action:</h2>
<form action="index.php?text_get2=getwithpost" method="post">
<input type="text" id="text_post2" value="test text get post" name="text_post2"/>
<input type="submit" value="submit">
</form>
<h2>File Upload Form:</h2>
<form action="index.php" method="post" enctype="multipart/form-data">
<input type="file" id="file" name="file">
<input type="submit" value="submit">
</form>
<h1>Results:</h1>
<h2>GET Form Result:</h2>
<p>text_get: <?php echo $_GET["text_get"]; ?></p>
<h2>POST Form Result:</h2>
<p>text_post: <?php echo $_POST["text_post"]; ?></p>
<h2>POST Form with GET Result:</h2>
<p>text_get2: <?php echo $_GET["text_get2"]; ?></p>
<p>text_post2: <?php echo $_POST["text_post2"]; ?></p>
<h2>File Upload:</h2>
<p>file:
<pre><?php if ( ! empty( $_FILES ) ) {
echo print_r( $_FILES, true );
} ?></pre>
</p>
<p></p>
</body>
</html><?php
// Very Bottom of your code:
// Kill Post Form Data Session Variable, so User can reload the Page without sending post data twice
unset( $_SESSION["POST"] );
It only works to avoid the resubmit of $_POST, not $_GET. But this is the behaviour I need.
The resubmit issue doesn't work with file uploads!
What Works For Me is :
if ( !refreshed()) {
//Your Submit Here
if (isset( $_GET['refresh'])) {
setcookie("refresh",$_GET['refresh'], time() + (86400 * 5), "/");
}
}
}
function refreshed()
{
if (isset($_GET['refresh'])) {
$token = $_GET['refresh'];
if (isset($_COOKIE['refresh'])) {
if ($_COOKIE['refresh'] != $token) {
return false;
} else {
return true;
}
} else {
return false;
}
} else {
return false;
}
}
function createToken($length) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
?>
And in your Form
<form action="?refresh=<?php echo createToken(3)?>">
</form>
This form.php sample shows how to use PRG correct (when form is valid or not).
It redirects to the same page, only when form is valid and action was performed.
Redirection protects form from being resubmitted on page refresh.
It uses session to not loose success messages you want to show when form is valid.
There are two buttons for testing: "Valid submit", "Invalid submit". Try both and refresh page after that.
<?php
session_start();
function doSelfRedirect()
{
header('Location:'.$_SERVER['PHP_SELF']);
exit;
}
function setFlashMessage($msg)
{
$_SESSION['message'] = $msg;
}
function getFlashMessage()
{
if (!empty($_SESSION['message'])) {
$msg = $_SESSION['message'];
unset($_SESSION['message']);
} else {
$msg = null;
}
return $msg;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Validation primitive example.
if (empty($_POST['valid'])) {
$formIsValid = false;
setFlashMessage('Invalid form submit');
} else {
$formIsValid = true;
}
if ($formIsValid) {
// Perform any actions here.
// ...
// Cool!
setFlashMessage('Form is valid. Action performed.');
// Prevent form resubmission.
doSelfRedirect();
}
}
?>
<h1>Hello form</h1>
<?php if ($msg = getFlashMessage()): ?>
<div><?= $msg ?></div>
<?php endif; ?>
<form method="post">
<input type="text" name="foo" value="bar"><br><br>
<button type="submit" name="invalid" value="0">Invalid submit</button>
<button type="submit" name="valid" value="1">Valid submit</button>
</form>
if (($_SERVER['REQUEST_METHOD'] == 'POST') and (isset($_SESSION['uniq']))){
if($everything_fine){
unset($_SESSION['uniq']);
}
}
else{
$_SESSION['uniq'] = uniqid();
}
$everything_fine is the boolean result of form-validation. If the form is not validating then it shall be usually displayed again with a hint what to correct, so that the user can send it again. Therefore the $_SESSION['uniq'] is created again too if a corrected form is desired
Why not just use the $_POST['submit'] variable as a logical statement in order to save whatever is in the form. You can always redirect to the same page (In case they refresh, and when they hit go back in the browser, the submit post variable wouldn't be set anymore. Just make sure your submit button has a name and id of submit.
I know this is very simple thing but i am not aware of this. I have php code on same page for a signup form which have some session variables to be shown when any condition matches with the code.
The code structure is like this:
<?php
session_start();
if(isset($_POST['signup'])
{
if(condition)
{
$_SESSION['err1']="string";
}
else
{
$_SESSION['err2']="string";
}
}
?>
//HTML form
<?php if(isset($_SESSION['err1']) {?>
<li><?php echo $_SESSION['err1'];}?></li>
<?php if(isset($_SESSION['err2']) {?>
<li><?php echo $_SESSION['err2'];}?></li>
//rest of the form
I have more block of if-else in my code. Initially, when an condition is matched, the session message is shown. But as soon as the page refresh an another session message is shown along with previous session message.
Is this correct way of coding with forms? Because i want to show error messages inside the html form.
That's maybe because you do not empty your session variable.
Between 2 HTTP request, the session is kept on the server (juste reloading at each request).
So, if you are putting a message on $_SESSION['error1'] for the first call, it will show it. Then, on the second load, if you are putting a message on $_SESSION['error2'], you will also have the message of error1 because the session keep your data.
After showing the form, you should empty all your session messages
Simply unset your session variable after you echo.
<li><?php echo $_SESSION['err1'];} unset($_SESSION['err1']); ?></li>
This is really a bad example that use session to echo errors.
what i do many times at the starting of my php.
$errors = array(); // make a empty array errors before the conditional statements
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['Submit'])) {
//handle your POST variable
if(condition1){
$errors[] = "some error";
}
if(condition2) {
$errors[] = "some another error";
}
//more conditions
if (!empty($errors)) {
//process your form data if there is no errro
} else {
//display back your form along with Errors
if(isset($errors) && !empty($errors)) {
foreach($errors as $error) {
echo "<p class = 'error'>" . $error . "</p>";
}
}
<form action = "" method = "POST">
//your form elements
</form>
}
}
in first line of the php page, u can write
you can try any of the three lines between if condition
if(isset($_SESSION))
{
unset($_SESSION);
unregister($_SESSION['variable-name']) // try this also
session_destroy(); //try this also
}
Ive got this register script that puts the information into a mysql database. now it all works fine and when someone does something wrong its says the error (e.g. "Username not defined")
but when it goes wrong it does not look very good because it just displays the message on an empty page, so i thought i would make it redirect to the form page and display the message there.
here is the working script
$forename = $_POST['forename'];
$surname = $_POST['surname'];
$email = $_POST['email'];
$password = $_POST['password'];
$username = $_POST['username'];
$errors = array();
if(!$username) {
$errors[] = "Username is not defined";
}
if(!$password) {
$errors[] = "Password is not defined";
}
and it continues.
now i just thought i could do this
$errors = array();
if(!$username) {
$errors[] = header( 'Location: http://localhost/muiltabledistractions/#!/page_register_error-Username-is-not-defined' ) ;
}
if(!$password) {
$errors[] = "Password is not defined";
}
but no, all it does is ignore it.
could someone please help me
please feel free to ask for more of the script if you need it
many thanks connor
You cannot wrap a header in a array like that.
You just call the function, then it redirects.
header( 'Location: http://localhost/muiltabledistractions/#!/page_register_error-Username-is-not-defined' ) ;
it does not look very good because it just displays the message on an empty page,
What's the problem?
Why not to show the form again? with fields already filled.
This is going to be a user-friendly interface.
Just include your form in the same page with fields populated.
That's more common way than your redirects to blank form.
This is called POST/Redirect/GET pattern and here goes a short example of it:
the code
<?
if ($_SERVER['REQUEST_METHOD']=='POST') {
$err = array();
//performing all validations and raising corresponding errors
if (empty($_POST['name']) $err[] = "Username field is required";
if (empty($_POST['text']) $err[] = "Comments field is required";
if (!$err) {
// if no errors - saving data
// and then redirect:
header("Location: ".$_SERVER['PHP_SELF']);
exit;
} else {
// all field values should be escaped according to HTML standard
foreach ($_POST as $key => $val) {
$form[$key] = htmlspecialchars($val);
}
} else {
$form['name'] = $form['comments'] = '';
}
include 'form.tpl.php';
?>
the template
<? if ($err): ?>
<? foreach($err as $e): ?>
<div class="err"><?=$e?></div>
<? endforeach ?>
<? endif ?>
<form>
<input type="text" name="name" value="<?=$form['name']?>">
<textarea name="comments"><?=$form['comments']?></textarea>
<input type="submit">
</form>
You are placing the return value of the header function in an array, then continuing with your page execution.
If you don't care about anything that would normally happen below that redirection, which I believe is what you're implying, you should just set the header and then immediately exit. Do not try to place the return value of the header function into the errors array like that, as there's no point.
if(!$username) {
header('Location: http://localhost/muiltabledistractions/#!/page_register_error-Username-is-not-defined');
exit;
}
I don't if this is the problem, but it's important to include the status code in header too. Like:
header("Location: /foo.php",TRUE,302);
307 for Temporary Redirect, 302 for permanently moved. Chrome, a while ago, didn't accepted headers redirect without status code (i don't know nowadays).
try this after filling your error array:
if (count($errors) > 0)
{
header( 'Location: http://localhost/muiltabledistractions/#!/page_register_error-Username-is-not-defined' );
exit;
}
Keep in mind there should be no html output before this part!
<?php
if(isset($_POST['chgPwd']))
{
$oldpwd=$_POST["txtOldPassword"];
$newpwd=$_POST["txtNewPassword"];
$cnewpwd=$_POST["txtConfirmNewPassword"];
//did stuff to get in the text fields
$oldpass = oci_result($new1,"OLDPASS");
if($oldpwd!=$oldpass)
{
$msg = "The old password does not match with the one in the records";
header("Location:ErrorPage.php?abc=".$msg);
}
}
?>
My question here is that when i redirecting my page to the ErrorPage.php, I am able to see the entire page in the URL, which i do not want it to. Is there anyway around this. I am thinking of binding sessions, but i am unable to get it right. Could you please show me the right way if there is any?
You should urlencode($msg) ( string $str ) and perhaps add an exit() after header.
Edit: Well, you only want to see ErrorPage.php in your browsers URL, right? Without any message or attributes? Then you have to work with SESSIONS (or Cookies) to store the message/location for the current user and then to redirect him back to ErrorPage with the individual message.
Get rid of the error page and show your errors oncite.
Here is the sketch of the registration code
<?
include 'config.php';
if ($_SERVER['REQUEST_METHOD']=='POST') {
$err = array();
//performing all validations and raising corresponding errors
if (empty($_POST['name']) $err[] = "Username field is required";
if (empty($_POST['text']) $err[] = "Comments field is required";
if (!$err) {
// if no errors - saving data
// and then redirect:
header("Location: ".$_SERVER['PHP_SELF']);
exit;
} else {
// all field values should be escaped according to HTML standard
foreach ($_POST as $key => $val) {
$form[$key] = htmlspecialchars($val);
}
} else {
$form['name'] = $form['comments'] = '';
}
include 'form.tpl.php';
?>
and a template contains the form and the error mesages
<? if ($err): ?>
<? foreach($err as $e): ?>
<div class="err"><?=$e?></div>
<? endforeach ?>
<? endif ?>
<form>
<input type="text" name="name" value="<?=$form['name']?>">
<textarea name="comments"><?=$form['comments']?></textarea>
<input type="submit">
</form>
This is the most common way of form processing called POST/Redirect/GET
header("Location:ErrorPage.php?abc=1");
ErrorPage.php
if(isset($_GET['abc'])=="1")
{
Show Some Message
}
You can use sessions to hide that parameters. It's the simplest way.