PHP Intermediate

PHP Forms and User Input Handling

CodingerWeb
CodingerWeb
24 views 65 min read

PHP Forms and User Input

Forms are essential for collecting user input in web applications. PHP provides powerful tools to handle form data securely and efficiently.

HTML Form Basics

Create forms that send data to PHP scripts:

<!-- Basic HTML form -->
<form action="process.php" method="POST">
    <label for="name">Name:</label>
    <input type="text" id="name" name="name" required>
    
    <label for="email">Email:</label>
    <input type="email" id="email" name="email" required>
    
    <label for="age">Age:</label>
    <input type="number" id="age" name="age" min="1" max="120">
    
    <button type="submit">Submit</button>
</form>

GET vs POST Methods

Understanding when to use each method:

<?php
// GET method - data visible in URL
// Good for: search forms, filtering, bookmarkable pages
if ($_SERVER["REQUEST_METHOD"] == "GET") {
    $searchTerm = $_GET["search"] ?? "";
    echo "Searching for: " . htmlspecialchars($searchTerm);
}
?>

<form action="" method="GET">
    <input type="text" name="search" placeholder="Search...">
    <button type="submit">Search</button>
</form>

<?php
// POST method - data hidden from URL
// Good for: login forms, sensitive data, file uploads
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $username = $_POST["username"] ?? "";
    $password = $_POST["password"] ?? "";
    
    // Process login (never echo passwords!)
    if (!empty($username) && !empty($password)) {
        // Authenticate user
        echo "Processing login for: " . htmlspecialchars($username);
    }
}
?>

<form action="" method="POST">
    <input type="text" name="username" placeholder="Username" required>
    <input type="password" name="password" placeholder="Password" required>
    <button type="submit">Login</button>
</form>

Accessing Form Data

PHP superglobals for form data:

<?php
// $_POST - for POST method data
if (isset($_POST["submit"])) {
    $name = $_POST["name"];
    $email = $_POST["email"];
    $message = $_POST["message"];
}

// $_GET - for GET method data
$page = $_GET["page"] ?? 1;
$category = $_GET["category"] ?? "all";

// $_REQUEST - contains both GET and POST (not recommended)
$data = $_REQUEST["data"]; // Avoid using this

// Check if form was submitted
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // Process POST data
} elseif ($_SERVER["REQUEST_METHOD"] == "GET") {
    // Process GET data
}
?>

Form Validation

Always validate and sanitize user input:

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

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // Validate name
    if (empty($_POST["name"])) {
        $errors["name"] = "Name is required";
    } else {
        $name = trim($_POST["name"]);
        if (strlen($name) < 2) {
            $errors["name"] = "Name must be at least 2 characters";
        }
    }
    
    // Validate email
    if (empty($_POST["email"])) {
        $errors["email"] = "Email is required";
    } else {
        $email = trim($_POST["email"]);
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $errors["email"] = "Invalid email format";
        }
    }
    
    // Validate age
    if (!empty($_POST["age"])) {
        $age = (int)$_POST["age"];
        if ($age < 1 || $age > 120) {
            $errors["age"] = "Age must be between 1 and 120";
        }
    }
    
    // If no errors, process the form
    if (empty($errors)) {
        echo "Form submitted successfully!";
        // Save to database, send email, etc.
    }
}
?>

<form method="POST">
    <div>
        <label for="name">Name:</label>
        <input type="text" id="name" name="name" value="<?= htmlspecialchars($name) ?>">
        <?php if (isset($errors["name"])): ?>
            <span class="error"><?= $errors["name"] ?></span>
        <?php endif; ?>
    </div>
    
    <div>
        <label for="email">Email:</label>
        <input type="email" id="email" name="email" value="<?= htmlspecialchars($email) ?>">
        <?php if (isset($errors["email"])): ?>
            <span class="error"><?= $errors["email"] ?></span>
        <?php endif; ?>
    </div>
    
    <button type="submit">Submit</button>
</form>

Input Sanitization

Clean user input to prevent security issues:

<?php
function sanitizeInput($data) {
    $data = trim($data);                    // Remove whitespace
    $data = stripslashes($data);            // Remove backslashes
    $data = htmlspecialchars($data);        // Convert special chars
    return $data;
}

// Sanitize all POST data
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $name = sanitizeInput($_POST["name"]);
    $email = sanitizeInput($_POST["email"]);
    $message = sanitizeInput($_POST["message"]);
}

// Filter functions for specific data types
$email = filter_var($_POST["email"], FILTER_SANITIZE_EMAIL);
$url = filter_var($_POST["website"], FILTER_SANITIZE_URL);
$int = filter_var($_POST["age"], FILTER_SANITIZE_NUMBER_INT);

