Ajax form validation in php

Im trying to create ajax from with php validation, let explain with screenshot. while validating form im getting all error in same place…

what im trying to get is individual validation for field like below

And after form is submitted i want display success message at the top of form but im getting success message on all field

html form data (index.php)

<form id="first_form" method="POST" action="form.php">
    <p class="form-message"></p>
    <div class="mb-3">
        <input type="text" class="form-control" id="name" name="name" placeholder="Name:">
        <p class="form-message"></p>
    </div>
    <div class="mb-3">
        <input type="tex" class="form-control" id="email" name="email" placeholder="Email:">
        <p class="form-message"></p>
    </div>
    <div class="mb-3">
        <input type="text" class="form-control" id="phone" name="phone" placeholder="Phone:">
    </div>
    <div class="mb-3">
        <input type="text" class="form-control" id="address" name="address" placeholder="Address:">
    </div>
    <div class="mb-3">
        <input type="text" class="form-control" id="subject" name="subject" placeholder="Subject:">
    </div>
    <div class="mb-3">
        <input type="text" class="form-control" id="services" name="services" placeholder="Services:">
    </div>
    <div class="mb-3">
        <textarea class="form-control" rows="5" id="message" name="message" placeholder="Leave Your Message..."></textarea>
    </div>
    <button type="submit" name="submit" id="submit" class="btn btn-primary">Submit</button>
</form>

js code:

  $(document).ready(function() {
    $("#first_form").submit(function(event) {
        event.preventDefault();
        
            name     = $("#name").val();
            email    = $("#email").val();
            phone    = $("#phone").val();
            address  = $("#address").val();
            subject  = $("#subject").val();
            services = $("#services").val();
            message  = $("#message").val();
            submit   = $("#submit").val();

            $(".form-message").load("form.php", {
                name: name,
                email: email,
                phone: phone,
                address: address,
                subject: subject,
                services: services,
                message: message,
                submit: 'submitted'
            });

    });
});

form.php data

if (isset($_POST['submit'])){
    $name = $_POST['name'];
    $email = $_POST['email'];
    $message = $_POST['message'];
    $subject = "Contact Form";
    $mailTo = "hello@develoweb.com";
    $headers = "From: ".$email;
    $txt = "You have received a message from ".$name.
        ".\n\n".$message;
    
    $errorEmptyname = false;
    $errorEmptyemail = false;
    $errorEmptymessage = false;
    $errorEmail = false;
    
    if (empty($name)) {
        echo "<span class='form-error'>Name Field cannot be empty</span> ";
        //$errorEmptyName = true;
    }  
    
    if (empty($email)) {
        echo "<span class='form-error'>Email Field cannot be empty</span>";
        //$errorEmptyemail = true;
    }    
    
    if (empty($message)) {
        //$errorEmptymessage = true;
    }
    elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        echo "<span class='form-error'>
        Write a valid e-mail addres </span>";
        $errorEmail = true;
    }
    else {
        echo "<span class='form-success'>
        Thank you for your message!<br>
        I'll get back to you as soon as I can.</span>";
        
        mail($mailTo, $subject, $body, $headers);
    }
}
else{
    echo "There was an error!";
}

what i have understand, im not getting individual validation error in individual field bcz class is same, how can i append error to related fields

i havent used js validation bcz i want to some validation for spammer to prevent spam mail and as we know while viewing source code we can easily view code for validation too, so pefer validation in php

to allow you to display either the success message or individual error messages, you must create elements with unique ids. the server-side code must then output (json) data that has those ids as keys, and the desired content as values.

some points about the existing code -

  1. don’t write out code for every field. operate on data as a set. you can the jquery .serialize() method to get all the form data at once.
  2. you need to use the jquery $.ajax method, so that you have more control over what it does.
  3. don’t copy variables to variables for nothing. this is just a waste of typing.
  4. keep the form data as a set, in a php array variable, then operate on elements in this array variable throughout the rest of the code.
  5. don’t create variables for every possible error. instead, use an array for user/validation errors.
  6. these emails are NOT being sent from the email address that was entered in the form. they are being sent from the mail server at your web hosting. the From: mail header must be an email address that corresponds to your sending mail server. you can put the entered email address into a Reply-to: mail header, after validating that it is only and exactly one properly formatted email address.
  7. Any dynamic value that gets used in the mail body should have htmlentities() applied to it to help prevent any html, css, javascript in the value from being operated on if the mail is read using a browser.

