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 example
<?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 example
<?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 example
<?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 name attributes
  • 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 title field.
  • Read a published checkbox 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 example
<?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.