$_POST

Yo Yogesh.M Updated 29 Oct 2026
8 min read

What Is $_POST?

In simple terms: $_POST is an array containing the data a browser sends when a user submits a form with method="post". Each form field's name becomes a key, and what the user entered becomes the value. Technically: $_POST is a superglobal that PHP populates from the body of an HTTP request when the request's Content-Type is application/x-www-form-urlencoded (the default for HTML forms) or multipart/form-data (forms with file uploads). Other body formats, such as JSON, do not populate $_POST.

Why POST Is Used for Forms

GETPOST
Where data travelsIn the URLIn the request body
Visible in address bar, history, server logsYesNo
Can be bookmarked or shared as a linkYesNo
Typical size limitA few kilobytes (URL length)Configurable, megabytes (post_max_size)
Meaning"Fetch something" (safe, repeatable)"Do something" (create, update, delete, log in)

Use POST for anything that changes data or contains sensitive information (passwords, personal details), and for large inputs.


A Basic Form

subscribe.php

<?php
$message = '';
if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
    $email = trim($_POST['email'] ?? '');
    if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
        $message = 'Please enter a valid email address.';
    } else {
        // In a real application: save to the database here
        $message = 'Subscribed: ' . htmlspecialchars($email);
    }
}
?>
<form method="post" action="">
    <label for="email">Email</label>
    <input type="email" id="email" name="email">
    <button type="submit">Subscribe</button>
</form>
<p><?= $message ?></p>

What Happens

  1. First visit (GET): the request method is GET, so the form is shown with an empty message.
  2. Submit: the browser sends a POST request whose body contains email=asha%40example.com.
  3. PHP decodes the body and fills $_POST: ['email' => 'asha@example.com'].
  4. The script validates the email and shows a message. The email is escaped with htmlspecialchars() before being printed.

Output After Submitting asha@example.com

<p>Subscribed: asha@example.com</p>

Key Points

  • The array key comes from the field's name attribute — not from id. A field without name is not sent.
  • action="" submits the form to the current URL.
  • $_SERVER['REQUEST_METHOD'] === 'POST' distinguishes "show the form" from "process the form".
  • ?? '' provides a default, because a manipulated request might not include the field.

Testing POST Requests With curl

You do not need a browser to send POST data. With the built-in server running (php -S localhost:8000):

curl -X POST -d "email=asha@example.com" http://localhost:8000/subscribe.php

-d sends form-encoded data in the body. This is also a reminder that anyone can send any POST data to your script, without using your form.


Form Field Types and $_POST

FieldWhat Is Sent
Text, email, password, textareaThe entered text (possibly an empty string)
SelectThe value of the chosen option
Radio buttons (same name)The value of the selected button; nothing if none selected
CheckboxIts value (default "on") if checked; nothing if unchecked
Disabled fieldsNothing
Submit button with a nameIts value, if that button was clicked

Because unchecked checkboxes and unselected radio buttons are not sent at all, always read them with a default:

$newsletter = isset($_POST['newsletter']);          // checkbox: true if checked
$plan = $_POST['plan'] ?? 'free';                    // radio: default if none chosen

Arrays From Form Fields

Field names with square brackets create arrays in $_POST:

<input type="checkbox" name="skills[]" value="php">
<input type="checkbox" name="skills[]" value="mysql">
<input type="text" name="address[city]">
<input type="text" name="address[pin]">

PHP parses these names exactly like parse_str() parses a query string, which lets you see the result without a browser:

<?php
$body = 'name=Asha&skills%5B%5D=php&skills%5B%5D=mysql&address%5Bcity%5D=Chennai&address%5Bpin%5D=600042';
parse_str($body, $data);
print_r($data);

Output

Array
(
    [name] => Asha
    [skills] => Array
        (
            [0] => php
            [1] => mysql
        )
    [address] => Array
        (
            [city] => Chennai
            [pin] => 600042
        )
)
  • skills[] (empty brackets) collects multiple values into a list — ideal for checkbox groups and multi-selects.
  • address[city] creates a nested associative array, which is useful for grouping related fields.
  • In the body, [ and ] are URL-encoded as %5B and %5D.

Every Field Can Be String or Array

Because the client chooses field names, a field you expect to be a string can arrive as an array (name[]=x), and vice versa. Passing an unexpected array to a string function throws a TypeError. A small helper prevents this:

<?php
function postString(string $key, string $default = ''): string
{
    $value = $_POST[$key] ?? $default;
    return is_string($value) ? trim($value) : $default;
}
function postArray(string $key): array
{
    $value = $_POST[$key] ?? [];
    return is_array($value) ? $value : [];
}