see the following example -

<p class='response' id="success_message"></p>

<form id="first_form" method="POST" action="form.php">
    <div class="mb-3">
        <input type="text" class="form-control" id="name" name="name" placeholder="Name:">
        <p class='response' id="name_error"></p>
    </div>
    <div class="mb-3">
        <input type="text" class="form-control" id="email" name="email" placeholder="Email:">
        <p class='response' id="email_error"></p>
    </div>
    <div class="mb-3">
        <textarea class="form-control" rows="5" id="message" name="message" placeholder="Leave Your Message..."></textarea>
        <p class='response' id="message_error"></p>
    </div>
    <button type="submit" name="submit" id="submit" class="btn btn-primary">Submit</button>
</form>
<script>
  $(document).ready(function() {
    $("#first_form").submit(function(event) {
        event.preventDefault();
        
		$.ajax({
			type: "POST",
			url: "form.php",
			dataType: 'json',
			data: $(this).closest("form").serialize(),
			success: function(response){
				// clear any existing class='response' html
				$(".response").empty();
				// loop over the keys/values in the response
				$.each(response, function(key, value){
					// set the html of the id corresponding to the key to the value
					$('#'+key).html(value);
				});
			}
		});
    });
});
</script>
<?php

// initialization

$subject = "Contact Form";
$mailTo = "hello@develoweb.com";
// the From: mail header must be an address that corresponds to your sending mail server
$mailFrom = "hello@develoweb.com";

$post = []; // array to hold a trimmed working copy of the form data
$errors = []; // array to hold user/validation errors

// post method form processing
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
	// inputs - name, email, message
	
	// trim all the data at once
	$post = array_map('trim',$_POST); // if any input is an array, use a recursive trim call-back function here instead of php's trim
	
	// validate inputs
	if($post['name'] === '')
	{
		$errors['name'] = "Name is required.";
	}

	if($post['email'] === '')
	{
		$errors['email'] = "Email is required.";
	}
	else if(!filter_var($post['email'], FILTER_VALIDATE_EMAIL))
	{
		$errors['email'] = "Email format is not valid.";
	}
	
	if($post['message'] === '')
	{
		$errors['message'] = "Message is required.";
	}	
	
	// if no errors, use the form data
	if(empty($errors))
	{
		// use the form data in $post here...
		
	    $headers = "From: ".$mailFrom;
		
		// you would use a call-back function with array_map() to apply htmlentities() to all the elements in $post, rather than writing out a line of code for each element
		$post['name'] = htmlentities($post['name'],ENT_QUOTES);
		$post['message'] = htmlentities($post['message'],ENT_QUOTES);
		
		$body = "You have received a message from {$post['name']}\n\n{$post['message']}";

		// you must test the returned value from the mail() call
		// if it is a false value, setup a message in the $errors array
		mail($mailTo, $subject, $body, $headers);
	}
	
	$response = [];
	if(empty($errors))
	{
		$response['success_message'] = "Thank you for your message!<br>I'll get back to you as soon as I can.";
	}
	else
	{
		foreach($errors as $key=>$value)
		{
			$response[$key.'_error'] = $value;
		}
	}
	echo json_encode($response);
}
1 Like

thank you so much sir,thats what i have been trying now i can get individual error but success message in not displayed on form submit…

what debugging have you done? how about checking the browser’s developer tools network response tab to see what is being output by the server?

your code work perfectly sir, issue was with my hosting, thank for your time

in form i have some hidden to identify the bot, if field value is change then it will not submit form but it will display successful message so that spammer think form is submitted.

