web php
POST Data
POST requests are used when a browser or client sends data in the request body. In PHP web applications, POST data usually comes from forms that create, update, delete, log in, register, check out, or send messages.
POST does not make data private or trustworthy. It only changes where the data is sent. PHP still needs to check the request method, read the expected source, validate the values, protect state-changing forms with CSRF tokens, and return a clear response.
Form POST data
For normal HTML forms, PHP puts submitted fields in $_POST.
<?php
declare(strict_types=1);
$server = ['REQUEST_METHOD' => 'POST'];
$post = ['title' => ' New post ', 'published' => '1'];
if (($server['REQUEST_METHOD'] ?? 'GET') === 'POST') {
$title = trim((string) ($post['title'] ?? ''));
$published = ($post['published'] ?? '') === '1';
echo $title . ' published=' . ($published ? 'yes' : 'no') . PHP_EOL;
}
// Prints:
// New post published=yes
This example uses arrays so it can run from the command line. In a real request, those values would usually be $_SERVER and $_POST.
POST is not always form data
JSON API requests also use POST, but JSON request bodies are not automatically placed in $_POST. For JSON, read the raw body from php://input and decode it.
<?php
declare(strict_types=1);
$rawBody = '{"email":"ada@example.com"}';
$data = json_decode($rawBody, true, flags: JSON_THROW_ON_ERROR);
echo $data['email'] . PHP_EOL;
// Prints:
// ada@example.com
In a live request, $rawBody would come from file_get_contents('php://input').
Know The Form Encodings
Browsers commonly submit forms as application/x-www-form-urlencoded. Upload forms use multipart/form-data. PHP parses both into familiar superglobals:
application/x-www-form-urlencoded -> $_POST
multipart/form-data -> $_POST and $_FILES
application/json -> read php://input yourself
The body format is part of the request contract. Check the Content-Type header when an API endpoint accepts JSON, and return a clear client error when the format is unsupported.
Checkbox And Missing-Field Behaviour
Unchecked HTML checkboxes are normally absent from the submitted data. Treat absence deliberately:
<?php
declare(strict_types=1);
$post = ['title' => 'Release notes'];
$published = ($post['published'] ?? '') === '1';
echo $published ? 'published' : 'draft';
echo PHP_EOL;
// Prints:
// draft
Do not confuse a missing optional field with a missing required field. Required fields need validation errors. Optional fields need a documented default.
Method Overrides And Framework Requests
Plain HTML forms directly support GET and POST. Frameworks often simulate PUT, PATCH, or DELETE with a hidden form field while the browser still sends POST. Learn the convention used by the project before debugging route mismatches.
Empty POST data
If a submitted form unexpectedly gives an empty $_POST, check:
- the form uses
method="post" - inputs have
nameattributes - the request body did not exceed
post_max_size - the content type matches the kind of body being sent
- file upload forms use
enctype="multipart/form-data"
Do not assume an empty $_POST means the user submitted empty values. It can also mean PHP did not parse the body.
State-changing requests need protection
A POST request can still be forged by another website through a user's browser. State-changing browser forms need CSRF protection, even if they use POST.
Use POST for actions that change state, but also check authentication, authorization, validation, and CSRF tokens. Method choice is only one layer.
What you should be able to do
After this lesson, you should be able to read POST form values, distinguish body encodings, handle absent checkboxes, distinguish form POST data from JSON request bodies, debug empty $_POST, and explain why POST data is still untrusted input.
Practice
Task: Read A POST Submission
Create a PHP function that reads submitted form data for a simple article form.
Requirements
- Accept a request method and submitted values as arguments.
- Only process the values when the method is
POST. - Read and trim a
titlefield. - Read a
publishedcheckbox value. - Return cleaned values and errors.
- Show one valid POST case and one non-POST case.
- Add a short note explaining why JSON POST bodies are handled differently from normal form POST bodies.
Check your work
The example should make it clear that POST is a request method, not automatic proof that the data is valid.
Show solution
<?php
declare(strict_types=1);
/**
* @return array{values: array{title: string, published: bool}, errors: array<string, string>}
*/
function readArticlePost(string $method, array $post): array
{
$values = ['title' => '', 'published' => false];
$errors = [];
if ($method !== 'POST') {
$errors['method'] = 'The form has not been submitted.';
return ['values' => $values, 'errors' => $errors];
}
$values['title'] = trim((string) ($post['title'] ?? ''));
$values['published'] = ($post['published'] ?? '') === '1';
if ($values['title'] === '') {
$errors['title'] = 'Title is required.';
}
return ['values' => $values, 'errors' => $errors];
}
$valid = readArticlePost('POST', ['title' => ' First article ', 'published' => '1']);
$notSubmitted = readArticlePost('GET', []);
echo $valid['values']['title'] . ' published=' . ($valid['values']['published'] ? 'yes' : 'no') . PHP_EOL;
echo implode(', ', $notSubmitted['errors']) . PHP_EOL;
// Prints:
// First article published=yes
// The form has not been submitted.
Normal form POST data is parsed into $_POST when the content type is a standard form type. JSON POST bodies are raw request bodies, so PHP code normally reads php://input and decodes JSON before validating it.