// Validation filters
$isValidEmail = filter_var($email, FILTER_VALIDATE_EMAIL);
$isValidUrl = filter_var($url, FILTER_VALIDATE_URL);
$isValidInt = filter_var($int, FILTER_VALIDATE_INT);
?>

Different Input Types

Handle various HTML5 input types:

<form method="POST" enctype="multipart/form-data">
    <!-- Text inputs -->
    <input type="text" name="username" placeholder="Username">
    <input type="email" name="email" placeholder="Email">
    <input type="password" name="password" placeholder="Password">
    <input type="url" name="website" placeholder="Website">
    <input type="tel" name="phone" placeholder="Phone">
    
    <!-- Number inputs -->
    <input type="number" name="age" min="1" max="120">
    <input type="range" name="rating" min="1" max="10">
    
    <!-- Date inputs -->
    <input type="date" name="birthdate">
    <input type="time" name="appointment">
    <input type="datetime-local" name="event">
    
    <!-- Selection inputs -->
    <select name="country">
        <option value="">Select Country</option>
        <option value="us">United States</option>
        <option value="ca">Canada</option>
        <option value="uk">United Kingdom</option>
    </select>
    
    <!-- Checkboxes -->
    <input type="checkbox" name="newsletter" value="1"> Subscribe to newsletter
    <input type="checkbox" name="hobbies[]" value="reading"> Reading
    <input type="checkbox" name="hobbies[]" value="sports"> Sports
    <input type="checkbox" name="hobbies[]" value="music"> Music
    
    <!-- Radio buttons -->
    <input type="radio" name="gender" value="male"> Male
    <input type="radio" name="gender" value="female"> Female
    <input type="radio" name="gender" value="other"> Other
    
    <!-- Textarea -->
    <textarea name="comments" rows="4" cols="50" placeholder="Comments"></textarea>
    
    <!-- File upload -->
    <input type="file" name="avatar" accept="image/*">
    
    <button type="submit">Submit</button>
</form>

<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // Handle different input types
    $username = $_POST["username"] ?? "";
    $age = (int)($_POST["age"] ?? 0);
    $birthdate = $_POST["birthdate"] ?? "";
    $country = $_POST["country"] ?? "";
    $newsletter = isset($_POST["newsletter"]);
    $hobbies = $_POST["hobbies"] ?? [];
    $gender = $_POST["gender"] ?? "";
    $comments = $_POST["comments"] ?? "";
    
    echo "Username: " . htmlspecialchars($username) . "<br>";
    echo "Age: " . $age . "<br>";
    echo "Newsletter: " . ($newsletter ? "Yes" : "No") . "<br>";
    echo "Hobbies: " . implode(", ", $hobbies) . "<br>";
}
?>

File Upload Handling

Handle file uploads securely:

<?php
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_FILES["avatar"])) {
    $file = $_FILES["avatar"];
    
    // Check for upload errors
    if ($file["error"] == UPLOAD_ERR_OK) {
        $fileName = $file["name"];
        $fileSize = $file["size"];
        $fileTmp = $file["tmp_name"];
        $fileType = $file["type"];
        
        // Validate file
        $allowedTypes = ["image/jpeg", "image/png", "image/gif"];
        $maxSize = 2 * 1024 * 1024; // 2MB
        
        if (!in_array($fileType, $allowedTypes)) {
            echo "Error: Only JPEG, PNG, and GIF files are allowed.";
        } elseif ($fileSize > $maxSize) {
            echo "Error: File size must be less than 2MB.";
        } else {
            // Generate unique filename
            $extension = pathinfo($fileName, PATHINFO_EXTENSION);
            $newFileName = uniqid() . "." . $extension;
            $uploadPath = "uploads/" . $newFileName;
            
            // Move uploaded file
            if (move_uploaded_file($fileTmp, $uploadPath)) {
                echo "File uploaded successfully: " . $newFileName;
            } else {
                echo "Error: Failed to upload file.";
            }
        }
    } else {
        echo "Error: " . $file["error"];
    }
}
?>

<form method="POST" enctype="multipart/form-data">
    <input type="file" name="avatar" accept="image/*" required>
    <button type="submit">Upload</button>
</form>

Form Security

Protect against common attacks:

<?php
session_start();

// CSRF Protection
function generateCSRFToken() {
    if (!isset($_SESSION["csrf_token"])) {
        $_SESSION["csrf_token"] = bin2hex(random_bytes(32));
    }
    return $_SESSION["csrf_token"];
}

function validateCSRFToken($token) {
    return isset($_SESSION["csrf_token"]) && 
           hash_equals($_SESSION["csrf_token"], $token);
}