<p class='response' id="success_message"></p>

<form id="first_form" method="POST" action="form.php">
    <div class="col-md-6">
        <input type="hidden" name="imnotspammer" placeholder="same as below" class="form-control"  value="imnotspammer">
    </div>
    <div class="col-md-6">
        <input type="hidden" name="imblank" placeholder="same as below" class="form-control"  value="">
    </div>
    <div class="mb-3">
        <input type="text" class="form-control" id="name" name="name" placeholder="Name:">
        <p class='response' id="name_error"></p>
    </div>
    <div class="mb-3">
        <input type="text" class="form-control" id="email" name="email" placeholder="Email:">
        <p class='response' id="email_error"></p>
    </div>
    <div class="mb-3">
        <textarea class="form-control" rows="5" id="message" name="message" placeholder="Leave Your Message..."></textarea>
        <p class='response' id="message_error"></p>
    </div>
    <button type="submit" name="submit" id="submit" class="btn btn-primary">Submit</button>
</form>

how can i added this things inside your code…
In php code i have doing as follows:

$floor = 'imnotspammer';
if ($_REQUEST['imnotspammer'] != $floor ){
   header('Location: https://mydomain.com/thankyou.php', true, 303);
}
            
elseif ($_REQUEST['imblank'] != ''){
    header('Location: https://mydomain.com/thankyou.php', true, 303);
}

so how can i added field and condition in which form will not submitted if this hidden field value is change but display successfully submitted message in ajax (in your code)

i have tried some code, its displaying successful message but also submitting form.

$floor = 'imnotspammer';
$response = [];
	
	if(empty($errors))
	{
		$response['success_message'] = "Thank you for your message!<br>I'll get back to you as soon as I can.";
	}elseif($post['spam'] !== $floor){
		$response['success_message'] = "Thank you for your message!<br>I'll get back to you as soon as I can.";
	}
	else
	{
		foreach($errors as $key=>$value)
		{
			$response[$key.'_error'] = $value;
		}
	}
	echo json_encode($response);

if hidden field value is change then i dont want to submit form but want to display successful message…

even die()/exit() doesn’t work

$response = [];
	
	if($post['spam'] !== $floor){
		$response['success_message'] = "This is not spamming ";
		die();
	}else{
		if(empty($errors)){
			$response['success_message'] = "Thank you for your message!<br>I'll get back to you as soon as I can.";
		}else{
			foreach($errors as $key=>$value)
			{
				$response[$key.'_error'] = $value;
			}
		}
	}	
	echo json_encode($response);

Look at the field names in your form, they are not called secretField, secretBlank or spam.

There’s no point setting the value of $response just before you call die(). But can you expand on “doesn’t work”?

code correction:

$floor = 'imnotspammer';
if ($_REQUEST['imnotspammer'] != $floor ){
   header('Location: https://mydomain.com/thankyou.php', true, 303);
}
            
elseif ($_REQUEST['imblank'] != ''){
    header('Location: https://mydomain.com/thankyou.php', true, 303);
}

what im trying to do is, im trying add code of line condition that if hidden field like field-1,field-2,field-3 ,if these hidden field value is change then form will not be submitted but it will show successful message as form have been submitted to prevent spam mail…

You need to exit() after each of your header redirects. Also note that if you’ve output anything to the browser before your redirect (even just a space or newline before the opening PHP tag), it will fail with a “headers already sent” error unless you’re buffering output.

What is in $_POST when you var_dump() it for debugging purposes? As the rest of the code uses $_POST, why not use that instead of $_REQUEST in your added code?

Because you are submitting the form using ajax, redirects in the server-side code won’t do anything and are not part of this activity.

Because you want to prevent the email from being sent, and also skip over all the rest of the validation logic, you would put any test for the two fields at the start of the validation section, set element(s) in the $errors array, and add a conditional test around the rest of the validation logic.

