PHP form validation doesn't work - php

I'm all new to PHP and JavaScript, just learning web development and I'm trying all sort of things in my free time, however, there is one thing I cannot find a solution for.
I have a form that would be collecting only 4 datas, Name, Date of Birth, Email and Phone number. All fields are required for further data procession. I literally tried every single thing I found on Google, but it still doesn't work. The form simply saves all sort of data into the database, without checking the input fields.
Later on I'd like the code to validate the form, display any errors on the same page not on a different ".php" one and also send 2 emails one as a confirmation for the person and one for notifying me about a form submission. What should I do/change to achieve that? I feel quite stuck atm.
my form:
<form class="contactform" id="cfrm" action="process.php" method="post">
<div class="f-data">
<input class="f-error" name="uname" placeholder="NAME" type="text" required="required" data-error="Name is required.">
</div>
<div class="clear"></div>
<div class="f-data">
<select name="birthday" id="forminput" aria-required="true" aria-invalid="false">
<option value="11">11</option>
<option value="12">12</option>
</select>
<select name="birthyear" id="forminput" aria-required="true">
<option value="1900" selected="selected">1900</option>
<option value="2001">2001</option>
</select>
</div>
<div class="f-data">
<input class="f-error" name="uemail" placeholder="EMAIL" type="text" required="required" data-error="Email is required.">
</div>
<div class="f-data">
<input class="f-error" name="uphone" placeholder="PHONE" type="text" required="required" data-error="Phone is required.">
</div>
<div class="clear"></div>
<div class="submit">
<p>
<input type="submit" value="submit" name="submit">
</p>
</div>
and the process.php
<?php
require "connection.php";
require "others/phpmailer/PHPMailerAutoload.php";
//form data
$connection = mysqli_connect($dbhost,$dbuser,$dbpass,$dbname);
$Name = $connection->real_escape_string($_POST['uname']);
$DoB = $connection->real_escape_string($_POST['birthyear'] . '-' .
$_POST['birthmonth'] . '-' . $_POST['birthday']);
$inputDoB = date("Y-m-d",strtotime($DoB));
$Email = $connection->real_escape_string($_POST['uemail']);
$Phone = $connection->real_escape_string($_POST['uphone']);
if (strlen($agree) == 0) $agree = 0;
// validating
if(isset($_POST['submit']));
{
if(empty($_POST['uname']))
{
$msg_name = "You must enter name";
$name_subject = $_POST['uname'];
$name_pattern = '/^[a-zA-Z ]*$/';
preg_match($name_pattern, $name_subject, $name_matches);
if(!$name_matches[0])
$msg2_name = "Only alphabets and white space allowed";
}
if(empty($_POST['uemail']))
{
$msg_email = "You must enter your email";
$email_subject = $_POST['uemail'];
$email_pattern = '/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/';
preg_match($email_pattern, $email_subject, $email_matches);
if(!$email_matches[0]) $msg2_email = "Must be a valid email address";
}
if($_POST['uphone'])
{
$phone = $_POST['uphone'];
preg_match('/^[_a-z0-9-]+(.[_a-z0-9-]+)*#[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z {2,3})$/i', $phone, $phone_match);
if(!$phone_match[0]) $msg_phone = "Must be a valid phone number";
if(strlen($phone)!='8') $msg2_phone = "Must be at least 8 characters long";
}
}
//save to db
$query = "INSERT INTO form (Name,DoB,Email,Phone,Date) VALUES ('$Name','$DoB','$Email','$Phone', CURRENT_TIMESTAMP)";
$success = $connection->query($query);
if (!$success) {
die("Couldn't enter data: ".$connection->error);
}
echo "Thank You For Contacting Us";
?>

As for your display of inline error messages, what I would recommend doing is only making use of one page to handle the main form 'logic', and another include() to represent the raw HTML markup fo the form itself. The 'logic' page would be where you direct your visitors as the 'form'.
Inside of your if(isset($_POST['submit'])), you would check the data that is submitted. If it is valid, you go ahead and process the submission. If it is invalid, you raise an error, and show the form again. The form is also shown by default.
This is shown in the following semi-pseudocode:
$error = ''; // Nothing is wrong at first
if(isset($_POST['submit'])) {
// Raise error messages based on submission
if(empty($_POST['uname'])) {
$error = "You must enter name";
}
if(empty($_POST['email'])) {
$error = "You must enter email";
}
// Show the form if there are errors
if ($error) {
include('form.php');
}
// Process the submission if there aren't
else {
//$query = ...
mail($Email, $email_subject, $msg_email);
}
}
else {
include('form.php');
}
With form.php conditionally checking for $error:
<?php
if ($error !== '') {
// Output the error message in a fancy way
echo "<span class='error'>" . $error . "</span>";
}
?>
<form> ... </form>
As for sending the two emails, you're practically there! You already have $msg_email, $email_subject and $Email. You're just looking to make use of PHP's mail() function:
mail($Email, $email_subject, $msg_email);
Note that you'll probably want to add the fourth parameter (headers) in there as well.
I also note that you currently have a semicolon in if(isset($_POST['submit']));{, which will prevent the block from triggering. Make sure you remove this.
Hope this helps! :)

