PHP Forms

Receive form data with $_GET and $_POST, choose the right method, keep forms sticky and redirect after a successful submission.

Lesson 10 of 86Intermediate17 min read

Forms are how websites listen. Search boxes, contact forms, sign-in pages, checkouts and comment boxes all collect information from visitors and send it to the server. On the server, PHP receives that information and decides what to do with it: search a database, send an email or save an order.

You already know how to build forms with HTML from the HTML forms lesson. This lesson is about the other side: reading the submitted values in PHP. They arrive in two special arrays, $_GET and $_POST, depending on how the form was sent.

You'll learn when to use GET and when to use POST, how to read text fields, checkboxes and select boxes, how to show values back safely, how to keep a form filled in when something needs correcting, and how to avoid the "resubmit form?" warning with a redirect.

From HTML form to PHP

HTML
<form action="search.php" method="get">
  <input name="q">
  <button>Search</button>
</form>
  • action is the PHP file that receives the data. Leave it out, or use an empty value, to send the form to the same page.
  • method is how the data is sent: get or post.
  • The name attribute of each field becomes the key in PHP. An input with name="q" arrives as $_GET['q'].

A field without a name isn't sent at all, which is one of the most common reasons a value seems to be "missing".

GET versus POST

GETPOST
Where the data goesIn the address: search.php?q=lampIn the request body, not the address
Bookmarkable and shareableYesNo
Good forSearches, filters, page numbersSign-ups, orders, messages, anything that changes data
PHP array$_GET$_POST

Use GET for requests that only read data and that people might want to bookmark. Use POST for anything that creates, changes or deletes data, or contains private information, so it doesn't end up in browser history and server logs.

Reading values safely

A form field might be missing, for example when the page is first opened. Read values with the null coalescing operator and trim stray spaces:

PHP
$name = trim($_POST['name'] ?? '');

To check whether the form has been submitted at all, look at the request method:

PHP
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // handle the submitted form
}

Whenever you print a submitted value back into the page, wrap it in htmlspecialchars(). Otherwise a visitor could type HTML or JavaScript into a field and have it run in other people's browsers, an attack called cross-site scripting (XSS).

Checkboxes, selects and sticky forms

  • A checkbox is only sent when it's ticked, so test it with isset($_POST['newsletter']).
  • A select sends the value of the chosen option.
  • Several checkboxes with the same name ending in [], such as name="toppings[]", arrive in PHP as an array.

A sticky form puts the submitted values back into the fields, so people don't have to retype everything when one field needs fixing: value="<?= htmlspecialchars($name) ?>". For a select, add selected to the option that matches, and for a checkbox, add checked when it was ticked.

PHP Forms Syntax

Form handling pattern

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $email = trim($_POST['email'] ?? '');
    $agree = isset($_POST['agree']);
    // validate and save...
    header('Location: thanks.php');
    exit;
}
$q = $_GET['q'] ?? '';
?>
<input name="email" value="<?= htmlspecialchars($email ?? '') ?>">

PHP Forms Summary

  • A field's name attribute becomes its key in $_GET or $_POST.
  • Use GET for reading and searching, POST for changing data or private information.
  • Read values with $_POST['field'] ?? '', and check $_SERVER['REQUEST_METHOD'].
  • Always escape output with htmlspecialchars() to prevent XSS.
  • Checkboxes are only sent when ticked; name="x[]" gives an array; redirect after a successful POST.

PHP Forms Examples

Each example shows the code, the output it produces and what each part does.

Example 1

A search form with GET

The visitor typed desk lamp and pressed Search, so the address is search.php?q=desk+lamp.

PHP
<?php
$products = ['Desk lamp', 'Floor lamp', 'Notebook', 'Pen'];
$q = trim($_GET['q'] ?? '');
$results = [];
if ($q !== '') {
    foreach ($products as $p) {
        if (stripos($p, $q) !== false) $results[] = $p;
    }
}
?>
<form method="get">
  <input name="q" value="<?= htmlspecialchars($q) ?>">
  <button>Search</button>
</form>
<p><?= count($results) ?> result(s) for "<?= htmlspecialchars($q) ?>"</p>
<?php foreach ($results as $r): ?>
  <li><?= htmlspecialchars($r) ?></li>
<?php endforeach; ?>
Output
<form method="get">
  <input name="q" value="desk lamp">
  <button>Search</button>
</form>
<p>1 result(s) for "desk lamp"</p>
  <li>Desk lamp</li>
Line-by-line explanation
  1. Line 3Read the search term from the address, or an empty string on first visit.
  2. Line 6stripos searches without caring about capital letters. It returns false when there's no match, so compare with !== false.
  3. Line 12Keeping the term in the box makes the form sticky.
Example 2

A contact form with POST

The visitor filled in Sam and Hello there!, ticked the copy box and pressed Send.

PHP
<?php
$sent = false;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = trim($_POST['name'] ?? '');
    $message = trim($_POST['message'] ?? '');
    $copy = isset($_POST['copy']);
    $sent = $name !== '' && $message !== '';
}
?>
<?php if ($sent): ?>
  <p>Thanks, <?= htmlspecialchars($name) ?>! We got your <?= strlen($message) ?>-character message.</p>
  <p><?= $copy ? 'A copy is on its way to you.' : 'No copy requested.' ?></p>