Because you probably want to log information about the occurrence of the two inputs not being as expected and you want to setup the fake ‘success’ message, wouldn’t the simplest solution be to test at the start of the ‘response’ section if the corresponding $errors element(s) are set, perform any logging and setup the success message, then skip over the existing if/else code building the values in $response, and execute the existing echo json_encode($response) statement?

3 Likes

i have try to figure out what you have told and tried code below, please kindly check if code if correct and is standard code.

//form hidden field
<input type="text" class="form-control" id="spam" name="spam" placeholder="Spam:" value="imnotspammer">

Now validating form and checking for hidden fields

// validate inputs
	
	if($post['name'] === '')
	{
		$errors['name'] = "Name is required.";
	}

  if($post['message'] === '')
	{
		$errors['message'] = "Message is required.";
	}	
	
	// if no errors, use the form data

  $floor = 'imnotspammer';//hidden field value

//checking if hidden field value have change or not if value is change it will stop form submitting
if($post['spam'] !== $floor){
    $errors['spam'] = "";
}elseif(!empty($errors)){//checking for any validation error
    foreach($errors as $key=>$value){
    $response[$key.'_error'] = $value;
  }
}else{//submitting form is everything is fine
  // use the form data in $post here...
		$post['name'] = htmlentities($post['name'],ENT_QUOTES);
		$post['message'] = htmlentities($post['message'],ENT_QUOTES);
		
		$body = "You have received a message from {$post['name']}\n\n{$post['message']}";

		// you must test the returned value from the mail() call
		// if it is a false value, setup a message in the $errors array
		mail($mailTo, $subject, $body);
	}

if there are to errors and all field are set then send message and mail

 $response = [];
	if(empty($errors)){
		$response['success_message'] = "Thank you for your message!<br>I'll get back to you as soon as I can.";

	}elseif($post['spam'] !== $floor){//sending fake message if hidden field value match fail
	    	$response['success_message'] = "Thank you for your message!";
	    }else{
		
		foreach($errors as $key=>$value){
			$response[$key.'_error'] = $value;
		}
	}	
	echo json_encode($response);

this code works fine as my i want but i bit confuse in validation for hidden fields

if($post['spam'] !== $floor){
    $errors['spam'] = "";
}elseif(!empty($errors)){
    foreach($errors as $key=>$value){
      $response[$key.'_error'] = $value;
    }
}else{
  //submitted form
}

now as check for condition meet in form hidden field is blank

if($post['spam'] !== $floor){
    $errors['spam'] = "";
}
should $errors['spam'] = ""; be blank or there should anything or im doing if/else condition totally wrong

code works fine… but i have doubt that $errors[‘spam’] = " "; should this really be blank…??

As I understand it you want to carry on as if nothing happened if the spam check fields are blank, so that would suggest that you should leave it blank. If you put something in it, your error-checking code will flag an error if you only use empty() to check.

1 Like

thank you once agian you are always there when one needs help thanks to all who spend time for viewing my issues… im in love with this community… :heart: :hearts: :heavy_heart_exclamation:

What are the goals of doing this -

  1. detect if something, probably a bot script, is submitting their own data.
  2. use the minimum of resources, i.e. skip over as much of the logic as possible.
  3. prevent the sending of the email.
  4. log information about the occurrence.
  5. setup a dummy success message.
  6. output the response to the ajax code.

I recommend that you devise, write, test, and debug the code for each of these things, one at a time.

If you do item #1 and intentionally manipulate the values in the fields, by either altering the code for the markup or temporarily make the fields type=‘text’ and entering/clearing the values, you should get xxxxx_error elements, with error message(s), that you will ultimately log instead of outputting, in the response back to the ajax code.

After you succeed with this step, go onto the next step. Test the code for it. Then continue until you are done and have achieved the desired results.

I have a couple of other recommendations. Instead of a static value for the field that must not be empty, generate a random value, store it in a session variable, put it into the field’s value, then compare the submitted value with the value in the session variable, making sure that both are not empty. You should also give the fields names that would seem like they are for values that are actually used and you should hide them using css that also is named like it is for something that is actually used.

1 Like

thank you for the solution, really appreciate your time and effort