PHP
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions
-
Section 4: Object-Oriented PHP
-
Section 5: Working with Data
-
Section 6: Modern PHP (PHP 8)
-
Section 7: Working with Files and Networking
-
Section 8: Common PHP Frameworks Overview
-
Section 9: Tooling and Ecosystem
-
Section 10: Practical Projects
-
Section 11: Interview Practice
-
Section 12: More Standard Library
-
Section 13: Data Structures and Algorithms in PHP
-
Section 14: More Practice Exercises
-
Section 15: More Security and Best Practices
-
Section 16: More Testing and Tooling
-
Section 17: WordPress-Style CMS Concepts
-
Section 18: Advanced OOP Practice
-
Section 19: More Web Fundamentals
-
Section 20: Database Practice
-
Section 21: PHP Manual: Array Functions
-
Section 22: PHP Manual: Date and Calendar Functions
-
Section 23: PHP Manual: Filesystem and Directory Functions
-
Section 24: PHP Manual: Filter and Var Handling
-
Section 25: PHP Manual: Math Functions
-
Section 26: PHP Manual: JSON and XML
-
Section 27: PHP Manual: Network and Stream Functions
-
Section 28: PHP Manual: Error and Exception Handling
-
Section 29: PHP Manual: Output Control and Misc
-
Section 30: PHP Manual: FTP, Zip, and Mail
-
Section 31: Modern PHP Frameworks Deep Dive
-
Section 32: PHP Design Patterns
-
Section 33: More Practice Exercises
-
Section 34: PHP Performance and Deployment
-
Section 35: More Interview Practice
-
Section 36: More PHP Standard Library
-
Section 37: PHP Concurrency and Async
-
Section 38: More Web Development Practice
-
Section 39: PHP Testing Deep Dive
-
Section 40: Composer and Package Development
-
Section 41: PHP Security Deep Dive
-
Section 42: More Practical Projects
-
Section 43: Legacy PHP Maintenance
-
Section 44: More Algorithm Practice
-
Section 45: Final Practice and Review
-
Section 46: PHP for E-Commerce Patterns
-
Section 47: PHP API Design Deep Dive
-
Section 48: PHP Caching Strategies
-
Section 49: PHP Queue and Background Jobs
-
Section 50: PHP Multi-Tenancy Patterns
-
Section 51: PHP Real-Time Features
-
Section 52: PHP CMS and Content Modeling
-
Section 53: PHP Internationalization
-
Section 54: More Framework-Specific Practice
-
Section 55: PHP Legacy Code Refactoring
-
Section 56: More Practice Projects Round 2
-
Section 57: PHP Command-Line Applications
-
Section 58: PHP and Microservices
-
Section 59: More Interview and Review Round 2
45: Building a Simple Contact Form Handler
A few years ago, I was reviewing a project for a junior dev who had built a beautiful landing page for a client. Everything looked polished, but the client complained that they weren't receiving any lead emails. The dev was baffled because, in his tests, the "Submit" button worked perfectly—the page would refresh, and he'd see a success message. It turned out he was checking for the form data using $_GET instead of $_POST, and since he'd accidentally left a query string in his test URL, it worked locally but failed completely in production. It's a classic "ghost in the machine" moment that happens when we forget exactly how the browser and server shake hands during a form submission.
Processing the Request and Capturing Data
When a user hits that submit button, the browser bundles up the input values and sends them to the server. To handle this in PHP, your first move should always be verifying that the request actually happened via the method you expected. I always wrap my handler in a check for $_SERVER["REQUEST_METHOD"]. If you don't, your script might try to process an empty form the moment the page loads, which usually leads to a screen full of "Field required" errors before the user has even typed a single character.
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$name = $_POST['user_name'] ?? '';
$email = $_POST['user_email'] ?? '';
$message = $_POST['user_message'] ?? '';
// Process the data here
}
Notice the null coalescing operator (??) there. I use this instead of isset() because it keeps the code clean. It essentially says, "Give me the value from the POST array, but if it's not there, just make it an empty string." This prevents those annoying "Undefined index" notices from cluttering your logs.
Cleaning and Validating the Input
Now, here is where most people get lazy: they trust the user. Never trust the user. Even if you have required attributes in your HTML, a savvy user (or a bot) can bypass those easily. You need to validate the data on the server side. For a contact form, the email address is the most critical piece. I recommend filter_var() with the FILTER_VALIDATE_EMAIL flag. It's far more reliable than trying to write your own complex regular expression for email patterns.
$errors = [];
if (empty($name)) {
$errors[] = "Please tell us your name.";
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = "That doesn't look like a valid email address.";
}
if (strlen($message) < 10) {
$errors[] = "Your message is a bit too short. Please provide more detail.";
}
By collecting errors in an array, you can loop through them and display them all at once to the user, rather than making them submit the form five times to find five different mistakes. It's a small touch, but it makes the experience feel professional.
Preventing the Double-Submit Loop
Once the data is validated and you've used mail() or a library like PHPMailer to send the message, you'll be tempted to just echo "Thank you!". Don't do that. If the user hits the refresh button on their browser, the browser will attempt to re-send the POST data, and your client will receive the same email again. And again. And again.
The fix is the Post-Redirect-Get (PRG) pattern. After the email is successfully sent, you send a header("Location: ...") redirect to a dedicated "thank you" page or back to the form with a success flag in the URL. This clears the POST buffer and ensures a refresh doesn't trigger a duplicate email.
if (empty($errors)) {
$to = "admin@example.com";
$subject = "New Contact Form Submission";
$body = "From: $name \nEmail: $email \n\n$message";
if (mail($to, $subject, $body)) {
header("Location: success.php");
exit;
} else {
$errors[] = "Server error: Could not send email.";
}
}
Remember to call exit; immediately after your header redirect. If you don't, the rest of your script will continue to execute in the background even though the user has been told to go elsewhere. I've seen scripts accidentally send two emails because the developer forgot that header() doesn't actually stop the script from running.
📋 Practical Task
Build a Lead Capture Handler with Validation
Create a PHP script that handles a contact form with three fields: full_name, email_address, and company_size (a dropdown with options like "1-10", "11-50", "51+").
Your script must implement the following:
- Verify the request method is
POST. - Validate that the email is a properly formatted email address using
filter_var(). - Ensure
full_nameis not empty and is at least 3 characters long. - Verify that
company_sizematches one of the three expected options (to prevent injected values). - If validation fails, display a list of all errors.
- If validation succeeds, simulate sending an email (using a
var_dumporechosince you may not have a mail server configured) and then redirect the user to a page calledthanks.html.
There are no comments for now.