Search code examples
javascriptphphtmlxmlhttprequest

PHP failed to submit the html form


below is simple PHP script to validate and successfully submit the form to the server I've added xhr(XMLHttpRequest) to make it efficient.First it was supposed to check if the input fields are empty then show error message , if password does not meet criteria then show error message but i am wondering why it does not work like it was expected , when i click submit button it submit the form and none of the functionalities works . any help will be appreciated

    <?php
require_once('db.php');
error_reporting(~E_NOTICE);
date_default_timezone_set('Africa/Nairobi');
// Log errors to a file
ini_set('error_log', '/var/log/php_errors.log');

// Initialize error message array
$errMsg = array();

if(isset($_POST['register'])){
    $name = filter_var($_POST['name'], FILTER_SANITIZE_STRING);
    $password = filter_var($_POST['password'], FILTER_SANITIZE_STRING);
    $time=date('y-m-d h:i:s',time());
    $date=date('y-m-d',strtotime('now'));
    
    // validate inputs and Display user-friendly error messages
    if (empty($name) || empty($password)) {
        // Display error message to the user
        $errMsg[] = "Enter both name and password";
    } else{
        // Implement password complexity rules
        if (strlen($password) < 8 || !preg_match("#[0-9]+#", $password) || !preg_match("#[A-Z]+#", $password) || !preg_match("#[a-z]+#", $password) || !preg_match("#[\W]+#", $password)) {
            $errMsg[]="Password must contain at least 8 characters including uppercase and lowercase letters, numbers, and symbols";
        } else {
            // Use a custom salt instead of the default salt
            $custom_salt = bin2hex(random_bytes(10));
            // Use password_hash() function to create a password hash
            $hash = password_hash($password . $custom_salt, PASSWORD_BCRYPT);
            
            // Insert user details into database
            if(empty($errMsg)){
                $sth=$db->prepare("INSERT INTO users(name,password,time,date) VALUES(:name,:password,:time,:date)");
                $sth->bindParam(':name', $name, PDO::PARAM_STR);
                $sth->bindParam(':password', $hash, PDO::PARAM_STR);
                $sth->bindParam(':time', $time, PDO::PARAM_STR);
                $sth->bindParam(':date', $date, PDO::PARAM_STR);
                $sth->execute();
                die('success');
            }
        }
    }
}
?>

<!-- HTML code starts here -->

<!DOCTYPE html>
<html>
<head>
    <title>User Registration</title>
</head>
<body>
    <h2>User Registration Form</h2>
    <?php 
    // Display error messages
    if (!empty($errMsg)) {
        foreach ($errMsg as $msg) {
            echo '<div style="color: red;">' . $msg . '</div>';
        }
    }
    ?>
    <div id="error-message" style="color: red;"></div>

<form id="register-form" action="" method="post">
        <label for="name">Name:</label>
        <input type="text" id="name" name="name"><br><br>
        
        <label for="password">Password:</label>
        <input type="password" id="password" name="password"><br><br>
        
        <input type="submit" name="register" value="Register">
    </form>
    <script>
  const form = document.getElementById('register-form');
  form.addEventListener('submit', function(event) {
    event.preventDefault(); // prevent the default form submission
    
    const xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
      if (xhr.readyState === XMLHttpRequest.DONE) {
        if (xhr.status === 200) {
          // successful response, redirect to the index page
          window.location.href = 'index.php';
        } else {
          // display the error message to the user
          const errMsg = document.getElementById('error-message');
          errMsg.innerHTML = xhr.responseText;
        }
      }
    };
    xhr.open('POST', form.action);
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.send(new FormData(form));
  });
</script>

</body>
</html>

Solution

  • You have at least two different problems here, each of which would cause your problem by itself.

    Your content-type is wrong

    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.send(new FormData(form));
    

    Under normal circumstances, when you pass a FormData object to send() then XHR will generate a Content-Type request header from it with the correct content type (multipart form data with a boundary parameter).

    In this case you've overridden the Content-Type header to one that is wrong. PHP tries to parse the body as application/x-www-form-urlencoded, fails, and doesn't populate $_POST.


    Your submit button is unsuccessful

    isset($_POST['register'])
    

    When you submit a form normally, the clicked submit button becomes a successful control (i.e. sends its name and value in the form data).

    You're intercepting the normal form submission (and preventing it with event.preventDefault();) and constructing a new request using Ajax.

    new FormData(form) will not include the submit button's data, so you can't use it to branch your code with an if statement as you are attempting.