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: <script>alert('XSS')</script>
๐น 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)