James Williams
Birmingham Newman University
jwilliams@staff.newman.ac.uk
3-hour session
1. User submits form
2. Browser sends data to server
3. PHP receives data via $_POST/$_GET
4. Validate and sanitize input
5. Process data (database, email, etc.)
6. Send response back to user
Complete Form Example:
<form method="POST" action="process.php" enctype="multipart/form-data">
<div class="form-group">
<label for="username">Username:</label>
<input type="text" name="username" id="username" required>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" name="email" id="email" required>
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" name="password" id="password" required>
</div>
<div class="form-group">
<label for="avatar">Profile Picture:</label>
<input type="file" name="avatar" id="avatar" accept="image/*">
</div>
<button type="submit">Register</button>
</form>
Basic Processing (process.php):
<?php
// Check if form was submitted
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// Get form data
$username = $_POST["username"];
$email = $_POST["email"];
$password = $_POST["password"];
// Basic validation
if (empty($username) || empty($email) || empty($password)) {
$error = "All fields are required";
} else {
// Process the data
echo "Username: " . htmlspecialchars($username) . "<br>";
echo "Email: " . htmlspecialchars($email) . "<br>";
echo "Registration successful!";
}
}
?>
Validation Functions:
function validateEmail($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL);
}
function validateUsername($username) {
// Username: 3-20 characters, alphanumeric and underscore
return preg_match("/^[a-zA-Z0-9_]{3,20}$/", $username);
}
function validatePassword($password) {
// Password: minimum 8 characters, at least one letter and number
return strlen($password) >= 8 &&
preg_match("/[a-zA-Z]/", $password) &&
preg_match("/[0-9]/", $password);
}
function sanitizeInput($input) {
return htmlspecialchars(trim($input), ENT_QUOTES, 'UTF-8');
}
Comprehensive Validation:
function validateRegistration($data) {
$errors = [];
// Username validation
if (empty($data["username"])) {
$errors["username"] = "Username is required";
} elseif (!validateUsername($data["username"])) {
$errors["username"] = "Username must be 3-20 characters";
}
// Email validation
if (empty($data["email"])) {
$errors["email"] = "Email is required";
} elseif (!validateEmail($data["email"])) {
$errors["email"] = "Invalid email format";
}
// Password validation
if (empty($data["password"])) {
$errors["password"] = "Password is required";
} elseif (!validatePassword($data["password"])) {
$errors["password"] = "Password must be at least 8 characters";
}
return $errors;
}
File Upload Processing:
function handleFileUpload($file) {
$errors = [];
$uploadDir = "uploads/";
// Check if file was uploaded
if ($file["error"] !== UPLOAD_ERR_OK) {
$errors[] = "File upload failed";
return $errors;
}
// Validate file type
$allowedTypes = ["image/jpeg", "image/png", "image/gif"];
if (!in_array($file["type"], $allowedTypes)) {
$errors[] = "Invalid file type";
}
// Validate file size (5MB max)
if ($file["size"] > 5 * 1024 * 1024) {
$errors[] = "File too large (max 5MB)";
}
// Generate unique filename
$extension = pathinfo($file["name"], PATHINFO_EXTENSION);
$filename = uniqid() . "." . $extension;
$filepath = $uploadDir . $filename;
// Move uploaded file
if (!move_uploaded_file($file["tmp_name"], $filepath)) {
$errors[] = "Failed to save file";
}
return $errors;
}
CSRF Token Implementation:
// Generate CSRF token
function generateCSRFToken() {
if (empty($_SESSION["csrf_token"])) {
$_SESSION["csrf_token"] = bin2hex(random_bytes(32));
}
return $_SESSION["csrf_token"];
}
// Verify CSRF token
function verifyCSRFToken($token) {
return isset($_SESSION["csrf_token"]) &&
hash_equals($_SESSION["csrf_token"], $token);
}
// Add token to form
<form method="POST" action="process.php">
<input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
<!-- form fields -->
</form>
// Verify in processing
if (!verifyCSRFToken($_POST["csrf_token"])) {
die("CSRF token validation failed");
}
Registration Processing:
function registerUser($data) {
// Validate input
$errors = validateRegistration($data);
if (!empty($errors)) {
return ["success" => false, "errors" => $errors];
}
// Check if user already exists
if (userExists($data["email"])) {
return ["success" => false, "errors" => ["email" => "Email already registered"]];
}
// Hash password
$hashedPassword = password_hash($data["password"], PASSWORD_DEFAULT);
// Create user
$userId = createUser([
"username" => $data["username"],
"email" => $data["email"],
"password" => $hashedPassword
]);
return ["success" => true, "user_id" => $userId];
}
Login Processing:
function loginUser($email, $password) {
// Validate input
if (empty($email) || empty($password)) {
return ["success" => false, "error" => "Email and password required"];
}
// Get user from database
$user = getUserByEmail($email);
if (!$user) {
return ["success" => false, "error" => "Invalid credentials"];
}
// Verify password
if (!password_verify($password, $user["password"])) {
return ["success" => false, "error" => "Invalid credentials"];
}
// Start session and store user data
session_start();
$_SESSION["user_id"] = $user["id"];
$_SESSION["username"] = $user["username"];
$_SESSION["logged_in"] = true;
return ["success" => true, "user" => $user];
}
Error Display System:
// Display errors function
function displayErrors($errors, $field) {
if (isset($errors[$field])) {
return "<span class='error'>" . htmlspecialchars($errors[$field]) . "</span>";
}
return "";
}
// Form with error display
<form method="POST" action="register.php">
<div class="form-group">
<label for="username">Username:</label>
<input type="text" name="username" id="username"
value="<?php echo isset($_POST['username']) ? htmlspecialchars($_POST['username']) : ''; ?>">
<?php echo displayErrors($errors, 'username'); ?>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" name="email" id="email"
value="<?php echo isset($_POST['email']) ? htmlspecialchars($_POST['email']) : ''; ?>">
<?php echo displayErrors($errors, 'email'); ?>
</div>
</form>
Product Search Form:
<form method="GET" action="search.php">
<input type="text" name="q" placeholder="Search products..."
value="<?php echo isset($_GET['q']) ? htmlspecialchars($_GET['q']) : ''; ?>">
<select name="category">
<option value="">All Categories</option>
<option value="electronics">Electronics</option>
<option value="clothing">Clothing</option>
<option value="books">Books</option>
</select>
<button type="submit">Search</button>
</form>
Contact Form:
<form method="POST" action="contact.php">
<input type="text" name="name" placeholder="Your Name" required>
<input type="email" name="email" placeholder="Your Email" required>
<textarea name="message" placeholder="Your Message" required></textarea>
<button type="submit">Send Message</button>
</form>
Time: 45 minutes
This task will help you master advanced form processing techniques
Take a break, ask questions, or catch up on the previous task.
Next: Secondary slides and Task 2
Security Checklist:
✓ Validate all input data
✓ Escape all output data
✓ Use CSRF tokens
✓ Hash passwords with password_hash()
✓ Validate file uploads
✓ Use HTTPS in production
✓ Implement rate limiting
✓ Log security events
✓ Keep PHP and dependencies updated
JavaScript AJAX Example:
document.getElementById('registerForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
fetch('register.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('Registration successful!');
} else {
displayErrors(data.errors);
}
})
.catch(error => {
console.error('Error:', error);
});
});
PHP Response (register.php):
header('Content-Type: application/json');
echo json_encode($result);
Client-side Validation:
function validateForm() {
let isValid = true;
const errors = {};
// Username validation
const username = document.getElementById('username').value;
if (username.length < 3 || username.length > 20) {
errors.username = 'Username must be 3-20 characters';
isValid = false;
}
// Email validation
const email = document.getElementById('email').value;
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
errors.email = 'Invalid email format';
isValid = false;
}
// Password validation
const password = document.getElementById('password').value;
if (password.length < 8) {
errors.password = 'Password must be at least 8 characters';
isValid = false;
}
return { isValid, errors };
}
Database Functions:
function createUser($userData) {
global $pdo;
$sql = "INSERT INTO users (username, email, password, created_at) VALUES (?, ?, ?, NOW())";
$stmt = $pdo->prepare($sql);
try {
$stmt->execute([
$userData['username'],
$userData['email'],
$userData['password']
]);
return $pdo->lastInsertId();
} catch (PDOException $e) {
error_log("Database error: " . $e->getMessage());
return false;
}
}
function getUserByEmail($email) {
global $pdo;
$sql = "SELECT * FROM users WHERE email = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$email]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
Email Functions:
function sendWelcomeEmail($email, $username) {
$to = $email;
$subject = "Welcome to Our E-commerce Site";
$message = "Hello $username,\n\nWelcome to our store!";
$headers = "From: noreply@example.com";
return mail($to, $subject, $message, $headers);
}
function sendPasswordReset($email, $token) {
$resetLink = "https://example.com/reset.php?token=" . $token;
$to = $email;
$subject = "Password Reset Request";
$message = "Click the following link to reset your password:\n$resetLink";
$headers = "From: noreply@example.com";
return mail($to, $subject, $message, $headers);
}
function sendOrderConfirmation($email, $orderDetails) {
$to = $email;
$subject = "Order Confirmation";
$message = "Thank you for your order!\n\nOrder ID: " . $orderDetails['id'];
$headers = "From: orders@example.com";
return mail($to, $subject, $message, $headers);
}
Analytics Implementation:
function logFormSubmission($formType, $success, $errors = []) {
$logData = [
'timestamp' => date('Y-m-d H:i:s'),
'form_type' => $formType,
'success' => $success,
'errors' => json_encode($errors),
'ip_address' => $_SERVER['REMOTE_ADDR'],
'user_agent' => $_SERVER['HTTP_USER_AGENT']
];
// Log to database or file
logToDatabase('form_submissions', $logData);
}
Time: 45 minutes
This task will help you build a complete e-commerce form processing system
MySQL Database Design - Database fundamentals and e-commerce schema