Skip to content

PHP Tutorial Working with JSON and APIs

HTTP Request Methods

Lesson 310 of 369 2 min read By Deepak Paswan Updated Oct 5, 2026

Every request has a method that tells the server what the client wants to do.

MethodMeaningChanges data?Has a body?
GETRead a resourceNoNo
POSTCreate a resource (or submit data)YesYes
PUTReplace a resource completelyYesYes
PATCHChange part of a resourceYesYes
DELETERemove a resourceYesUsually no
HEADLike GET, headers onlyNoNo
OPTIONSAsk what is allowed (used by CORS)NoNo

A REST-style API

A common way to organise an API around a “products” resource:

RequestMeaning
GET /productsList products
GET /products/42Show product 42
POST /productsCreate a product
PUT /products/42Replace product 42
PATCH /products/42Change some fields of product 42
DELETE /products/42Delete product 42

Read the method in PHP

index.php
PHP
<?php
$method = $_SERVER["REQUEST_METHOD"];   // "GET", "POST", ...

Read the data for each method

  • GET: $_GET.
  • POST with a normal HTML form: $_POST.
  • JSON in any method (POST, PUT, PATCH): the raw body.
  • PUT and PATCH: PHP does not fill $_POST. Read the body yourself.
index.php
PHP
<?php
function readBody(string $contentType, string $rawBody): array
{
    if (str_starts_with($contentType, "application/json")) {
        $data = json_decode($rawBody, true, 512, JSON_THROW_ON_ERROR);

        return is_array($data) ? $data : [];
    }

    parse_str($rawBody, $data);   // application/x-www-form-urlencoded

    return $data;
}

print_r(readBody("application/json", '{"name":"Pen","price":12}'));
print_r(readBody("application/x-www-form-urlencoded", "name=Pen&price=12"));
Output
OUTPUT
Array
(
    [name] => Pen
    [price] => 12
)
Array
(
    [name] => Pen
    [price] => 12
)

In a real request: $raw = file_get_contents("php://input"); and $_SERVER["CONTENT_TYPE"] ?? "". (PHP 8.4 also adds request_parse_body() for PUT and PATCH forms.)

Route by method

index.php
PHP
<?php
function handle(string $method, string $path): array
{
    $routes = [
        "GET /products" => [200, "list products"],
        "POST /products" => [201, "create a product"],
        "GET /products/1" => [200, "show product 1"],
        "DELETE /products/1" => [204, "delete product 1"],
    ];

    $key = "$method $path";

    if (isset($routes[$key])) {
        return $routes[$key];
    }

    // Is the path known, but with another method?
    foreach (array_keys($routes) as $known) {
        if (str_ends_with($known, " $path")) {
            return [405, "method not allowed"];
        }
    }

    return [404, "not found"];
}

foreach ([["GET", "/products"], ["POST", "/products"], ["PUT", "/products"], ["GET", "/nothing"]] as [$m, $p]) {
    [$status, $message] = handle($m, $p);
    echo "$m $p -> $status $message\n";
}
Output
OUTPUT
GET /products -> 200 list products
POST /products -> 201 create a product
PUT /products -> 405 method not allowed
GET /nothing -> 404 not found

A 405 response should also include an Allow header that lists the allowed methods.

Safe and idempotent

  • Safe methods (GET, HEAD, OPTIONS) never change data. A crawler can call them freely.
  • Idempotent methods (GET, PUT, DELETE) give the same result if you repeat them. Deleting product 42 twice leaves the same state. POST is not idempotent: sending it twice creates two records.

Browsers only send GET and POST from forms

HTML forms support only GET and POST. For PUT and DELETE from a form, many frameworks use a hidden _method field and treat a POST as the other method. APIs called with JavaScript fetch() can use all methods.

Never change data with GET

A GET request can be triggered by a link, an image tag or a crawler. Using it to delete or buy things is a security and reliability bug (see CSRF).

lightbulb
Use the method as the verb
The URL names the thing (/products/42), and the method gives the action. That is much cleaner than /deleteProduct.php?id=42.