While formatting your code for question clarity I think I found the issue.
You have 2 formatting issues that would cause this sort of issue.
1) You have a semicolon preventing your if from being a block conditional
if(isset($_POST['submit']));
with that semicolon there the block will run separated and simply act as a scope separator.
2) Your Regex isn't complete
preg_match('/^[_a-z0-9-]+(.[_a-z0-9-]+)*#[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z {2,3})$/i', $phone, $phone_match);
In your last capture group (.[a-z {2,3}) you don't have a closing square bracket for the [a-z] character selector it should be (.[a-z]{2,3})
I would also point out that you are setting$msg_name and $msg2_name but I don't see them used anywhere and you don't stop execution on error so the process just continues through to the query even though you said you want it to stop.

Related

How to pass and put variable from a php page into a another page(form)?

I working on two pages, a first one which has a form with three fields: name, email and message). This page will send these data to a second page, that will validate if those fields meet the criteria.
If on the second page, any of those fields does not meet the criteria, I want to redirect to the first page (or a third php one), fill the form with previous information and tell the user to correct the fields properly.
I'm strugling to send the data form the second page to the first (or third) one. Does anyone knows a good way to do it?
Here's my code:
First page - contato.html
<form action="validate.php" method="POST" name="emailform">
<div class="form-group">
<input type="text" id="name" name="nome" placeholder="Type your name">
</div>
<div class="form-group">
<input type="text" id="email" name="email" placeholder="type your#email.com here">
</div>
<div class="form-group">
<textarea class="form-control" cols="30" rows="10" maxlength="300" id="message" name="mensagem" placeholder="Leave your message." ></textarea>
</div>
<div class="form-group">
<input type="submit" name="submit" value="Send message" onclick="alert('Thank you!')" ></form>
Second Page - validate.php
if(isset($_POST['nome'])) $nome = $_POST['nome'];
if(isset($_POST['email'])) $email_visitante = $_POST['email'];
if(isset($_POST['mensagem'])) $mensagem = $_POST['mensagem'];
// if does not meet the criteria, redirect to contato.html and update the form with the info
if(empty($nome)){
Header("location:contato.html");
}
if(empty($email_visitante)){
Header("location:contato.html");
}
if(empty($mensagem)){
Header("location:contato.html");
}
// check for letters and space only
if (!preg_match("/^[a-zA-Z ]*$/",$nome)) {
Header("location:contato.html");
}
// check if e-mail address is well-formed
if (!filter_var($email_visitante, FILTER_VALIDATE_EMAIL)) {
Header("location:contato.php");
}
Does anyone knows how to do it? Either sending to a third page or redirecting to the first one (and fill the form in again)
You have to use sessions and store data there in one page and access in another, here is a small usage
<?php
// page 1
session_start();
// Set session variables
$_SESSION["nome"] = $nome;
$_SESSION["email"] = $email_visitante;
$_SESSION["mensagem"] = $mensagem;
<?php
// page 2|3|N - any other page
session_start();
// Get session variables
$nome = $_SESSION["nome"];
$email_visitante = $_SESSION["email"];
$mensagem = $_SESSION["mensagem"];
Part of your problem is that upon any failed validation you are using a redirect. Alternatively you can display an error message to the user: suggesting they need to correct their input by going back a page (browser back).
When forms get longer users need some hand holding with error correction. Their errors need to be clearly indicated with a message alongside as to how they can fix it.
Avoiding using the 'browser back' method above it's common to have the form send to its own url. I've included an example below.
By doing this you can repopulate the form with posted values upon error and add error feedback. You must be careful to escape user input in this situation.
I've added a generic error feedback notice. Which isn't that helpful in its current form. You could improve upon this by adjusting the validation code to return an array of error notices and use that within your form for more targeted error feedback. You could also add - all fields are required - text to help the user.
Upon successful validation that's when to redirect the user to a confirmation page. This can prevent form resubmissions.
Your name regex pattern in its current form will not allow hyphens or apostrophes. I haven't changed it below. Do bear this in mind. "Michael O'leary" would be faced with an error and likely not understand why. You need to be careful when using strict rules for user input. Also this will reject some unicode.
You also need to escape user input appropriately. Note that you may be satisfied that the name and email after validation follows a particular pattern, but becareful of raw user input. The message text is passed on raw after validation.
<?php
$nome = $_POST['nome'] ?? null;
$email_visitante = $_POST['email'] ?? null;
$mensagem = $_POST['mensagem'] ?? null;
$feedback = null;
if(isset($_POST['submit'])) {
if(validate($nome, $email_visitante, $mensagem) !== false) {
process($nome, $email_visitante, $mensagem);
// Redirect to success/thankyou/confirmation page.
header('location:success.html');
exit;
}
// This is a generic message, could this be more helpful?
$feedback = 'Your form has errors. Please correct them.';
}
form($nome, $email_visitante, $mensagem, $feedback);
function process($nome, $email_visitante, $mensagem) {
// do something with your values.
}
function validate($nome, $email_visitante, $mensagem) {
if(empty($nome)) {
return false;
}
if(empty($email_visitante)){
return false;
}
if(empty($mensagem)){
return false;
}
if (!preg_match("/^[a-zA-Z ]*$/",$nome)) {
return false;
}
if (!filter_var($email_visitante, FILTER_VALIDATE_EMAIL)) {
return false;
}
return true;
}
function form($nome = null, $email_visitante = null, $mensagem = null, $feedback = null) {
?>
<?= $feedback ?>
<form action='' method='POST' name='emailform'>
<div class='form-group'>
<label for='name'>Your name:</label>
<input type='text' id='name' name='nome' value='<?= htmlspecialchars($nome) ?>'>
</div>
<div class='form-group'>
<label for='email'>Your email address:</label>
<input type='text' id='email' name='email' value='<?= htmlspecialchars($email_visitante) ?>'>
</div>
<div class='form-group'>
<label for='message'>Your message:</label>
<textarea class='form-control' cols='30' rows='10' maxlength='300' id='message' name='mensagem'><?= htmlspecialchars($mensagem) ?></textarea>
</div>
<div class='form-group'>
<input type='submit' name='submit' value='Send message'>
</div>
</form>
<?php
}