// Process form with CSRF protection
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    if (!validateCSRFToken($_POST["csrf_token"] ?? "")) {
        die("CSRF token validation failed");
    }
    
    // Process form data...
}
?>

<form method="POST">
    <input type="hidden" name="csrf_token" value="<?= generateCSRFToken() ?>">
    
    <input type="text" name="username" required>
    <input type="password" name="password" required>
    <button type="submit">Login</button>
</form>

Practical Example: Contact Form

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

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // Validate and sanitize input
    $name = trim($_POST["name"] ?? "");
    $email = trim($_POST["email"] ?? "");
    $subject = trim($_POST["subject"] ?? "");
    $message = trim($_POST["message"] ?? "");
    
    // Validation
    if (empty($name)) {
        $errors["name"] = "Name is required";
    }
    
    if (empty($email)) {
        $errors["email"] = "Email is required";
    } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errors["email"] = "Invalid email format";
    }
    
    if (empty($subject)) {
        $errors["subject"] = "Subject is required";
    }
    
    if (empty($message)) {
        $errors["message"] = "Message is required";
    } elseif (strlen($message) < 10) {
        $errors["message"] = "Message must be at least 10 characters";
    }
    
    // If no errors, send email
    if (empty($errors)) {
        $to = "admin@example.com";
        $headers = "From: " . $email . "
";
        $headers .= "Reply-To: " . $email . "
";
        $headers .= "Content-Type: text/html; charset=UTF-8
";
        
        $emailBody = "<h3>Contact Form Submission</h3>";
        $emailBody .= "<p><strong>Name:</strong> " . htmlspecialchars($name) . "</p>";
        $emailBody .= "<p><strong>Email:</strong> " . htmlspecialchars($email) . "</p>";
        $emailBody .= "<p><strong>Subject:</strong> " . htmlspecialchars($subject) . "</p>";
        $emailBody .= "<p><strong>Message:</strong></p>";
        $emailBody .= "<p>" . nl2br(htmlspecialchars($message)) . "</p>";
        
        if (mail($to, $subject, $emailBody, $headers)) {
            $success = true;
            $name = $email = $subject = $message = ""; // Clear form
        } else {
            $errors["general"] = "Failed to send message. Please try again.";
        }
    }
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>Contact Form</title>
    <style>
        .error { color: red; font-size: 0.9em; }
        .success { color: green; padding: 10px; background: #e8f5e8; }
        .form-group { margin-bottom: 15px; }
        label { display: block; margin-bottom: 5px; }
        input, textarea, select { width: 100%; padding: 8px; }
    </style>
</head>
<body>
    <h1>Contact Us</h1>
    
    <?php if ($success): ?>
        <div class="success">Thank you! Your message has been sent.</div>
    <?php endif; ?>
    
    <?php if (isset($errors["general"])): ?>
        <div class="error"><?= $errors["general"] ?></div>
    <?php endif; ?>
    
    <form method="POST">
        <div class="form-group">
            <label for="name">Name:</label>
            <input type="text" id="name" name="name" value="<?= htmlspecialchars($name) ?>">
            <?php if (isset($errors["name"])): ?>
                <div class="error"><?= $errors["name"] ?></div>
            <?php endif; ?>
        </div>
        
        <div class="form-group">
            <label for="email">Email:</label>
            <input type="email" id="email" name="email" value="<?= htmlspecialchars($email) ?>">
            <?php if (isset($errors["email"])): ?>
                <div class="error"><?= $errors["email"] ?></div>
            <?php endif; ?>
        </div>
        
        <div class="form-group">
            <label for="subject">Subject:</label>
            <input type="text" id="subject" name="subject" value="<?= htmlspecialchars($subject) ?>">
            <?php if (isset($errors["subject"])): ?>
                <div class="error"><?= $errors["subject"] ?></div>
            <?php endif; ?>
        </div>
        
        <div class="form-group">
            <label for="message">Message:</label>
            <textarea id="message" name="message" rows="5"><?= htmlspecialchars($message) ?></textarea>
            <?php if (isset($errors["message"])): ?>
                <div class="error"><?= $errors["message"] ?></div>
            <?php endif; ?>
        </div>
        
        <button type="submit">Send Message</button>
    </form>
</body>
</html>

Practice Exercise

Create a user registration form that:

  • Collects username, email, password, and confirm password
  • Validates all fields with appropriate error messages
  • Checks if username/email already exists
  • Includes CSRF protection
  • Handles file upload for profile picture

Key Takeaways

  • Always validate and sanitize user input
  • Use POST for sensitive data, GET for searches
  • Implement CSRF protection for security
  • Handle file uploads carefully with validation
  • Provide clear error messages and user feedback