PHP Form Handling

Validate, sanitize, and process form data securely

๐Ÿ›ก๏ธ What is PHP Form Handling?

Form handling involves validating, sanitizing, and processing user input securely. Proper handling prevents security vulnerabilities, ensures data integrity, and provides better user experience with helpful error messages and feedback.


<?php
if($_SERVER["REQUEST_METHOD"] == "POST") {
    // Validate input
    $email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
    
    // Sanitize input
    $name = htmlspecialchars($_POST['name']);
    
    // Process data
    echo "Welcome, $name!";
}
?>
                                    

Form Handling Concepts

โœ…

Validation

Check if user input meets requirements like format, length, and type. Ensures data quality before processing and provides feedback for corrections.

<?php
if(empty($name)) {
    $error = "Name is required";
}
?>
๐Ÿงน

Sanitization

Clean user input by removing dangerous characters and code. Prevents XSS attacks and ensures safe data storage by filtering malicious content.

<?php
$clean = htmlspecialchars($input);
$email = filter_var($email, FILTER_SANITIZE_EMAIL);
?>
๐Ÿ”’

Security

Protect against common attacks like SQL injection, XSS, and CSRF. Use prepared statements, escape output, and validate all input from users.

<?php
// Prevent SQL injection
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
?>
๐Ÿ’ฌ

Error Handling

Display helpful error messages to guide users. Show specific validation errors, maintain form data after errors, and provide clear instructions for correction.

<?php
if($errors) {
    foreach($errors as $error) {
        echo "<p class='error'>$error</p>";
    }
}
?>

๐Ÿ”น Basic Form Validation

Check if required fields are filled:

<?php
$errors = [];

if($_SERVER["REQUEST_METHOD"] == "POST") {
    // Check if name is empty
    if(empty($_POST['name'])) {
        $errors[] = "Name is required";
    }
    
    // Check if email is empty
    if(empty($_POST['email'])) {
        $errors[] = "Email is required";
    }
    
    // Check if password is empty
    if(empty($_POST['password'])) {
        $errors[] = "Password is required";
    }
    
    // If no errors, process form
    if(empty($errors)) {
        echo "Form submitted successfully!";
    }
}

// Display errors
if(!empty($errors)) {
    foreach($errors as $error) {
        echo "<p style='color: red;'>$error</p>";
    }
}
?>

Output (with errors):

Name is required

Email is required

Password is required

๐Ÿ”น Email Validation

Validate email format using filter_var():

<?php
if($_SERVER["REQUEST_METHOD"] == "POST") {
    $email = $_POST['email'];
    
    // Validate email format
    if(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        echo "Invalid email format!";
    } else {
        echo "Valid email: $email";
    }
}
?>

<form method="POST">
    <input type="email" name="email" placeholder="Enter email">
    <button type="submit">Validate</button>
</form>

Output:

Valid email: [email protected]

๐Ÿ”น Sanitizing Input

Clean user input to prevent XSS attacks:

<?php
if($_SERVER["REQUEST_METHOD"] == "POST") {
    // Dangerous input with HTML/JavaScript
    $dangerous = $_POST['comment'];
    
    // Sanitize using htmlspecialchars()
    $safe = htmlspecialchars($dangerous, ENT_QUOTES, 'UTF-8');
    
    echo "<h4>Original (dangerous):</h4>";
    echo "<pre>" . htmlspecialchars($dangerous) . "</pre>";
    
    echo "<h4>Sanitized (safe):</h4>";
    echo "<p>$safe</p>";
}
?>

<form method="POST">
    <textarea name="comment" placeholder="Enter comment"></textarea>
    <button type="submit">Submit</button>
</form>

Example:

Input: <script>alert('XSS')</script>

Sanitized: &lt;script&gt;alert('XSS')&lt;/script&gt;

๐Ÿ”น Retaining Form Values

Keep form data after validation errors:

<?php
$name = $email = "";
$errors = [];

if($_SERVER["REQUEST_METHOD"] == "POST") {
    $name = $_POST['name'];
    $email = $_POST['email'];
    
    if(empty($name)) {
        $errors[] = "Name is required";
    }
    
    if(empty($email)) {
        $errors[] = "Email is required";
    }
    
    if(empty($errors)) {
        echo "Success! Name: $name, Email: $email";
    }
}
?>

<form method="POST">
    <input type="text" name="name" value="<?php echo htmlspecialchars($name); ?>" placeholder="Name">
    <br>
    <input type="email" name="email" value="<?php echo htmlspecialchars($email); ?>" placeholder="Email">
    <br>
    <button type="submit">Submit</button>
</form>

<?php
foreach($errors as $error) {
    echo "<p style='color: red;'>$error</p>";
}
?>

๐Ÿ”น Password Validation

Validate password strength and confirmation:

<?php
if($_SERVER["REQUEST_METHOD"] == "POST") {
    $password = $_POST['password'];
    $confirm = $_POST['confirm_password'];
    $errors = [];
    
    // Check minimum length
    if(strlen($password) < 8) {
        $errors[] = "Password must be at least 8 characters";
    }
    
    // Check if passwords match
    if($password !== $confirm) {
        $errors[] = "Passwords do not match";
    }
    
    // Check for uppercase letter
    if(!preg_match("/[A-Z]/", $password)) {
        $errors[] = "Password must contain at least one uppercase letter";
    }
    
    // Check for number
    if(!preg_match("/[0-9]/", $password)) {
        $errors[] = "Password must contain at least one number";
    }
    
    if(empty($errors)) {
        echo "Password is strong and valid!";
    } else {
        foreach($errors as $error) {
            echo "<p style='color: red;'>$error</p>";
        }
    }
}
?>

