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