A basic form
HTML
<form method="post" action="submit.php">
<label>Name: <input type="text" name="name"></label>
<label>Email: <input type="email" name="email"></label>
<button type="submit">Send</button>
</form>Reading it in PHP
PHP
<?php
// submit.php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
echo "Thanks, " . htmlspecialchars($name);
}The name attribute in the HTML is the key in $_POST. No name, no
data.
GET vs POST
| GET | POST | |
|---|---|---|
| Data location | URL query string | request body |
| Visible in address bar | yes | no |
| Bookmarkable | yes | no |
| Size limit | ~2000 chars | effectively unlimited |
| Use for | searches, filters, pagination | logins, orders, anything that changes data |
Rule of thumb: GET reads, POST writes. Never delete or charge anything from a GET request — browsers and crawlers prefetch GET URLs.
Self-submitting form
PHP
<?php
$errors = [];
$name = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name'] ?? '');
if ($name === '') {
$errors[] = 'Name is required.';
}
if (!$errors) {
// save, then redirect (see below)
}
}
?>
<form method="post">
<input type="text" name="name" value="<?= htmlspecialchars($name) ?>">
<button>Submit</button>
</form>
<?php foreach ($errors as $e): ?>
<p style="color:red"><?= htmlspecialchars($e) ?></p>
<?php endforeach; ?>Re-filling the input with the submitted value (value="...") is what
makes a failed submission not feel broken.
Post/Redirect/Get
After a successful POST, redirect instead of rendering directly. This stops the browser from re-submitting the form when the user hits refresh:
PHP
<?php
// ... save the record ...
header('Location: /thank-you.php');
exit; // always exit after a redirectFile uploads
HTML
<form method="post" enctype="multipart/form-data">
<input type="file" name="photo">
<button>Upload</button>
</form>PHP
<?php
if (isset($_FILES['photo']) && $_FILES['photo']['error'] === UPLOAD_ERR_OK) {
$tmp = $_FILES['photo']['tmp_name'];
$name = basename($_FILES['photo']['name']); // basename() strips paths
move_uploaded_file($tmp, __DIR__ . "/uploads/" . $name);
}enctype="multipart/form-data" is required or $_FILES stays empty.
Always validate the file's real type and size — never trust the
browser-supplied name or MIME type.