I have buy.php with a form where you enter items, quantity, shipping data, etc.
When you click the Submit button, it posts back to buy.php ($_SERVER['PHP_SELF']) and does some data validation.
If there are fields missing or errors, they are highlighted. If everything is correct, I save the $_POST data in $_SESSION variables, then do a header('Location: check.php'), where I display the data so the buyer can check the info one last time before actually buying.
Now, if I'm in check.php and hit the Back button to buy.php so I can change stuff, the browser asks if I want to resend the POST data. I'm trying to avoid that.
Anyone have any good advice or good practices for PHP Multiform validation?
Also, if I had n pages for the user to fill, buy.php, buy2.php, ... buyn.php before check.php would the same ideas still hold?
You could do a redirect to buy.php after saving to the session object, which then does a server redirect to check.php, it would mean when the user clicks back, they're going back to the GET request not the POST request
Yes - I agree with above. I ALWAYS do a redir away from the last post, so clicking back bounces them back without that error OR re-submissions. it also avoids complications. u can always tag the redir link page with a ?m or &m (i.e.: page.php?m) and have this at top of page: (use elseif there after)
if (isset($_GET['m'])) {
echo 'order placed.';
}
else {
//...
}
You can have it all on one page too. Just name the submit buttons submit1, submit2, like: (bear in mind if you use an image for submits, it becomes $_POST['submit1_x'] :)
if (isset($_POST[submit1]) {
//validate + save session data from form1
//display form 2
} else if(isset($_POST[submit2])) {
//validate + save session data from form2
//display form 3
} else {
//display first form
//<input type="submit" name="submit1" value="Continue">
}
Related
I have two simple HTML form buttons that call PHP functions to send emails now. Everything works fine except for one thing. If one of the buttons is clicked to send a report, and then the page is refreshed, the function seemed to be called again and the emails well go out again with a page refresh by a user using a browser refresh button.
If the page is refreshed, the email will go out again for the last button clicked. So, if I click on Button 1 and then refresh the page, I will get two reports for button 1. If I click on button #1, and then click on Button #2, only the second report will go out. If I click on button #2 and then #1, only Report #1 will go out again.
So, no matter how many buttons are clicked, refreshing the page will cause the last button click (only to repeat). Trying to unset the request parameter (in code below) has no effect all on the repeats caused by a page refresh.
I don't understand why (on a Page Refresh) the page is seeing the last button click made as set, and why the unset command is not working.
Thanks for any help.
if( isset( $_REQUEST['email_this_weeks_report'] )) {
unset($_REQUEST['email_last_weeks_report']);
#send email now email code for this week
}
if( isset( $_REQUEST['email_last_weeks_report'] )) {
unset($_REQUEST['email_last_weeks_report']);
#send email now email code for last week
}
<form>
<input class="ui-button ui-widget ui-corner-all" type="submit"
name="email_this_weeks_report" value="Email This Weeks Report Now" />
</form>
<form>
<input class="ui-button ui-widget ui-corner-all" type="submit"
name="email_last_weeks_report" value="Email Last Weeks Report Now" />
</form>
Clicking the button submits the form.
The data in the form is bundled up and included in the request.
Aside: You're using method=GET, the default, but you're not making a "safe" request. You are doing something, not just getting information. You should use a POST request.
When you click refresh, you tell the browser to make the request again and display a new version of the page.
Since the request includes the query string which says "send a particular email", it sends that email again.
Unsetting values in $_REQUEST has no effect because when the browser makes a new request with the same data in it: $_REQUEST just gets filled up again.
You should deal with this by using the PRG pattern:
Submit the form using method=POST
Have your PHP script process the data in the form (i.e. send the email) then redirect to a different PHP script
Have the new PHP script display the result (in this case there is no result, its just the form, you could use a plain HTML document with no PHP in it).
Change
<form>
To
<form method='POST'>
A simple way to prevent multiple submissions is to add a random token to the form in a hidden input.
<input type='hidden' name='formtoken' value='<?= uniqueid() ?>'/>
Every time the page is fetched from the server, the value of this hidden variable will change. So on the server side, you can prevent the same form being resubmitted by checking whether a form with this unique ID has been submitted before.
session_start();
$sessionToken = $_SESSION['formtoken']? : null;
$currentToken = $_POST['formtoken']? : null;
// If no session token yet: form has never been submitted
if(!$sessionToken):
// save the current token in session so we'll recognize it next time
$_SESSION['formtoken'] = $currentToken;
/* ok to send the email */
// ElseIf current token was already used: Duplicate form submission
elseif($sessionToken === $currentToken):
/* don't send the email!*/
// Else session token exists, but current token is new: User fetched a new form from server
else:
// update the session token
$_SESSION['formtoken'] = $currentToken;
/* ok to send the email */
endif;
When the user refreshes, the browser will ask if she wants to re-submit the form. If she does, you will know because the current token and the session token will be the same. It's up to you to decide how to handle it.
Refreshing a page with a GET or a POST form will resubmit the data (albeit it will ask you first in the POST scenario, which you should use by the way).
Try redirecting the user after form submit
if( isset(...) ){
// Do your logic
header('Location: https://you_site.com/your-form-page?thank-you');
exit;
}
This must be done before anything else is outputted on the page.
This question already has answers here:
Avoid resending forms on php pages
(6 answers)
Closed 9 years ago.
I have a webpage that contains a form that uses the POST method and references the same page it is on for submission. I am using a PHP include file that contains an if statement that runs when the submit value is set. For some reason though, after one submission, every time you refresh the page it submits the form with the previously submitted data (The browser warns of this before refreshing the page). What causes this, and what could I be doing wrong?
This is expected. You should have the form submit to a handler that has a unique URL, whether it be a query string or a different URI. One solution (of many) would be to change your form action:
<form action="?action=submit" method="post">
<input type="hidden" name="action" value="submit" />
...
and then in the PHP script handle the form, then change the context back to a URL without the hidden query string
if (!empty($_POST['action']) && $_POST['action'] == 'submit') {
// do stuff
header('Location: '.$_SERVER['SCRIPT_NAME']);
die();
}
Note the query string is not actually present in $_POST but we keep it there so browsers don't consider it to be a redirect loop.
i had the same issue with one of my pages.
the reason is that when the browser warns you that it will submit the form again, that means it is going yo be the same exact thing when you click on a submit button.
I did 2 things to avoid it but i am sure there many other ways.
1. Do not let the page echo the form again after succesfull submission of the form.
mine was like this
<?php
if(!isset($_POST['submit'])) {
include(form.php);// you can modify this according to your needs.
} else {
//display your message about what happened with the form.
}
?>
with that approach, your page will not the contaion a form to submit HOWEVER this will not prevent it from submitting on refresh.
2. if the form is submitted create a contoller input that carries a value indication that the form is already submitted. for example , place this into your form:
<?=(isset($_POST['submit']))?"" :"<input type-"hidden" name="submit_stat" value="true" />" ; ?>
and when you process your form when it is submitted check it with your php and make the script act on that variable like this:
<?php
if($_POST['submit_stat']==true) {
//do not process the form here.
//stop your script
}
?>
Another thing you can do is redirect your page to another page other than the page that handles the form. i believe this is the safest one.
Another Way to prevent this is to move the Post Data to Session, redirect, collect Post back from Session and delete Session Post Data.
if(!empty($_POST) && empty($_FILES)){
// move post to session
// redirect to same url (don't forget possible get query)
}else{
// collect post from session
// unset post from session
}
Build this as default and you should never have problems with post data.
Only exceptions are File uploads. In this case redirect *after* post processing manualy.
I am making a page that has a bunch of fields that allows the user to enter in information and submit it to a database. This page is called 'add.php' I created a 'form' tag and had the information posted to another page called 'process.php' where the information is collected, then inserted into the database. I want the user to know whether it was successful or not, so I was wondering how to tell the user something specific on the 'add.php' page. like "insertion successful!" at the top of the page.
I thought of including the 'process.php' code in 'add.php', then calling the 'add.php' in the action of the form, but the code gets called the first time the page is loaded, which inserts a completely blank entry into the database.
Should I implement some sort of flag that is only set to true after the 'submit' button is clicked? Or is there another way to update the page and tell the user the status of the insertion?
I can paste the relevant code as needed. :)
Thanks!
Assuming that you are using the post method in your form and php, you can simply check if a post was made:
if ($_SERVER['REQUEST_METHOD'] === 'POST')
{
// form was posted, process and display output
}
else
{
// nothing was posted, normal get request, show form
}
just check if query worked well. If no exception was thrown, it mostly has, and the add appropriate message with output.
First you need to check and handle errors
try
{
}
catch(Exception $e){
header('Location:oldlocation.php?succ=0')
exit();
}
header('Location:oldlocation.php?succ=0')
exit();
If all goes well, you can also redirect to a new location(as shown in code). This has to be done properly, you may redirect back to the old location, with additional data like
oldlocation.php?succ=1;
If anything goes wrong redirect to
oldlocation.php?succ=0
Then fetch the succ using $_GET["succ"] and print appropriate message.
If you din get, comment.
Here's what I would do...
Keep your processing data in one file, and include the form file at the end
//add.php
//if the form is submitted make the database entry
if(isset($_POST['foo']) AND $_POST['foo'] != '')
{
//code to process form submission
$success = 'success!';
}
//include the form
include addform.php
in addform.php put your form. Include an 'isset' that is watching for $success to alert that the entry was successful
//addform.php
<?php if(isset($success)){ echo "<h2> Data successfully entered! </h2>";} ?>
<form action='' method='POST'>
<input type='text' name='foo' />
//etc
</form>
So once you submit the form, the code starts at the top of add.php - the 'isset' sees the $_POST submission, runs the form submission code and sets the success variable. Then, it includes the form page. The form page has an 'isset' that is watching for the success variable. When you first navigate to the page, or if you refresh, the add.php code will skip the first code block (the form submission stuff) and won't make a database submission or set the success variable.
I have a form in page1.php which directs to page2.php from where the data from the form in page1.php is inserted into database. after successful insertion, page2.php displays a message and gives link to go to a third page.
The problem is when the user after the insertion hits the back button of the browser and clicks the form submit button, insertion is made again.
Is there any way so that after one insertion when the back button is pressed a message will be displayed showing that visiting the back-button is not allowed? Or in case it is allowed no insertion will take place on clicking the form submit button?
EDITED LATER TO ADD THIS PART:
okk let me tell in details. it is about an admin back end. the admin gives description text input for different products. He gives the input from page1.php and message is shown on page2.php that the description has been inserted into db. then there is another form below the message. It just asks whether the admin wishes to do more with description text. If yes, then clicking on the form submit button , he is taken to a page from where across some page(s) he is again taken to page1.php ( this time for another product), from there to page2.php and so on. btw i could use a normal page link instead of the form button link below the message on page2.php
The problem is, while the admin is on page2.php and hits the back button , he goes back to page1.php and from there if he hits on the form submit button, the data is inserted for the second time in a new row.
u may suggest to use 'IGNORE' with 'INSERT' command, but there are other columns in the row which may not get matched with those of another column while the description columns(admin inserts text data for this column ) may get matched.
1)Is ignore applicable in this case?
2)What should be the solution if duplicate entry is allowed for the database of the site?
thanks
hope it makes the whole thing clear.
Instead of giving link to a third page, redirect to the very same URI
this is quite handy method called POST/Redirect/GET:
here is a concise example of it:
<?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 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';
?>
Here you can see another example, concise yet powerful:
Separating Logic/Style in PHP properly
it's complete solution to display, add and edit database contents, exactly for admin purpose.
You should not display your message on page2.php.
Instead :
page2.php should deal with the data
when the data has been saved, page2.php should redirect to confirmation.php
And it's only confirmation.php which would display the message.
For more informations, take a look at the Post/Redirect/Get pattern.
Edit after the comment : but note that, in any case, you will never be able to prevent the user from re-submitting a form, if he really wants to...
The only solution you'll have is, when a form is submitted, to check in your database if the currently submitted data already exists -- and if it does, refuse to insert it again.
Of course, if the suer changes even a single letter in his input, it won't be the same data anymore...
I have an HTML form. Let's say I fill out all the fields and submit it (PHP script runs here).
Then I want to go back to the form using "Back" button of my browser.
What I see is the empty form.
What do I do to have the entered data retain on the page after I come back to it using "Back" button of the browser?
Thank you!
If you use the "Back" button of your browser then your browser is responsible for re-populating your form data.
Usually that functionality is handled by the browser, however if you want to "force" the fields to always be pre-filled with the user's data, you can store the $_POST data in a session variable and use that to load the form.
Example:
// submission page
session_start();
if(isset($_POST)){
// save the posted data in the session
$_SESSION["POST"] = $_POST;
}
Then on the actual form page, you can check to see if session data exists. It won't if the form is being loaded the first time, but it will if the user submits the form and then presses the browser back button:
// form page
session_start();
if(isset($_SESSION["POST"])){
// previous POST data has been saved
// build the form with pre-defined values from $_SESSION
...
} else {
// no previous data
// build the form without pre-defined values
...
}
Note that you must call session_start() before outputting any HTML.
Store the value in a session
session_start();
//form so that you have all the potential forms in a single session array
//form_1 to identify the form in question
if(!empty($_POST)){
$_SESSION['forms']['form_1'] = $_POST;//if this is for the public internet, then I would really consider making sure that the posted data matches the received data... (and that its comming from YOUR form), which is way too long to post here...
}
then on the form page
<input name="flowers" value="<?php echo if(isset($_SESSION['forms']['forms_1']['flowers'])){ echo htmlspecialchars($_SESSION['forms']['forms_1']['flowers']);} ?>" />
obviously the above can be simplified, but for a example's sake it's better this way.
(make sure to clean out the old form data eventually)
You can potentially store the data in the session, and re-populate it back using PHP sessions. You should create a separate back button that takes you to the previous page.
Example:
Storing data:
$_SESSION['data'] = $_POST['item1'];
In the HTML Forms:
<input type="text" name="someinput" value="<?=$_SESSION['data']?>" />