Baue eine saubere JSON-API, indem du die Header, das Lesen des rohen Bodys und die feine Semantik der Statuscodes beherrschst.
Diese Lektion in Kodokon öffnenEine JSON-API ist ein Vertrag: Jede Antwort kündigt ihren Typ an (Content-Type: application/json), trägt den richtigen Statuscode und eine stabile Struktur. PHP verschickt davon standardmäßig nichts - es deklariert text/html. Erster Baustein: ein einziger Antwort-Helper, typisiert mit never (PHP 8.1+). Dieser Rückgabetyp garantiert der Engine wie auch den Werkzeugen der statischen Analyse, dass die Funktion die Kontrolle niemals zurückgibt: Jeder Code, der nach einem Aufruf steht, ist nachweislich unerreichbar.
<?php
declare(strict_types=1);
function jsonResponse(
mixed $data,
int $status = 200
): never {
http_response_code($status);
header('Content-Type: application/json');
echo json_encode(
$data,
JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE
);
exit;
}
jsonResponse(['status' => 'ok']);Eine zweite Feinheit, die oft zu spät entdeckt wird: $_POST bleibt bei einem JSON-Body leer. PHP füllt es nur für application/x-www-form-urlencoded und multipart/form-data. Der rohe Body wird aus dem Stream php://input gelesen. Dekodiere ihn mit JSON_THROW_ON_ERROR: Ohne dieses Flag gibt json_decode bei einem Fehler stillschweigend null zurück - nicht unterscheidbar von einem Body, der buchstäblich null enthält. Und dank des Typs never braucht das folgende switch überhaupt kein break.
<?php
declare(strict_types=1);
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
jsonResponse(['items' => []]);
case 'POST':
$raw = (string) file_get_contents(
'php://input'
);
try {
$payload = json_decode(
$raw,
true,
512,
JSON_THROW_ON_ERROR
);
} catch (JsonException) {
jsonResponse(
['error' => 'Malformed JSON'],
400
);
}
header('Location: /items/42');
jsonResponse(['created' => $payload], 201);
default:
header('Allow: GET, POST');
jsonResponse(
['error' => 'Method not allowed'],
405
);
}Wähle die Codes genau, denn deine Clients programmieren gegen sie und nicht gegen deine Meldungen: 200 erfolgreiches Lesen, 201 Erstellung (begleitet von einem Location-Header, der auf die Ressource zeigt), 204 Erfolg ohne Body, 400 fehlerhaftes JSON, 404 fehlende Ressource, 405 nicht behandelte Methode (mit einem Allow-Header, der die erlaubten auflistet), und 422 für JSON, das syntaktisch gültig, aber semantisch falsch ist. Prüfe das alles mit curl -i, das die empfangenen Header anzeigt.
curl -i -X POST http://localhost:8000/items \
-H 'Content-Type: application/json' \
-d '{"name":"Widget"}'