Fix PHP User Registration System: Valid Input Errors

I’m working on a registration system but have hit a bit of a roadblock. I set it up so that when a session is active (session_start()), it redirects to #notLoggedIn if the user is already logged in. The logic then checks if a form has been submitted using $_SERVER["REQUEST_METHOD"] == "POST", and if so, it begins validating the form fields. Currently, I’m performing several checks to validate the form (e.g., checking for empty fields, filtering out unallowed characters, and assigning variables to cleaned input).

Once I perform these checks, the script prepares an INSERT statement to add data to the database. However, the problem I’m facing is that it doesn’t wait for the checks to complete before inserting into the database. It seems like the script is trying to execute everything in one go and just redirects to index.php, regardless of whether there are errors in the fields.

Error Code:

codesession_start();

if (isset($_SESSION['logged_in'])) {

header('Location: #notLoggedIn');
exit;

} else {

if ($_SERVER["REQUEST_METHOD"] == "POST") {

if (empty($_POST["field"])) {
// display error
} else if (/* condition to check unallowed characters */) {
// display another error
} else {
$name = $_POST["name"]; // Example of assigning a checked input
}

// Like 4-5 other checks running in the same way as above

$query = $pdo->prepare('INSERT INTO table (a, b, c, d, e) VALUES (?,?,?,?,?)');

$query->bindValue(1, $value1); // Set $value1, $value2, etc. to appropriate variables
$query->bindValue(2, $value2);
$query->bindValue(3, $value3);
$query->bindValue(4, $value4);
$query->bindValue(5, $value5);

$query->execute();

header('Location: index.php');
exit;
}
}

Let’s go through this code step-by-step, adding necessary corrections, comments, and explanations along the way.

Problem:

The code provided aims to:

  1. Check if the user is logged in.
  2. If the user is not logged in, it processes form data sent via a POST request.
  3. Validate various form fields.
  4. Insert validated data into a database table.
  5. Redirect back to the main page after insertion.

However, there are a few issues with the code, such as missing validation checks and incorrect placeholders in the prepared statement.

Correct Code:

code<?php
session_start();

// Check if user is logged in
if (!isset($_SESSION['logged_in'])) {
// User is not logged in; redirect to a "not logged in" section or page
header('Location: #notLoggedIn');
exit;
}

if ($_SERVER["REQUEST_METHOD"] == "POST") {
// Array to store error messages
$errors = [];

// Check if the 'name' field is empty
if (empty($_POST['name'])) {
$errors[] = "Name field is required.";
} elseif (!preg_match("/^[a-zA-Z-' ]*$/", $_POST['name'])) {
// Check if 'name' contains only allowed characters
$errors[] = "Only letters and white space allowed in Name.";
} else {
// Assign the sanitized input to a variable
$name = htmlspecialchars(trim($_POST['name']));
}

// Additional validation checks for other fields
if (empty($_POST['email'])) {
$errors[] = "Email field is required.";
} elseif (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
$errors[] = "Invalid email format.";
} else {
$email = htmlspecialchars(trim($_POST['email']));
}

if (empty($_POST['age'])) {
$errors[] = "Age field is required.";
} elseif (!is_numeric($_POST['age']) || $_POST['age'] <= 0) {
$errors[] = "Please enter a valid age.";
} else {
$age = (int)$_POST['age'];
}

// Example additional fields: $city and $occupation
$city = !empty($_POST['city']) ? htmlspecialchars(trim($_POST['city'])) : null;
$occupation = !empty($_POST['occupation']) ? htmlspecialchars(trim($_POST['occupation'])) : null;

// Only proceed if there are no errors
if (empty($errors)) {
// Database insertion
try {
// Create a prepared statement
$query = $pdo->prepare('INSERT INTO table_name (name, email, age, city, occupation) VALUES (?, ?, ?, ?, ?)');

// Bind parameters to their corresponding values
$query->bindValue(1, $name);
$query->bindValue(2, $email);
$query->bindValue(3, $age);
$query->bindValue(4, $city);
$query->bindValue(5, $occupation);

// Execute the prepared statement
$query->execute();

// Redirect to a success page or the index page
header('Location: index.php');
exit;
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
} else {
// If there are errors, display them
foreach ($errors as $error) {
echo "<p style='color:red;'>$error</p>";
}
}
}
?>

Explanation:

  1. Session Check:
    • The session_start() function starts a session.
    • We check if the $_SESSION['logged_in'] variable is set. If it’s not, we assume the user is not logged in and redirect them to a specific section or page with header('Location: #notLoggedIn');.
  2. Form Submission Check:
    • $_SERVER["REQUEST_METHOD"] == "POST" checks if the form has been submitted via a POST request.
  3. Validation:
    • Name: Checks if the name field is empty and, if not, whether it only contains letters and white spaces. If valid, we sanitize and assign the value to $name.
    • Email: Checks if the email field is empty and if it’s in a valid email format using filter_var().
    • Age: Ensures age is numeric and greater than zero, casting it to an integer if valid.
    • Other fields (e.g., city and occupation) can be added similarly, using optional sanitization if they are allowed to be empty.
  4. Error Handling:
    • Errors are collected in an array ($errors). If any errors are present, we display them instead of proceeding to the database insertion.
  5. Database Insertion:
    • Using PDO (PHP Data Objects), we prepare an SQL statement with placeholders.
    • Each placeholder is bound to a validated value using $query->bindValue().
    • The execute() method runs the prepared statement, inserting the data into the database.
  6. Redirection:
    • Upon successful insertion, the user is redirected to index.php. If there is an error in the database operation, it will be caught and displayed.

Final Thought:

In wrapping up, implementing user session management and form validation, as shown in this example, ensures a secure and reliable process for data handling in PHP applications. By carefully validating user inputs, handling errors, and managing database operations with prepared statements, we create a more robust and user-friendly experience. This approach not only improves security preventing SQL injection and data inconsistencies but also enhances the overall usability of the application, contributing to a seamless user journey. Remember, building secure, efficient code is always worth the effort, as it forms the foundation of any successful web application.

    Related blog posts