I want to ask a best practice question.
Suppose I have a form in php with 3 fields say name, email and comment.
I submit the form via POST. In PHP I try and insert the date into the database.
Suppose the insertion fails.
I should now show the user an error and display the form filled in with the data he previously inserted so he can correct his error. Showing the form in it's initial state won't do.
So I display the form and the 3 fields are now filled in from PHP with echo or such. Now if I click refresh I get a message saying "Are you sure you want to resend information?".
OK.
Suppose after I insert the data I don't carry on but I redirect to the same page but with the necessary parameters in the query string. This makes the message go away but I have to carry 3 parameters in the query string.
So my question is:
How is it better to do this? I want to not carry around lots of parameters in the query string but also not get that error. How can this be done? Should I use cookies to store the form information.
Your first scenario seems the most valid.
i.e.
User submits the form
Some problem prevents submission, so form is re-displayed
If user "refreshes" they see the usual message about re-sending information (although their most likely path of progression is to re-submit the form that you are kindly re-populating for them).
The "Are you sure you want to resend information?" message is perfectly valid in the event of someone refreshing the page after a form submission, so don't write code to specifically break this behaviour.
I think generally people would temporarily store the submitted data in a session variable, and send the data back to the client.
Maybe it is besides the point but you mentioned "wrong dates", and I think many would say you should arrange things so that the user cannot unintentionally send you wrong dates.
Related
Further to my previous question, here's what I decided to implement; it may not be pure P-R-G, but it seems ok. Care to comment?
The form.php has an action; let's call it validate.php.
validate.php is never seen by the user; if validates all $_GET and, if valid writes it to database and generates the HTML of a confirmation page / if not valid, it generates the HTML of an error page explaining what is wrong.
Whichever HTML is generated get stored in a $_SESSION variable and then validate.php does a header('Location: <as appropriate>);
Finally a page called submitted.php of invalid_input.php (in case the user reads the URL) consists only of echo $_SESSION['form_html'];
That seems to me like is proff against both page reload and back button problems.
Or did I goof by trying to reinvent the wheel?
Firstly, you're better off storing the form data, which means you can perform the validation again. It will also be less html. The problem with the method you're employing now is that it doesn't protect against multiple tabs, since $_SESSION is universal to a browser session.
One way I've used to prevent against duplicate submission (without PRG) is to generate a unique id for every page load (where a form is involved). When I generate that unique id, I add it to a $_SESSION['form_unique_ids'] array, and I include it as a hidden field in every form I generate. Then before I take action on a form submission, I check to see if that unique id is in the session. If it is, this is the first time that form has been submitted, and I remove it from the session. That way if I try to resubmit that page, I will know because that id is not in the session not to process the results.
This could be extended so that instead of storing a single id, you use the id as the key in the array, and let the value be the result of the transaction. Then:
If there are errors, you store the $_POST data as well. Then, redirect to original_form.php?id=unique_id and display the validation results. You can either store them or recalculate them there.
If there is success, store the success message and redirect to success_page.php?id=unique_id. Display the success message prominently there. If you like, you can remove it from the page.
You have the option of removing the session data when you display it, but that would mean if they refreshed the edit page they'd lose the validation messages and saved form data. I'd rather find a way to get rid of data that is old enough that they're not likely to need it anymore.
Anyway, some of those ideas might be useful. Then again, maybe it's way too much effort for the problem. Your call :)
As long as you use a php redirect at the end of your validate you cannot reload or back button into the validate.php
I have a form that the user needs to populate and then the form will be sent to a server.
After the user submits the form, if the server script found that the form is not correctly populated (i.e. the uploading file is too big), it should return error to the client side.
Now, my question is as follows:
How do I keep the user seeing the same page without transferring to a different page?
Because I don't want the user to waste time to reenter everything again. I just want the user to correct the wrong part.
Because I don't want the user to waste
time to reenter everything again. I
just want the user to correct the
wrong part.
This is a good intention, but the wrong solution.
To stay on the same page would mean you have to submit the form using javascript. While possible, why make things more complicated than they have to be?
Instead, submit the form to the server and when you write out the form again to the user with the error message, set what the user entered as the default value on the form. Then it will be there for them and they won't have to type it again.
Note: Don't do this for passwords tho; the page may be cached and then the users password is saved in a plain file on the hard disk. This is why most sites make users retype passwords each time.
You need to show form again and fill previously entered data in input's "value" fields. Of course, don't forget to replace special characters with html entities with htmlentities();
I also found one tutorial for you: http://evolt.org/node/60144
I'm currently developing a page where the user fills out a form, and when submitted they are taken to the next page. When on the next page, I want to have it so that if the user went back to the previous page using the back button, or hit refresh, the submission will not be saved into the DB.
Now I recall reading somewhere that if you had a way to make each submission unique, this issue is averted, but after screwing around for hours on end, for the life of me I cannot recall how this could be done (using PHP), so long story short has anyone ran into this, and if so, what was your solution?
Use the Post/Redirect/Get pattern to avoid this problem. See also Redirect After Post.
Another way is to generate an identifier using uniqid and include it in the form as a hidden input. On submission, store that identifier in a database column marked with a UNIQUE index. This will cause subsequent submissions to throw a SQL error, which your application can handle gracefully.
You can add any confirmation on the second page.
By adding any confirmation box or any button....
by which you can confirm that whether user want to save it or not....
and if you don't want any confirmation...then you can delete the last record....by using managing session...but it is not good practice to fire the query very soon and delete in that kind..
so best way will be by adding any confirmation msg....
On my site, I have a form that users fill out to become a member. They fill out name, bday, email, etc. Then when they click submit, the data gets into mySQL. But sometimes when a user clicks submit many times or refreshes the page, the data gets inputted to the database more than once. How can I prevent this accidental submission? Is there a code I can use to only let one set of data get into the database?
This is also a problem in my comment section. I allow uses to put comments on people's profiles. But when they abuse the refresh button or submit button, I get like 10 of the same comments. I am trying to prevent users accidentally submitting a comment twice.
Thanks.
Create a UNIQUE constraint:
CREATE UNIQUE INDEX name_of_youw_index ON tablename(columnname);
INSERTs will now fail with double data.
In the first case you probably just want to add a unique index on the email address and use that to create a profile for that user.
In the second case, as I understand it, you are trying to prevent users from accidentally submitting data twice, not to completely prevent data being submitted twice. You probably don't want to prevent people from writing the same comment twice on the same page. If someone writes "Today was like yesterday!", you don't want to prevent them from coming back the next day and writing "Today was like yesterday!" again. This would be unnatural and the check could be expensive as it would require indexing a lot of data. I think you want to prevent someone from submitting the same form twice, regardless of whether the data is the same or not.
So the solution to your second example is to include a hidden field in your form that uniquely identifies it. When they submit the form, mark the value in the hidden field as used. If someone later submits a form with the same value in the hidden field, reject it.
Server-side: Implement throttling. Only allow 1 submission every 10 seconds or so.
Update: When you accept a form submission, record the timestamp you
made the submission in $_SESSION.
When you accept another (or rather,
every) form submission, check if the
value stored in $_SESSION is older
than 10 seconds. If it is, continue.
If it isn't, don't do any more work.
You could do it with just some
database stuff to I guess, but
$_SESSION is much simpler.
Client-side: Disable the submit button via Javascript when the form is submitted.
Make the email field in your database "unique", by adding a unique index to it.
If your database gets another entry with an email which has already been used then mysql throws an error - the error number is 1062.
If you wanted to then you could handle this error different from others.
mysql_errno()
http://www.php.net/manual/en/function.mysql-errno.php
In the case of the database duplicates, put a unique constraint on the field.
For both the database duplicates and the duplicate comments, disable the submit button for 2-3 seconds after it is pressed to prevent multiple submits.
Im trying my first form validation with PHP.
I need some guidance with the logic.
I have purchase.php (which has the form) and review-purchase.php(which sets SESSION variables and displays the user data inputted)
If any of the fields fail validation I don't want the user to get to review-purchase.php
Should I be sending the user to the review-purchase.php script, checking validation there and then redirecting back the purchase.php with an error message?
or
should I be using an if/else statement with $_SERVER['php_self'] etc in the form action="" and keep all the validation on the purchase.php page itself and only letting purchase-review run if everything passes validation?
Sorry for the confusing question but i myself am very confused...
That's a question many people ask themselves, and there is probably not one right answer...
What I generally do, in your case, is :
purchase.php displays the form
that form posts on itself (ie, purchase.php)
when data has been submitted, it is dealt with -- still in purchase.php
if there is an error (like something not OK in the input), you can re-display the form really easily, this way : you already have every values that were typed in by the user
if there is no error, you can do whatever you have to with the data ; like set it in session, if that's what you need, or save it to database, for instance.
only when everything was OK (data validation OK and storage OK), you redirect to "confirm.php"
that confirmation page does nothing except display a message saying "thanks for your purchase", or something like that.
It means putting more stuff in your purchase.php, yes :
(re-)displaying of the form
dealing with the input
But, this way, it is really easier to re-display the form, pre-filled with what the use first typed, when there's a validation error.
You can use functions/classes/methods or even some included files, though, to not end up with one big chunk of un-readable / un-maintenable code...
If your form posts to another page, it'll be really harder to re-display the form... If you are using redirections, you'll to pass everything in the URL, and it'll be a mess (And there's a size limit, too)
Here, it means I would totaly remove your review-purchase.php file ; and transform it to a confirmation page, so the user knows everything was OK and his purchase is being take care of.
I suppose it's quite what you meant in your last paragraph, actually :-)
Just beware : you have to think about escaping data before injecting it back into the form (see htmlspecialchars and/or htmlentities) ; that is true for everything you get from the user (And, probably, for PHP_SELF too, I'd say) ;-)
Well, it seems you have a misconception about where and when PHP code is executed. If you want to validate user input on the server side - with PHP (and you should because any JavaScript validation on the client can be worked around by a nefarious user) - the PHP validation can only occur after the user has posted data. That is no matter to which page the user posts the data - be it the original form or a different page.
So, in your situation if you want users to go to a page if validation is successful and to a different page is validation fails yo will need to do a redirect anyway.
In this case you have two paths:
user requests Purchase.php and fills out the form
user posts data to validation page
if data is valid -> display purchase review information
else -> re-display form page and have user re-enter data
So if Purchase.php posts to itself, you can validate there and redirect to review.php only if data is valid. Which means that in the successful case you do 2 redirects and in the failed case you do only 1 post.
On the other hand, if you post directly to review.php and you validate there, you have 1 post in the successful case, and 2 in the failed case.
The above is true no matter how you spin it - unless you use the same URL for the form and the review, in which case you can put logic in the same place to do the form, validation and purchase review in the successful case.
I hope this helps.
The most common way of doing this would be to do all your validation checks in purchase.php. This way, if there are validation errors, it's easier to re-display the form with all of the information that the user has already entered.
If the validation passes, you can do a redirect to review-purchase.php with the necessary purchase information set in a database, or possibly $_SESSION if you're not using a database.
If you can separate the validation code into functions, and the display code into templates to be included, you can achieve a nice separation of logic that would allow you to use them from whichever file you go with. You might be able to avoid a redirect in that way, ie. in purchase.php you could check if there's $_POST input, validate it, and either re-display the form template, or display the purchase review template.