Handling Forms in PHP
Why Forms Matter in Web Development
Forms are how websites collect information from visitors — login credentials, contact messages, search queries, checkout details. Everything you've learned so far about variables, arrays, and control flow comes together directly in this lesson, since handling a form means taking user input, storing it in variables, checking conditions on it, and deciding what to do next.
This lesson focuses on how PHP receives and processes form data. Validating that data safely and securely is covered in the next lesson, so keep in mind the examples here are simplified to focus purely on the mechanics of form handling.
How HTML Forms Send Data to PHP
An HTML form doesn't process anything by itself — it collects input and sends it to a specified PHP file when submitted. Two attributes on the <form> tag control this: action (where the data goes) and method (how it's sent).
html
<form action="process.php" method="post">
<input type="text" name="username">
<input type="email" name="email">
<button type="submit">Submit</button>
</form>
When this form is submitted, the browser sends the username and email values to process.php, where PHP can access them using the name attribute of each field as the key.
The POST Method
POST sends form data invisibly in the request body, rather than in the URL. It's the standard choice for forms handling sensitive data (passwords, personal details) or forms that create or change data (registrations, comments, orders).
php
<?php // process.php $username = $_POST['username']; $email = $_POST['email']; echo "Username: $username, Email: $email";
$_POST is a PHP superglobal — a built-in array automatically populated with data whenever a form is submitted using the POST method. The array keys directly match the name attributes from the HTML form.
The GET Method
GET sends form data as part of the URL itself, visible in the address bar (process.php?search=laptop). It's typically used for search forms, filters, or any scenario where bookmarking or sharing the resulting URL is useful.
html
<form action="search.php" method="get">
<input type="text" name="query">
<button type="submit">Search</button>
</form>
php
<?php // search.php $searchQuery = $_GET['query']; echo "You searched for: $searchQuery";
If a user searches for "laptop," the resulting URL would look like search.php?query=laptop, making GET naturally suited for shareable or bookmarkable results pages.
GET vs POST: Choosing the Right Method
Aspect GET POST
------------------------------------------------------------
Data visibility Visible in the URL Hidden in the
request body
Data size limit Limited (URL length Much larger
restrictions apply) limit
Best for Search, filters, Logins, forms
shareable links with sensitive
or changing data
Bookmarkable? Yes No
Cached by browsers? Can be Not by default
Checking How the Form Was Submitted
A common pattern is having a single PHP file both display a form and process its submission, distinguishing between the two using the request method.
php
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'];
echo "Thank you, $name!";
} else {
// Show the form (this runs when the page first loads)
}
$_SERVER['REQUEST_METHOD'] tells you whether the current request is a GET (typically the initial page load) or a POST (the form submission), allowing one file to handle both the display and the processing logic.
Avoiding Undefined Key Warnings
If a form field is missing, empty, or the page loads without a submission at all, directly accessing $_POST['fieldname'] triggers a warning. Using the null coalescing operator (??) guards against this cleanly.
php
<?php $name = $_POST['name'] ?? ''; $comments = $_POST['comments'] ?? 'No comments provided'; echo $name; echo $comments;
This is a habit worth building early, since real forms are rarely submitted perfectly every time — fields get skipped, JavaScript sometimes fails, and users occasionally tamper with requests directly.
Handling Checkboxes and Multiple Values
Checkboxes behave differently from text fields: if a checkbox isn't checked, its key won't exist in $_POST at all, rather than existing with an empty value.
html
<form action="process.php" method="post">
<label><input type="checkbox" name="subscribe" value="yes"> Subscribe to newsletter</label>
<button type="submit">Submit</button>
</form>
php
<?php $subscribed = isset($_POST['subscribe']) ? "Yes" : "No"; echo "Subscribed: $subscribed";
For a group of checkboxes representing multiple selections, using array-style naming lets PHP collect them all into a single array:
html
<input type="checkbox" name="interests[]" value="Sports"> <input type="checkbox" name="interests[]" value="Music"> <input type="checkbox" name="interests[]" value="Travel">
php
<?php
$interests = $_POST['interests'] ?? [];
foreach ($interests as $interest) {
echo $interest . "\n";
}
The square brackets in name="interests[]" tell PHP to collect every checked value into an array under the interests key, rather than overwriting a single value each time.
Handling Dropdowns and Radio Buttons
Dropdowns (<select>) and radio button groups both submit a single value, accessed the same straightforward way as a text field.
html
<select name="country">
<option value="IN">India</option>
<option value="US">United States</option>
</select>
php
<?php $country = $_POST['country'] ?? ''; echo "Selected country: $country";
A Complete Basic Example
Putting the pieces together, here's a simplified contact form that displays itself and processes its own submission:
php
<?php
$message = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';
if (!empty($name) && !empty($email)) {
$message = "Thank you, $name! We'll contact you at $email.";
} else {
$message = "Please fill in all fields.";
}
}
?>
<!DOCTYPE html>
<html>
<body>
<?php if ($message): ?>
<p><?php echo $message; ?></p>
<?php endif; ?>
<form method="post">
<input type="text" name="name" placeholder="Your name">
<input type="email" name="email" placeholder="Your email">
<button type="submit">Submit</button>
</form>
</body>
</html>
Notice the form's action attribute is omitted here — when left out, the form submits back to the same file it's already on, which is a common and convenient pattern for simple forms.
What's Next
- This lesson covered the mechanics of receiving form data, but real applications can never trust user input blindly — data needs to be validated and sanitized before it's used or stored anywhere. That's the exact focus of the next lesson, covering form validation and basic security practices.