Practical Example: Contact Form With Validation and Redirect

contact.php

<?php
session_start();
function postString(string $key): string
{
    $value = $_POST[$key] ?? '';
    return is_string($value) ? trim($value) : '';
}
$errors = [];
$old = ['name' => '', 'email' => '', 'message' => ''];
if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
    $old = [
        'name' => postString('name'),
        'email' => postString('email'),
        'message' => postString('message'),
    ];
    if ($old['name'] === '') {
        $errors['name'] = 'Please enter your name.';
    }
    if (filter_var($old['email'], FILTER_VALIDATE_EMAIL) === false) {
        $errors['email'] = 'Please enter a valid email address.';
    }
    if (mb_strlen($old['message']) < 10) {
        $errors['message'] = 'Message must be at least 10 characters.';
    }
    if ($errors === []) {
        // Save the message or send an email here.
        $_SESSION['flash'] = 'Thank you, ' . $old['name'] . '! We will reply soon.';
        header('Location: /contact.php', true, 303);
        exit;
    }
}
$flash = $_SESSION['flash'] ?? null;
unset($_SESSION['flash']);
function e(string $value): string
{
    return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
}
?>
<?php if ($flash !== null): ?>
<p class="success"><?= e($flash) ?></p>
<?php endif; ?>
<form method="post" action="/contact.php" novalidate>
    <label>Name <input name="name" value="<?= e($old['name']) ?>"></label>
    <?php if (isset($errors['name'])): ?><span class="error"><?= e($errors['name']) ?></span><?php endif; ?>
    <label>Email <input type="email" name="email" value="<?= e($old['email']) ?>"></label>
    <?php if (isset($errors['email'])): ?><span class="error"><?= e($errors['email']) ?></span><?php endif; ?>
    <label>Message <textarea name="message"><?= e($old['message']) ?></textarea></label>
    <?php if (isset($errors['message'])): ?><span class="error"><?= e($errors['message']) ?></span><?php endif; ?>
    <button type="submit">Send</button>
</form>

How It Behaves

ScenarioResult
First visitEmpty form
Submitted with errors (e.g. invalid email)Form shown again with the user's values filled in and an error next to each invalid field
Submitted successfullyBrowser is redirected to /contact.php, which shows "Thank you, Asha! We will reply soon."
Page refreshed after successThe message disappears; nothing is submitted again

Step-by-Step Explanation

  1. Reading input: postString() trims values and ignores unexpected arrays.
  2. Validation: each rule adds an error keyed by field name, so the template can show it next to the right field.
  3. Keeping user input: $old holds what the user typed, so the form can be refilled after an error — users should not have to retype everything.
  4. Post/Redirect/Get (PRG): after a successful submission, the script redirects with status 303 See Other, which tells the browser to load the page with a GET request. Refreshing the page then repeats the harmless GET, not the POST — preventing duplicate messages or orders.
  5. Flash message: the success message is stored in the session before the redirect and removed after it is displayed once (see PHP Sessions).
  6. Escaping: every value printed into HTML goes through e(), including the user's own input.
  7. novalidate turns off the browser's built-in validation so you can see the server-side checks working. Browser validation improves user experience, but server-side validation is always required, because requests can bypass the browser. A production form would also include a CSRF token (see CSRF Protection).

JSON Request Bodies

JavaScript applications and APIs often send JSON instead of form data:

curl -X POST -H "Content-Type: application/json" \
     -d '{"name": "Asha", "plan": "pro"}' \
     http://localhost:8000/api/subscribe.php

For such requests, $_POST is empty. Read the raw body instead:

