PHP: Form Handling in PHP
If PHP has a trump card, it's form handling. Tasks that other languages need a framework to accomplish, PHP has been able to do since day one. This lesson teaches you the single most practical skill in web development.
1. HTML Form Refresher
HTML
<form method="POST" action="process.php">
<!-- Form fields go here -->
<button type="submit">Submit</button>
</form>
| Attribute | Value | Description |
|---|---|---|
method |
GET or POST |
GET = fetch data, POST = modify data |
action |
URL ("" = same page) |
Where the data is sent |
name |
Field name | Required — PHP uses this to access the value |
🔥 Common Mistake: Every form field must have a
name attribute. If a field is missing name, PHP will never receive its value.
2. Receiving Different Field Types
(1) Text Fields
PHP
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';
$password = $_POST['password'] ?? '';
$bio = $_POST['bio'] ?? '';
}
?>
<form method="POST" action="">
<input type="text" name="name" placeholder="Username"><br>
<input type="email" name="email" placeholder="Email"><br>
<input type="password" name="password" placeholder="Password"><br>
<textarea name="bio" placeholder="About yourself"></textarea><br>
<button type="submit">Register</button>
</form>
(2) Selection Fields (Radio, Checkbox, Dropdown)
▶ サンプル: Handling Selection Fields
PHP
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$gender = $_POST['gender'] ?? '';
$skills = $_POST['skills'] ?? []; // Checkboxes come as an array
$city = $_POST['city'] ?? '';
echo "Gender: {$gender}<br>";
echo "Skills: " . implode(', ', $skills) . "<br>";
echo "City: {$city}<br>";
}
?>
<form method="POST" action="">
<label>Gender:</label>
<input type="radio" name="gender" value="male"> Male
<input type="radio" name="gender" value="female"> Female
<br>
<label>Skills:</label>
<input type="checkbox" name="skills[]" value="php"> PHP
<input type="checkbox" name="skills[]" value="mysql"> MySQL
<input type="checkbox" name="skills[]" value="js"> JavaScript
<br>
<label>City:</label>
<select name="city">
<option value="">Choose...</option>
<option value="beijing">Beijing</option>
<option value="shanghai">Shanghai</option>
</select>
<br>
<button type="submit">Submit</button>
</form>
⚠️ Warning: Checkbox groups must use
name="skills[]" (with square brackets) so PHP collects all checked values into an array. Without the brackets, you'll only receive the last checked value.
3. Form Repopulation (Preserving User Input)
The worst user experience is filling out a form, hitting submit, getting an error, and losing everything you typed. PHP makes this trivially easy to fix:
▶ サンプル: Form with Error Handling and Repopulation
PHP
<?php
$errors = [];
$name = $email = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
if ($name === '') {
$errors[] = 'Username is required';
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Invalid email format';
}
if (empty($errors)) {
echo "<h3 style='color:green'>Registration successful! Welcome, {$name}!</h3>";
$name = $email = ''; // Clear fields on success
} else {
echo "<ul style='color:red'>";
foreach ($errors as $e) echo "<li>{$e}</li>";
echo "</ul>";
}
}
?>
<form method="POST" action="">
<input type="text" name="name" placeholder="Username"
value="<?= htmlspecialchars($name) ?>"><br>
<input type="email" name="email" placeholder="Email"
value="<?= htmlspecialchars($email) ?>"><br>
<button type="submit">Register</button>
</form>
💡 Tip:
htmlspecialchars() is essential here — it prevents characters like ", <, and > in user input from breaking your HTML or injecting scripts (XSS attacks). We'll cover this in depth in Lesson 18.
4. Repopulating Radio Buttons and Checkboxes
PHP
<?php
$gender = $_POST['gender'] ?? 'male';
$skills = $_POST['skills'] ?? [];
?>
<!-- Radio buttons: use the checked attribute -->
<input type="radio" name="gender" value="male"
<?= $gender === 'male' ? 'checked' : '' ?>> Male
<!-- Checkboxes: check with in_array -->
<input type="checkbox" name="skills[]" value="php"
<?= in_array('php', $skills) ? 'checked' : '' ?>> PHP
<!-- Dropdown: use the selected attribute -->
<select name="city">
<option value="beijing" <?= $city === 'beijing' ? 'selected' : '' ?>>Beijing</option>
</select>
5. Detecting Form Submissions
PHP
<?php
// Method 1: Check the request method (recommended)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Process the form
}
// Method 2: Check for the submit button
if (isset($_POST['submit'])) {
// Process the form
}
// Method 3: Check if any POST data arrived
if (!empty($_POST)) {
// Process the form
}
?>
6. The PRG Pattern (Post-Redirect-Get)
Ever submitted a form, hit refresh, and seen that dreaded "Confirm form resubmission" dialog? The PRG pattern fixes it for good:
PHP
<?php
// prg.php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Process the data
$name = trim($_POST['name'] ?? '');
// Store a flash message in the session
$_SESSION['flash_message'] = "Welcome, {$name}!";
// Redirect to the same page with a GET request
header("Location: " . $_SERVER['PHP_SELF']);
exit;
}
// Display any flash message
if (isset($_SESSION['flash_message'])) {
echo "<div style='color:green'>{$_SESSION['flash_message']}</div>";
unset($_SESSION['flash_message']);
}
?>
<form method="POST" action="">
<input type="text" name="name" placeholder="Username">
<button type="submit">Register</button>
</form>
💡 Tip:
header("Location: ...") issues a redirect; exit stops the script immediately. The PRG flow: POST → process data → redirect to GET → user refreshes the GET page safely, no duplicate submission.
❓ よくある質問
Q Why aren't my checkboxes showing up in PHP?
A Check if the
name attribute includes [] (e.g., skills[]). Without the brackets, only the last checked value is sent. With name[], PHP collects them all into an array.Q Will my forms still work if the user disables JavaScript?
A Absolutely. PHP form processing happens entirely on the server — it doesn't depend on JavaScript at all. JavaScript only improves the experience (client-side validation, AJAX submissions), but the core functionality works without it.
Q
header("Location: ...") throws an error. What's wrong?A The most common cause is output before
header(). Anything — an echo, raw HTML, even a blank line or BOM before the <?php tag — counts as output. Make sure header() runs before any output, and save your file as UTF-8 without BOM.📖 まとめ
- Every form field needs a
nameattribute for PHP to receive its value - Different field types (text, radio, checkbox, select) are received differently
value="..."repopulates text fields;checked/selectedrepopulate choice fieldshtmlspecialchars()prevents XSS attacks when displaying user input$_SERVER['REQUEST_METHOD']tells you whether the request is GET or POST- The PRG pattern prevents duplicate submissions: POST → redirect → GET
📝 練習問題
- Build a full registration form with: username, email, password, gender (radio), interests (checkboxes), and city (dropdown). Use
var_dump()to inspect all received data on submission. - Add validation and repopulation to the form: username must not be empty, email must be valid, gender must be selected. Preserve all user input when validation fails.
- Implement the PRG pattern: after successful registration, redirect to the same page and display a green "Registration successful" message.