Search code examples
phpformspostget

Show errors on form without using $_GET


I created a registration form using PHP. When submitting the form, I check for errors (is name or email taken, are both passwords correct). If something is wrong, I return the user to the form using the header function along with the info (error and fields) and then use the $_GET method to show the error and fill the form back in.

Is there a way to show the errors on the form without the use of header and $_GET? Can I recieve error information from $_POST and fill the form back in?

I prefer not to use JavaScript, but will if needed.

My code works perfectly, just want to know if there is a way to not use the URL.

My registration form:

<?php
  require 'header.php';
?>

<section>
  <?php
    if (isset(&_GET['error'])) {
      // My error code here...
    }
  ?>
  <form action="inc/register.inc.php" method="post">
    <input type="text" name="name" placeholder="Name" value="<?php $_GET['name'] ?>" />
    <input type="text" name="mail" placeholder="E-mail" value="<?php $_GET['mail'] ?>" />
    <input type="password" name="pwd" placeholder="Password" />
    <input type="password" name="pwd-repeat" placeholder="Confirm Password" />
    <input type="submit" name="registerBtn" value="Registreer" />
  </form>
</section>

<?php
  require 'footer.php';
?>

php file that handles errors and registration:

<?php
if (isset($_POST['registerBtn'])) {
  require 'db_connect.php';

  $name = $_POST['name'];
  $email = $_POST['mail'];
  $pwd = $_POST['pwd'];
  $pwd2 = $_POST['pwd-repeat'];

  if (empty($name) or empty($email) or empty($pwd) or empty($pwd2)) {
    header("Location: ../register.php?error=emptyfields&name=". $name ."&mail=". $email);
    exit();
  }
  else if (!preg_match("/^[\p{L}\p{N}_-]*$/u", $name) and !filter_var($email, FILTER_VALIDATE_EMAIL)) {
    header("Location: ../register.php?error=invalidmailname);
    exit();
  }
  else if (!preg_match("/^[\p{L}\p{N}_-]*$/u", $name)) {
    header("Location: ../register.php?error=invalidname&mail=". $email);
    exit();
  }
  else if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    header("Location: ../register.php?error=invalidmail&name=". $name);
    exit();
  }
  else if ($pwd !== $pwd2) {
    header("Location: ../register.php?error=passwordcheck&name=". $name ."&mail=". $email);
    exit();
  }
  else {
    // More code here... but you get the gist.
  }
}
else {
  header("Location: ../register.php");
  exit();
}

Solution

  • If you want to use a separate script to handle your form processing, you can use the session to hold temporary data - this is commonly known as flash data.

    In the following example, we set errors and data to the session so that we can access it from index.php.

    After dealing with the flash data, we remove it from the session since we don't want it around on the next request.

    index.php

    session_start();
    
    // The values that are used to display the form after validation has failed.
    // Notice that we actually set them below using the flash data if it's available.
    $firstName = '';
    $lastName = '';
    
    // Do we have any flash data to deal with?
    if (isset($_SESSION['flash'])) {
    
        // Here, we deal with any _errors_
        if (isset($_SESSION['flash']['errors'])): ?>
    
            <ul>
                <?php foreach ($_SESSION['flash']['errors'] as $field => $error): ?>
                    <li><?php echo $error; ?></li>
                <?php endforeach; ?>
            </ul>
        <?php endif;
    
        // Here we deal with populating the form again from _data_
        if (isset($_SESSION['flash']['data'])) {
            $firstName = $_SESSION['flash']['data']['first_name'] ?: '';
            $lastName = $_SESSION['flash']['data']['last_name'] ?: '';
        }
    
        // Remove the flash data from the session since we only want it around for a single request
        unset($_SESSION['flash']);
    }
    ?>
    <form method="post" action="handler.php">
    
        <label>
            <input type="text" name="first_name" placeholder="First Name" value="<?php echo $firstName; ?>">
        </label>
    
        <label>
            <input type="text" name="last_name" placeholder="Last Name" value="<?php echo $lastName; ?>">
        </label>
    
        <input type="submit" name="submit">
    </form>
    

    handler.php

    session_start();
    
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    
        $firstName = $_POST['first_name'] ?: null;
        $lastName = $_POST['last_name'] ?: null;
    
        $errors = [];
    
        if (empty($firstName)) {
            $errors['first_name'] = 'Please enter your first name';
        }
    
        if (empty($lastName)) {
            $errors['last_name'] = 'Please enter your last name';
        }
    
        // If we have errors, set up our flash data so it is accessible on the next request and then go back to the form. 
        if ($errors) {
            $_SESSION['flash']['errors'] = $errors;
            $_SESSION['flash']['data'] = $_POST;
    
            header('Location: index.php');
            exit;
        }
    
        // We know there are no errors at this point so continue processing...
    
    }