<?php
// api/subscribe.php
header('Content-Type: application/json');
try {
    $data = json_decode(file_get_contents('php://input'), true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
    http_response_code(400);
    echo json_encode(['error' => 'Invalid JSON']);
    exit;
}
$name = is_array($data) && is_string($data['name'] ?? null) ? trim($data['name']) : '';
if ($name === '') {
    http_response_code(422);
    echo json_encode(['error' => 'Name is required']);
    exit;
}
echo json_encode(['message' => "Welcome, $name"]);

Response for the curl Request Above

{"message":"Welcome, Asha"}
  • php://input is a read-only stream containing the raw request body.
  • JSON_THROW_ON_ERROR makes invalid JSON throw a JsonException, which is answered with 400 Bad Request.
  • Missing or invalid fields are answered with 422 Unprocessable Content, a common status for validation errors in APIs.

Size Limits

php.ini SettingDefaultEffect
post_max_size8MMaximum size of the entire POST body
max_input_vars1000Maximum number of input fields; extra fields are dropped with a warning
upload_max_filesize2MMaximum size per uploaded file (see PHP File Upload)

Important: When a request body exceeds post_max_size, PHP discards it: $_POST and $_FILES are empty, and a warning is logged. A form that "submits but loses all data" is often caused by this. Check $_SERVER['CONTENT_LENGTH'] against the limit to show a helpful error.


Common Mistakes

Missing name Attributes

Effect: Fields are not sent; $_POST lacks the expected keys. Fix: Give every input a name.

Reading Fields Without Defaults

Effect: Warnings for unchecked checkboxes and manipulated requests. Fix: Use ?? '', isset(), or helper functions.

Trusting Hidden Fields and Select Values

Effect: Users change prices, IDs, or roles in the browser's developer tools. Fix: Validate against allowed values and look up important data (prices, permissions) on the server.

Printing Input Unescaped

Effect: Cross-site scripting — even when refilling the user's own form. Fix: Escape with htmlspecialchars().

Processing the Form and Showing a Page in the Same Response

Effect: Refreshing the page submits the form again. Fix: Redirect after a successful POST (Post/Redirect/Get).

Expecting JSON in $_POST

Effect: $_POST is empty for JSON requests. Fix: Read php://input and json_decode() it.


Best Practices

  • Use POST for actions that change data and for sensitive or large inputs.
  • Check the request method explicitly, then validate every field on the server.
  • Read fields with defaults and type checks; never assume a field is a string.
  • Refill forms with escaped user input after validation errors.
  • Redirect after successful submissions (PRG), and protect forms with CSRF tokens. Official reference: https://www.php.net/manual/en/reserved.variables.post.php

0 Comments

Reviewed before they appear

No comments yet.

Data Mining
Introduction to Data Mining Data Mining Implementation Process Data Mining Architecture Data Mining Techniques KDD: Knowledge Discovery in Databases History of Data Mining Data Mining Tools Data Mining vs Machine Learning Facebook Data Mining Social Media Data Mining Methods Clustering in Data Mining Text Data Mining Bagging vs Boosting Data Mining vs Data Warehousing Social Media Data Mining Data Mining: Bayesian Classifiers Data Mining: World Wide Web Different Types of Clustering Bitcoin Mining and Blockchain Data Mining Orange Data Mining Data Mining vs Big Data Decision Tree Induction Educational Data Mining Data Mining in Healthcare Apriori Algorithm Data Integration in Data Mining Difference Between Data Mining and Text Mining Discretization in Data Mining Redundancy and Correlation in Data Mining Classification of Data Mining Systems Classification Algorithms in Data Mining Data Generalization in Data Mining Classification and Prediction in Data Mining Regression in Data Mining What Is an Outlier in Data Mining Data Cleaning in Data Mining Data Processing in Data Mining Data Mining Task Primitives Web Content Mining, Web Structure Mining, and Web Usage Mini Binning in Data Mining KDD vs. Data Mining Noise in Data Mining BIRCH in Data Mining Stemming in Data Mining Feature Transformation in Data Mining Visual and Audio Data Mining Class Comparison Methods in Data Mining Data Selection in Data Mining Tasks and Functionalities of Data Mining Ubiquitous and Invisible Data Mining Importance of Data Mining Data Quality in Data Mining Mining Frequent Patterns in Data Mining Data Warehouse and OLAP Technology for Data Mining Need for Data Mining Pattern Evaluation Methods in Data Mining Logarithms and Exponents in Complexity Analysis Time Series Clustering What is the C4.5 Algorithm and How Does It Work? Expanding Contractions in Text Mining Cosine Similarity in Data Mining Lazy Learning in Data Mining Neural Networks in Data Mining Building a Text Normalizer Shallow Parsing Data Pipeline Orchestration Big Data vs Small Data Myths of Data Mining Data Reduction in Data Mining Data Mining Models Difference Between Data Mining and Data Science Difference Between Data Mining and Statistics Difference Between Data Mining and Web Mining Difference Between Data Mining and Data Analysis Difference Between Business Intelligence and Data Mining Difference Between Data Mining and Data Visualization Data Mining vs Data Analytics Types of Data Mining Difference Between Data Profiling and Data Mining Predictive Analytics vs Data Mining Difference Between Data Mining and OLAP Descriptive and Predictive Data Mining Difference Between Spatial and Temporal Data Mining Difference Between Classification and Clustering in Data Min Hierarchical Clustering in Data Mining Density-Based Clustering in Data Mining What Is Aggregation in Data Mining?
Ask about this post
AI Ask about this post

Ask questions about $_POST and get answers drawn from it.

Signed-in readers only.