<?php endif; ?>
Output
  <p>Thanks, Sam! We got your 12-character message.</p>
  <p>A copy is on its way to you.</p>
Line-by-line explanation
  1. Line 3Only process the form when it was submitted with POST.
  2. Line 6A ticked checkbox is present in $_POST; an unticked one is missing, so isset gives true or false.
  3. Line 10Escape the name before printing it.
Example 3

Several checkboxes as an array

The visitor ticked Cheese and Olives.

PHP
<?php
// <input type="checkbox" name="toppings[]" value="cheese">
// <input type="checkbox" name="toppings[]" value="ham">
// <input type="checkbox" name="toppings[]" value="olives">
$toppings = $_POST['toppings'] ?? [];
$allowed = ['cheese', 'ham', 'olives'];
$chosen = array_values(array_intersect($toppings, $allowed));

echo count($chosen) . " toppings: " . implode(', ', $chosen) . "\n";
echo "Price: £" . number_format(8 + count($chosen) * 1.5, 2);
Output
2 toppings: cheese, olives
Price: £11.00
Line-by-line explanation
  1. Lines 2 to 4The [] in the name tells PHP to collect the ticked values into an array.
  2. Line 5If nothing is ticked, the key is missing, so default to an empty array.
  3. Line 7Keep only values from the allowed list, in case someone sends something unexpected.

Common PHP Forms Mistakes

A field without a name

Don't
<input id="email" type="email">
Do
<input id="email" name="email" type="email">

Without name, the field isn't sent, and $_POST['email'] doesn't exist.

Printing input without escaping

Don't
echo "Hello " . $_GET['name'];
Do
echo "Hello " . htmlspecialchars($_GET['name'] ?? '');

A name like <script>...</script> would otherwise run as code in the page.

Using GET for actions that change data

Don't
<a href="delete.php?id=5">Delete</a>
Do
<form method="post" action="delete.php">
  <input type="hidden" name="id" value="5">
  <button>Delete</button>
</form>

Browsers and link previewers may load GET links automatically, deleting things nobody chose to delete.

PHP Forms in Real Projects

Forms on real websites

Every login, registration, checkout and comment box runs through code like this. Frameworks such as Laravel and Symfony add helpers for reading input, but underneath they still read $_GET and $_POST. Searches use GET so results can be shared, and payment and account forms use POST with a redirect so refreshing never charges twice.

PHP Forms FAQ

How do I upload files with a PHP form?

Set method="post" and enctype="multipart/form-data" on the form and add an <input type="file" name="photo">. PHP puts the upload's details in $_FILES['photo'], including a temporary path; move it with move_uploaded_file() after checking its size and real type. The upload security lesson covers the checks.

Why is $_POST empty after submitting a large form?

If a request exceeds post_max_size in php.ini, PHP discards the whole body, so both $_POST and $_FILES arrive empty. Uploads are also limited by upload_max_filesize. Check both settings, and the web server's own request size limit, when large forms fail silently.

Should I use $_REQUEST?

Usually not. $_REQUEST mixes GET, POST and sometimes cookie values, so you can't tell where a value came from, and a value in the URL can override one you expected from the form body. Read from $_GET or $_POST explicitly.

How do I protect a form against CSRF?

Store a random token in the session, add it to the form as a hidden field, and reject the POST request if the submitted token doesn't match. This stops another website from silently submitting the form using a logged-in visitor's browser. Frameworks such as Laravel and Symfony add these tokens automatically.

How do I validate form input?

Check every field on the server, even if the browser already checks it: required values, length, format and allowed options. Collect error messages per field and show the form again with sticky values. The form validation lesson builds a complete example.

PHP Forms Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Fill in the blankseasy

Complete the code that reads the "email" field from a POST form.

$email = $['email']  '';
Multiple choiceeasy

Which method should a search form use?

Multiple choicemedium

How do you check whether an unticked checkbox named "terms" was ticked?

Predict the outputmedium

The address is page.php?colour=red&size=M. What does this output?

echo $_GET['size'] . '-' . ($_GET['qty'] ?? 1);
Multiple choicehard

Why redirect after successfully handling a POST form?

PHP Forms Quiz

5 questions to check what you learned.

  1. Which attribute decides the key a field's value arrives under?

    • id
    • class
    • value
    • name
  2. Where does GET data appear?

    • In the page address after a question mark
    • Only in cookies
    • In the request body
    • In a hidden file
  3. What does htmlspecialchars() protect against?

    • SQL injection
    • Slow pages
    • Cross-site scripting, by turning characters like < into safe codes
    • Missing fields
  4. What does name="colours[]" do for a group of checkboxes?

    • Only the first value is sent
    • PHP collects all ticked values into an array
    • It creates a list of fields
    • It's invalid HTML
  5. How can PHP tell that a form was submitted with POST?

    • Check isset($_GET)
    • Check the page's file name
    • Check $_SERVER['REQUEST_METHOD'] === 'POST'
    • Check count($_POST) > 100