Serverul rulează scriptul tău
PHP întoarce pe dos servirea paginilor web față de majoritatea limbajelor: nu scrii un server care rulează la nesfârșit — serverul web rulează scriptul tău, o dată pentru fiecare cerere. Scriptul este handlerul: superglobale precum $_SERVER și $_GET conțin cererea, iar header() plus echo construiesc răspunsul.
PHP vine cu propriul server web pentru dezvoltare: php -S host:port router.php răspunde la fiecare cerere rulând acel unic script. Exemplele de aici îl rulează cu adevărat: fiecare își scrie scriptul de handler într-un fișier temporar, pornește php -S pe un port liber ca proces copil, îi trimite cereri HTTP reale, afișează răspunsurile și oprește serverul — așa că fiecare exemplu rulează și se încheie de la sine.
Un prim handler
Cel mai mic script de handler posibil scrie o linie de text. Tot ce face un API — JSON, coduri de status, rutare — se întâmplă în interiorul aceleiași forme: cererea intră, ieșirea se afișează cu echo.
Salut de la un handler
Scriptul de handler afișează o singură linie; clientul citește exact acea linie ca corp al răspunsului, cu statusul 200 OK completat automat.
Ieșire: script PHP
<?php
// Scriptul de handler: serverul web rulează acest fișier o dată pentru fiecare cerere.
$router = <<<'PHP'
<?php
header("Content-Type: text/plain");
echo "salut de la server\n";
PHP;
$routerFile = sys_get_temp_dir() . "/pc-first-handler.php";
file_put_contents($routerFile, $router);
// Un port liber, apoi serverul web încorporat în PHP ca proces copil.
$probe = stream_socket_server("tcp://127.0.0.1:0");
$port = (int) explode(":", stream_socket_get_name($probe, false))[1];
fclose($probe);
$server = proc_open(["php", "-S", "127.0.0.1:$port", $routerFile],
[1 => ["file", "/dev/null", "w"], 2 => ["file", "/dev/null", "w"]], $pipes);
do {
usleep(20000);
$up = @fsockopen("127.0.0.1", $port);
} while ($up === false);
fclose($up);
$context = stream_context_create(["http" => ["ignore_errors" => true]]);
$body = file_get_contents("http://127.0.0.1:$port/", false, $context);
[, $status] = explode(" ", $http_response_header[0], 2);
echo "stare: $status\n";
echo "corp: $body";
proc_terminate($server);
proc_close($server);
unlink($routerFile);
Răspunsul în JSON
Un handler de API face trei lucruri: setează antetul Content-Type, alege un cod de status și codifică datele — mai întâi header(), apoi echo json_encode($value).
Ordinea contează: antetele trebuie trimise înainte de primul octet al corpului.
Un endpoint JSON
Handlerul codifică un tablou direct în răspuns. Clientul primește JSON valid și tipul de conținut corect — acesta este scheletul fiecărui endpoint din restul acestui grup.
Ieșire: script PHP
<?php
// Un handler de API: mai întâi antetul, apoi corpul codificat.
$router = <<<'PHP'
<?php
header("Content-Type: application/json");
echo json_encode(["id" => 1, "name" => "Ana"]) . "\n";
PHP;
$routerFile = sys_get_temp_dir() . "/pc-json-handler.php";
file_put_contents($routerFile, $router);
// Un port liber, apoi serverul web încorporat în PHP ca proces copil.
$probe = stream_socket_server("tcp://127.0.0.1:0");
$port = (int) explode(":", stream_socket_get_name($probe, false))[1];
fclose($probe);
$server = proc_open(["php", "-S", "127.0.0.1:$port", $routerFile],
[1 => ["file", "/dev/null", "w"], 2 => ["file", "/dev/null", "w"]], $pipes);
do {
usleep(20000);
$up = @fsockopen("127.0.0.1", $port);
} while ($up === false);
fclose($up);
$context = stream_context_create(["http" => ["ignore_errors" => true]]);
$body = file_get_contents("http://127.0.0.1:$port/user", false, $context);
[, $status] = explode(" ", $http_response_header[0], 2);
$type = "";
foreach ($http_response_header as $headerLine) {
if (stripos($headerLine, "Content-Type:") === 0) {
$type = trim(substr($headerLine, 13));
}
}
echo "stare: $status\n";
echo "tip: $type\n";
echo "corp: $body";
proc_terminate($server);
proc_close($server);
unlink($routerFile);