๐Ÿ”น File Upload Validation

Validate uploaded files for security:

<?php
if($_SERVER["REQUEST_METHOD"] == "POST") {
    $file = $_FILES['upload'];
    $errors = [];
    
    // Check if file was uploaded
    if($file['error'] !== UPLOAD_ERR_OK) {
        $errors[] = "File upload failed";
    }
    
    // Check file size (max 2MB)
    $maxSize = 2 * 1024 * 1024; // 2MB in bytes
    if($file['size'] > $maxSize) {
        $errors[] = "File is too large (max 2MB)";
    }
    
    // Check file type
    $allowed = ['jpg', 'jpeg', 'png', 'gif'];
    $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
    if(!in_array($ext, $allowed)) {
        $errors[] = "Invalid file type. Allowed: " . implode(", ", $allowed);
    }
    
    if(empty($errors)) {
        // Move uploaded file
        $destination = "uploads/" . basename($file['name']);
        move_uploaded_file($file['tmp_name'], $destination);
        echo "File uploaded successfully!";
    } else {
        foreach($errors as $error) {
            echo "<p style='color: red;'>$error</p>";
        }
    }
}
?>

<form method="POST" enctype="multipart/form-data">
    <input type="file" name="upload">
    <button type="submit">Upload</button>
</form>

๐Ÿ”น Complete Contact Form Example

Full form with validation, sanitization, and error handling:

<?php
$name = $email = $message = "";
$errors = [];
$success = false;

if($_SERVER["REQUEST_METHOD"] == "POST") {
    // Get and sanitize input
    $name = trim($_POST['name']);
    $email = trim($_POST['email']);
    $message = trim($_POST['message']);
    
    // Validate name
    if(empty($name)) {
        $errors[] = "Name is required";
    } elseif(strlen($name) < 2) {
        $errors[] = "Name must be at least 2 characters";
    }
    
    // Validate email
    if(empty($email)) {
        $errors[] = "Email is required";
    } elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errors[] = "Invalid email format";
    }
    
    // Validate message
    if(empty($message)) {
        $errors[] = "Message is required";
    } elseif(strlen($message) < 10) {
        $errors[] = "Message must be at least 10 characters";
    }
    
    // If no errors, process form
    if(empty($errors)) {
        // Sanitize for display/storage
        $name = htmlspecialchars($name, ENT_QUOTES, 'UTF-8');
        $email = filter_var($email, FILTER_SANITIZE_EMAIL);
        $message = htmlspecialchars($message, ENT_QUOTES, 'UTF-8');
        
        // Here you would typically:
        // - Send email
        // - Save to database
        // - etc.
        
        $success = true;
        
        // Clear form
        $name = $email = $message = "";
    }
}
?>

<!DOCTYPE html>
<html>
<head>
    <style>
        .error { color: red; margin: 5px 0; }
        .success { color: green; padding: 10px; background: #d4edda; border: 1px solid #c3e6cb; }
        input, textarea { display: block; margin: 10px 0; padding: 8px; width: 300px; }
    </style>
</head>
<body>

<h2>Contact Form</h2>

<?php if($success): ?>
    <div class="success">Thank you! Your message has been sent.</div>
<?php endif; ?>

<?php if(!empty($errors)): ?>
    <div class="error">
        <strong>Please fix the following errors:</strong>
        <ul>
            <?php foreach($errors as $error): ?>
                <li><?php echo $error; ?></li>
            <?php endforeach; ?>
        </ul>
    </div>
<?php endif; ?>

<form method="POST" action="">
    <label>Name:</label>
    <input type="text" name="name" value="<?php echo htmlspecialchars($name); ?>">
    
    <label>Email:</label>
    <input type="email" name="email" value="<?php echo htmlspecialchars($email); ?>">
    
    <label>Message:</label>
    <textarea name="message" rows="5"><?php echo htmlspecialchars($message); ?></textarea>
    
    <button type="submit">Send Message</button>
</form>

</body>
</html>

๐Ÿ”น Preventing CSRF Attacks

Use tokens to prevent Cross-Site Request Forgery:

<?php
session_start();

// Generate CSRF token
if(empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}

if($_SERVER["REQUEST_METHOD"] == "POST") {
    // Verify CSRF token
    if(!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
        die("CSRF token validation failed!");
    }
    
    // Process form...
    echo "Form processed securely!";
}
?>

<form method="POST">
    <!-- Hidden CSRF token field -->
    <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
    
    <input type="text" name="data" placeholder="Enter data">
    <button type="submit">Submit</button>
</form>

๐Ÿ’ก Form Handling Best Practices:

  • Always Validate: Never trust user input, validate everything
  • Sanitize Output: Use htmlspecialchars() when displaying user data
  • Use Prepared Statements: Prevent SQL injection with PDO or MySQLi
  • Validate on Server: Client-side validation is not enough
  • Provide Clear Errors: Help users understand what went wrong
  • Use HTTPS: Encrypt data transmission for sensitive forms
  • Limit File Uploads: Restrict file types and sizes
  • Rate Limiting: Prevent spam and abuse with rate limits

๐Ÿ”’ Common Security Functions:

  • htmlspecialchars(): Prevent XSS attacks
  • filter_var(): Validate and sanitize data
  • trim(): Remove whitespace from input
  • strip_tags(): Remove HTML and PHP tags
  • password_hash(): Hash passwords securely
  • mysqli_real_escape_string(): Escape special characters (use prepared statements instead)

๐Ÿง  Test Your Knowledge

Which function should you use to prevent XSS attacks when displaying user input?