PHP Contact Form: empty values received, no update to div for delivery success message

My question might be quite a simple one, but I am very new to PHP and have tried to piece everything together after reading, but have run into some problems. I have read through possible duplicates of this post and tried as much as possible to put those solutions into my code but to no avail.
Objective:
Name and email validation (just not empty and in email format)
Details sent to indicated email
Basic sanitizing of code (mysqli escape and htmlspecialchars) (Understand that there is PDO, but would like to stick to this).
After successful submission, reload page with same website (fields empty) but with message in indicating message sent or error. Am trying header("Location: "). Would prefer not to introduce AJAX as I have no knowledge of it. Is this possible? Have also read about using action:"" to stay on same page, but how do I run my mail.php if my action is ""? Have also tried include: mail.php, or renaming my mail.php to index.php, but still did not succeed.
Current problems faced:
I do receive an email but with empty fields, i.e. inputs are not reflected although I did enter some values in the form. These are the values I received:
From:
Phone:
etc....
Page does direct to header location. But div not updated with $success variable, i.e. no message updated to show in div.
Please refer to my php and html file below:
PHP:
<?php
$link = mysqli_connect("host", "username", "password", "dbname");
$NameErr=$EmailErr=$Success="";
$Name=$Email=$Company=$JobTitle=$Phone=$Message="";
function sanitize($link,$entry) {
$entry = mysqli_real_escape_string($link,$entry);
$entry = htmlspecialchars($entry);
return $entry;
}
if (empty($_POST["Name"])) {
$nameErr = "Name is required";
}
else if (!preg_match("/^[a-zA-Z ]+$/", $Name)) {
$NameErr = "Only letters and spaces allowed";
}
else {
$Name = sanitize($link, $_POST["Name"]);
}
if (empty($_POST["Email"])) {
$EmailErr = "Email is required";
}
else if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$EmailErr = "Invalid email format";
}
else {
$Email = sanitize($link, $_POST["Email"]);
}
$Company = sanitize($link, $_POST["Company"]);
$JobTitle = sanitize($link, $_POST["JobTitle"]);
$Phone = sanitize($link, $_POST["Phone"]);
$Message = sanitize($link, $_POST["Message"]);
$formcontent=" From: $Name \n Phone: $Phone \n Company: $Company \n Job Title: $JobTitle \n Phone: $Phone \n Message: $Message";
$recipient = "myemail#gmail.com";
$subject = "Contact Form";
$mailheader = "From: $Email \r\n";
if (mail($recipient, $subject, $formcontent, $mailheader)){
$Success = "Message sent, thank you for contacting us!";
header("location:Contact.Us.html");
}
else($Success = "Sorry, we are unable to process your submission.");
?>
HTML form:
<form action="mail.php" method="POST">
<ul class="contact">
<li>
<label for="Name">Name<span class="red">*</span></label>
<p><input id="Name" name="Name" type="text" required/></p>
</li>
<li>
<label for="Email">Email<span class="red">*</span></label>
<p><input id="Email" name="Email" type="email" required/></p>
</li>
<li>
<label for="Company">Company</label>
<p><input id="Company" name="Company"/></p>
</li>
<li>
<label for="JobTitle">Job Title</label>
<p><input id="JobTitle" name="JobTitle"/></p>
</li>
<li>
<label for="Phone">Phone</label>
<p><input id="Phone" name="Phone"/></p>
</li>
<li>
<label for="Message">Message</label>
<p><textarea id="Message" wrap="soft" name="Message"></textarea></p>
</li>
</ul>
<br>
<p><input id="submit" type="submit" value="Send!" /></p>
<div class="success"><? =$Success; ?></div>
</form>
Would appreciate your reply to resolve any of the problems mentioned above. Would also appreciate if you could highlight other areas of possible security concerns. Thanks!
Also, upon implementing recommendation of sanitize($link,$entry), I am receiving inputs in my email for the variables: Company and Job Title.
Hence, I further changed all my variables name to first letter capital i.e. $message to $Message and aligned it throughout my form's input 'id', 'name' and 'for'. After which, I managed to receive input for the additional variables of Phone and Message.
Currently, am only not receiving values in my email for variables Name and Email. Perhaps there is an error with my 'if else if' portion of the php code. Will figure and update again. In the meantime, if any recommendation, please continue to update too. Thanks for your help!
As #headmax pointed, you need to also pass the link parameter to the sanitize function
function sanitize ($link, $entry) {
}
Reason is without passing it as a parameter, the $link variable becomes undefined. If you had error reporting on, you would have gotten a notice on $link.
For future purposes, whenever in development environment, always turn on error reporting as
error_reporting(E_ALL);//place this at the top of the script
EDIT
In order for you to display the success message and perform a redirect, you'd be better off using Ajax.
setTimeOut();//use this to display the success message for a while(pass number of seconds)
Then perform a redirect using javascript as
window.location.href ='URL';
Using your approach, just declare the success variable as
$success = '';//add this before you use the variable

how to add blank antispam input field into my form.php

I have a form that I am trying to add some steps that will minimize spam without forcing the end user to input some random number text series.
here’s an example of my form code:
<form action="form.php" method="post">
<label for="Name" style="some style">Enter your name:</label>
<input type="text" name="name">
<label for="Email" style="some style">Your email address:</label>
<input type="text" name="email">
<label for="City" style="some style">City:</label>
<select id="some ID" name="city" value="PQS" >
<option value="" selected disabled>Choose A City</option>
<option value="City1">City1</option>
<option value="City2">City2</option>
<input type="submit" value="Sign Up Now" class="button" id="subscribe">
</form>
<p id="error" style="some style">OOPS! Something went wrong. Please try again.</p>
<p id="success" style="some style">Success! We’ll contact you shortly</p>
My current form.php looks somewhat like this:
<?php
$emailmanager = 'me#myemail.com';
$name = $_POST['name'];
$visitor_email = $_POST['email'];
$city = $_POST['city'];
error_reporting(0);
$email = trim($_POST['email']);
$Ok = ereg("^([a-zA-Z0-9_\.-]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+)) ([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", $email);
if ($Ok) {
mail($emailmanager,'New Contact Request','You have a new contact request for homes in '.$_POST['city'].' from '.$_POST['name'].' ','From: '.$_POST['email'].' ');
if( !ereg("^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$",$UNameFrm) )
{
echo 1;
}
}
else
{
echo 0;
}
What I am trying to incorporate is a blank field that can deter the spambots, and I found an awesome code to use but I would like to incorporate it into my code above. See below the code i found:
<?php
// if the url field is empty
if(isset($_POST['url']) && $_POST['url'] == ''){
// put your email address here
$youremail = 'you#yoursite.com';
// prepare a "pretty" version of the message
$body = "This is the form that was just submitted:
Name: $_POST[name]
E-Mail: $_POST[email]
Message: $_POST[message]";
// Use the submitters email if they supplied one
// (and it isn't trying to hack your form).
// Otherwise send from your email address.
if( $_POST['email'] && !preg_match( "/[\r\n]/", $_POST['email']) ) {
$headers = "From: $_POST[email]";
} else {
$headers = "From: $youremail";
}
// finally, send the message
mail($youremail, 'Contact Form', $body, $headers ); } // otherwise, let the spammer think that they got their message through ?>
This code i found requires me to create a class
.antispam { display:none;}
...and add some html in my form
<label for="url" class="anti spam">Leave This Empty:</label>
<input type="text" name="url" />
how do I incorporate these 2 together? There are some things that are obvious to me, like adding
$url = $_POST['url'];
to my form.php on the next line following $city. My challenge is where to incorporate
// if the url field is empty
if(isset($_POST['url']) && $_POST['url'] == '')
and
if( $_POST['email'] && !preg_match( "/[\r\n]/", $_POST['email']) ) {
$headers = "From: $_POST[email]";
} else {
$headers = "From: $youremail";
}
into my form.php without screwing up my form function entirely. Any help would be appreciated, and I hope I made my question clear
You generate a random token for each guest session (or even user's login or form page) and save in database.
When printing forms, add one hidden input.
<input type="hidden" name="token" value="token_value_RANDOM1234567890">
When user submits form, then you check if given token is valid (or belongs to authenticated user, in login case). If belongs, then he's a valid user, else is a bot (not so simple as that). By the way, it complicates the process of spamming, do not block all ways of spamming. And you get an improvement on your website security.
Hope it helps.
You should put the class on the input, not the label, since labels aren't sent to the server.
<input type="text" class="antispam" name="antispam" value="">
Browsers won't send inputs that have display: none;, so if you receive this input, it means it came from an automated spammer.
if (isset($_POST['antispam'])) {
// Reject as spam
}
I use this honeypot tactic all the time. The trick is to create a field on the form that will not be visible to humans with eyes, but will be seen by bots. I usually give it an attractive name like "url" like your example does.
<input class="honeypot" name="url" value="url" />
Then you use CSS to push it off the screen:
input.honeypot {
position:absolute;
left:-5000px;
}
That can go anywhere in your stylesheet, or in a <style> tag in your html, or right on the input
<input style="position:absolute; left:-5000px;" name="url" value="url" />
Then you need a test in the validation code which is the action PHP:
if (isset($_POST['url'] && 'url' != $_POST['url']) {
header("location:/routing-error");
}
This gives the bot a 404 for the page "routing-error"

JS message in PHP return to HTML page

HTML Code
<div id="fourmstyle" class="fourm">
<form action="scripts/mail.php" method="post">
<label for="name">Your Name <required>*</required>
</label>
<input type="text" name="Name" id="Name" placeholder="Joe Bloggs">
<label for="email">Your Email <required>*</required>
</label>
<input type="text" name="Email" id="Email" placeholder="Joebloggs#example.com">
<label for="telephone">Telephone
</label>
<input type="text" name="Telephone" id="Telephone">
<label for="type">Type
</label>
<select name="Type">
<option value="Booking" selected>Booking</option>
<option value="B&B">B&B</option>
<option value="Question">Question</option>
<option value="General">General</option>
<option value="Website Feedback">Website Feedback</option>
</select></p>
<label for="messsage">Message <required>*</required>
</label>
<textarea name="Message" id="Message" rows="5" cols="25">
</textarea></p>
<label for="btn"> </label>
<button type="submit" class="button">Submit
</button>
<br> <requireddescription> *(indicates that the information is required)
</requireddescription>
</form>
PHP Code
<?php
if(isset($_POST))
{
$name = (isset($_POST['Name'])) ? strip_tags($_POST['Name']) : NULL; //if name is set, strip html tags, and return it, otherwise set the string as NULL.
$email = (isset($_POST['Email'])) ? strip_tags($_POST['Email']) : NULL; //same as above.
$telephone = (isset($_POST['Telephone'])) ? preg_replace('~[^0-9\-]~','',$_POST['Telephone']) : NULL; //if telephone is set, remove any characters that are not a number, or a dash, othewise set as NULL.
$type = (isset($_POST['Type'])) ? strip_tags($_POST['Type']) : NULL; //strip tags.
$message = (isset($_POST['Message'])) ? strip_tags($_POST['Message']) : NULL; //strip tags.
if(empty($name) || empty($email) || empty($message))
{
//name, email, and message are required fields, if they are empty, tell the user to go back and fill them in.
echo '<script type="text/javascript"> alert ("Please go back and fill in all required lines"); </script>';
}
else
{
//if the fields are NOT empty, proceed with the mailing.
$formcontent=" From: $name \n Type: $type \n\n Message: $message \n\n Telephone: $telephone";
$recipient = "joebloggs#example.com";
$subject = "Website Contact Form: $type";
$mailheader = "From: $email \r\n";
if(mail($recipient, $subject, $formcontent, $mailheader))
{
//if mail is sent to the SMTP server successfully, echo 'thank you'.
echo '<script type="text/javascript"> alert ("Thankyou '.$name.' we have submitted your message and we will get back to you as soon as possible, if you need to speak to us in the mean time please call 01983 872244 "); </script>';
}
else
{
//otherwise, tell the user it did not go through.
echo '<script type="text/javascript"> alert ("I am sorry but there has been an error submitting your request please try again or call us on 01983 872244"); </script>';
}
}
}
?>
Ok so my code above works quite nicely and I have JS pop up alerts. However, when I ok the JS alert it takes me back to the mail.php script and not the HTML page in which it originated from how would I rectify this ?
This should help solve your immediate issue... but in the future, try out an AJAX call.
if(mail($recipient, $subject, $formcontent, $mailheader))
{
//if mail is sent to the SMTP server successfully, echo 'thank you' and return to previous page.
echo '<script type="text/javascript"> alert ("Thankyou '.$name.' we have submitted your message and we will get back to you as soon as possible, if you need to speak to us in the mean time please call 01983 872244 "); window.history.back(); </script>';
}
else
{
//otherwise, tell the user it did not go through.
echo '<script type="text/javascript"> alert ("I am sorry but there has been an error submitting your request please try again or call us on 01983 872244"); window.history.back(); </script>';
}
EDIT
forgot to include the first instance
if(empty($name) || empty($email) || empty($message))
{
//name, email, and message are required fields, if they are empty, tell the user to go back and fill them in and send them back.
echo '<script type="text/javascript"> alert ("Please go back and fill in all required lines"); window.history.back()</script>';
}
When you submit to mail.php, mail.php becomes the new page your user is on. If you want them to still be on the page from which they called it, you either need to submit it via AJAX, or tell the browser to go back to the page from which the script was called. To do it the second way, add this to your script echos:
window.history.back()
It depends on what you've done in your HTML page:
If your PHP was called via ajax, then you need to add return false to the javascript function that initiated that ajax call.
If you have a form and the form's submission via regular postback to the action's url was how you processed that PHP page, then you need to either add a redirect in PHP back to that page WHILE storing that alert message in session so it doesn't get lost, OR throw some HTML after that PHP.

PHP Show error messages in order and re-display correct fields

I have an email form that checks three fields, name, valid email and comments. But the way it's set up now, since name and comments are in one function it first checks name and comments even if email is not valid, how can I re-write it so it checks the fields in order. Also, I would like to re-display the fields that have no errors, so the user doesn't have to type again. Please help. Thanks
<?php
$myemail = "comments#myemail.com";
$yourname = check_input($_POST['yourname'], "Enter your name!");
$email = check_input($_POST['email']);
$phone = check_input($_POST['phone']);
$subject = check_input($_POST['subject']);
$comments = check_input($_POST['comments'], "Write your comments!");
if (!preg_match("/([\w\-]+\#[\w\-]+\.[\w\-]+)/", $email))
{
show_error("Enter a valid E-mail address!");
}
exit();
function check_input($data, $problem='')
{
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
if ($problem && strlen($data) == 0)
{
show_error($problem);
}
return $data;
}
function show_error($myError)
{
?>
<!doctype html>
<html>
<body>
<form action="myform.php" method="post">
<p style="color: red;"><b>Please correct the following error:</b><br />
<?php echo $myError; ?></p>
<p>Name: <input type="text" name="yourname" /></P>
<P>Email: <input type="text" name="email" /></p>
<P>Phone: <input type="text" name="phone" /></p><br />
<P>Subject: <input type="text" style="width:75%;" name="subject" /></p>
<p>Comments:<br />
<textarea name="comments" rows="10" cols="50" style="width: 100%;"></textarea></p>
<p><input type="submit" value="Submit"></p>
</form>
</body>
</html>
<?php
exit();
}
?>
First off, I would suggest you validate ALL of the fields at once, and display all appropriate error messages on the form. The primary reason is that it can be bad user experience if they have to submit your form a whole bunch of times because they have to address one error at a time. I'd rather correct my email address, password, comments, and selection in one try instead of fixing one at a time just to reveal what the next error is.
That said, here are some pointers on validating the form like you want. This is typically how I approach a form doing what you want to do. This assumes your form HTML and form processor (PHP) are together in the same file (which is what you have now). You can split the two, but the methods for doing that can be a bit different.
Have one function or code block that outputs the form and is aware of your error messages and has access to the previous form input (if any). Typically, this can be left outside of a function and can be the last block of code in your PHP script.
Set up an array for error messages (e.g. $errors = array()). When this array is empty, you know there were no errors with the submission
Check to see if the form was submitted near the top of your script before the form is output.
If the form was submitted, validate each field one at a time, if a field contained an error, add the error message to the $errors array (e.g. $errors['password'] = 'Passwords must be at least 8 characters long';)
To re-populate the form inputs with the previous values, you have to store the entered values somewhere (you can either just use the $_POST array, or sanitize and assign the $_POST values to individual variables or an array.
Once all the processing is done, you can check for any errors to decide whether the form can be processed at this point, or needs new input from the user.
To do this, I typically do something like if (sizeof($errors) > 0) { // show messages } else { // process form }
If you are re-displaying the form, you simply need to add a value="" attribute to each form element and echo the value that was submitted by the user. It is very important to escape the output using htmlspecialchars() or similar functions
With those things in place, here is some re-work of your form to do that:
<?php
$myemail = "comments#myemail.com";
$errors = array();
$values = array();
$errmsg = '';
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
foreach($_POST as $key => $value) {
$values[$key] = trim(stripslashes($value)); // basic input filter
}
if (check_input($values['yourname']) == false) {
$errors['yourname'] = 'Enter your name!';
}
if (check_input($values['email']) == false) {
$errors['email'] = 'Please enter your email address.';
} else if (!preg_match('/([\w\-]+\#[\w\-]+\.[\w\-]+)/', $values['email'])) {
$errors['email'] = 'Invalid email address format.';
}
if (check_input($values['comments']) == false) {
$errors['comments'] = 'Write your comments!';
}
if (sizeof($errors) == 0) {
// you can process your for here and redirect or show a success message
$values = array(); // empty values array
echo "Form was OK! Good to process...<br />";
} else {
// one or more errors
foreach($errors as $error) {
$errmsg .= $error . '<br />';
}
}
}
function check_input($input) {
if (strlen($input) == 0) {
return false;
} else {
// TODO: other checks?
return true;
}
}
?>
<!doctype html>
<html>
<body>
<form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="post">
<?php if ($errmsg != ''): ?>
<p style="color: red;"><b>Please correct the following errors:</b><br />
<?php echo $errmsg; ?>
</p>
<?php endif; ?>
<p>Name: <input type="text" name="yourname" value="<?php echo htmlspecialchars(#$values['yourname']) ?>" /></P>
<P>Email: <input type="text" name="email" value="<?php echo htmlspecialchars(#$values['email']) ?>" /></p>
<P>Phone: <input type="text" name="phone" value="<?php echo htmlspecialchars(#$values['phone']) ?>"/></p><br />
<P>Subject: <input type="text" style="width:75%;" name="subject" value="<?php echo htmlspecialchars(#$values['subject']) ?>" /></p>
<p>Comments:<br />
<textarea name="comments" rows="10" cols="50" style="width: 100%;"><?php echo htmlspecialchars(#$values['comments']) ?></textarea></p>
<p><input type="submit" value="Submit"></p>
</form>
</body>
</html>
I have a more advanced example which you can see here that may give you some guidance as well.
Hope that helps.
The simplest option is to use a form validation library. PHP's filter extension, for example, offers validation and sanitization for some types, though it's not a complete solution.
If you insist on implementing it yourself, one issue you'll have to consider is what counts as the order: the order of the elements in the form or the order of the user input in $_POST. On most browsers, these should be the same, but there's no standard that enforces this. If you want to go off of form order, you'll need to define the form structure in one place, and use that information to do things like generating or validating the form (a consequence of the Don't Repeat Yourself (DRY) principle). Iterating over the appropriate structure will give you the order you desire: looping over the form gives you form order, whereas looping over $_POST gives you user input order.
It looks like you want to more than simply validate the data; you also want to prepare it for use, a process called "sanitization".
When it comes to sanitization, define different kinds of sanitizers, rather than a single check_input function. Specific sanitizers could be functions, or objects with an __invoke method. Create a map of form fields to sanitizers (for example, an array of input name to sanitizer callbacks). The order of the elements in the mapping sets the order of the sanitization; if you use a single structure to define the form information, the display order and sanitization order will thus be the same.
Here's a very broad outline:
# $fields could be form structure or user input
foreach ($fields as $name => $data) {
# sanitize dispatches to the appropriate sanitizer for the given field name
$form->sanitize($name, $data);
# or:
//sanitize($name, $data);
# or however you choose to structure your sanitization dispatch mechanism
}
As for setting an input's value to the user-supplied data, simply output the element value when outputting the element. As with all user input (really, all formatted output), properly escape the data when outputting it. For HTML attributes, this means using (e.g.) htmlspecialchars. Note you should only escape outgoing data. This means your sanitization functions shouldn't call htmlspecialchars.
You can improve usability by placing each error next to the corresponding input, adding an "error" class to the element and styling the "error" class to make it stand out. Improve accessibility by wrapping <label> elements around the label text.
Use this structure of script:
<?php
$errors = array();
if (isset($_POST['send'])) {
// check data validity
if (!mailValid($_POST['email']))
$errors[] = 'Mail is not valid';
...
// send data by email
if (!$errors) {
// send mail and redirect
}
}
?>
<html>
...
<?php
if ($errors) {
// display errors
foreach ($errors as $error) {
echo "$error<br />";
}
}
?>
<form ...>
...
Email: <input type="text" name="email" value="<?php echo isset($_POST['email']) ? htmlspecialchars($_POST['email']) : '' ?>" />
...
</form>
...
</html>
You could always do it like this, using filter_var and in_array checks:
<?php
$myemail = "comments#myemail.com";
//Pre made errors array
$errors=array('name'=>'Enter Your name',
'email'=>'Please enter valid email',
'phone'=>'Please enter valid phone number',
'subject'=>'Please enter valid subject, more then 10 chars',
'comment'=>'Please enter valid comment, more then 10 chars');
//Allowed post params and its validation type
$types = array('name'=>'string',
'email'=>'email',
'phone'=>'phone',
'subject'=>'string',
'comment'=>'string');
//A simple validation function using filter_var
function validate($value,$type){
switch ($type){
case "email":
return ((filter_var($value, FILTER_VALIDATE_EMAIL))?true:false);
break;
case "phone":
return ((preg_match("/^[0-9]{3}-[0-9]{4}-[0-9]{4}$/", $value))?true:false);
break;
case "string":
return ((strlen($value) >=10 )?true:false);
break;
default:
return false;
break;
}
}
//If forms been posted
if(!empty($_POST) && $_SERVER['REQUEST_METHOD'] == 'POST'){
//Assign true, if all is good then this will still be true
$cont=true;
$error=array();
foreach($_POST as $key=>$value){
//if key is in $types array
if(in_array($key,$types)){
//If validation true
if(validate($value, $types[$key])==true){
$$key=filter_var($value, FILTER_SANITIZE_STRING);
}else{
//Validation failed assign error and swithc cont to false
$error[$key]=$errors[$key];
$cont=false;
}
}
}
}
if($cont==true && empty($error)){
//Send mail / do insert ect
}else{
//Default to form
?>
<!doctype html>
<html>
<body>
<form action="" method="post">
<p>Name: <input type="text" name="name" value="<?=#htmlentities($name);?>"/> <?=#$error['name'];?></P>
<P>Email: <input type="text" name="email" value="<?=#htmlentities($email);?>" /> <?=#$error['email'];?></p>
<P>Phone: <input type="text" name="phone" value="<?=#htmlentities($phone);?>"/> <?=#$error['phone'];?></p><br />
<P>Subject: <input type="text" style="width:75%;" name="subject" /> <?=#$error['subject'];?></p>
<p>Comments: <?=#$error['comment'];?><br />
<textarea name="comment" rows="10" cols="50" style="width: 100%;"><?=#htmlentities($comment);?></textarea></p>
<p><input type="submit" value="Submit"></p>
</form>
</body>
</html>
<?php
}?>

Categories