Cealaltă parte a API-ului
Scripturile PHP nu sunt doar servere — ele apelează și API-uri: aduc date, vorbesc cu servicii, integrează terți. Clientul încorporat este file_get_contents cu un context de flux: singur, URL-ul face un GET simplu, iar contextul adaugă metode, anteturi și un corp. Trei obiceiuri:
1. pune ignore_errors în context, ca răspunsurile 4xx și 5xx să îți dea totuși corpul lor,
2. verifică codul de stare — prima linie din $http_response_header — înainte să te încrezi în corp,
3. decodifică corpul cu json_decode și verifică dacă e null înainte de a folosi datele.
(PHP vine și cu extensia cURL pentru lucru avansat de client; tot ce e aici are nevoie doar de fluxurile încorporate.) Demonstrațiile de mai jos apelează un server de test local, așa că ieșirile sunt stabile — codul clientului este exact cel pe care l-ai îndrepta către un URL real.
GET și decodificare
Sarcina de zi cu zi: faci GET pe un URL, verifici starea, decodifici corpul JSON în tablouri cu json_decode($body, true) — de acolo încolo sunt date PHP obișnuite.
Aducerea unei liste în tablouri
Corpul răspunsului se decodifică într-o listă de utilizatori, iar de acolo încolo sunt date PHP obișnuite — parcurse în buclă și afișate câmp cu câmp.
Ieșire: script PHP
<?php
// Un server care răspunde cu o listă JSON de utilizatori.
$router = <<<'PHP'
<?php
header("Content-Type: application/json");
echo '[{"id": 1, "name": "Ana"}, {"id": 2, "name": "Ben"}]';
PHP;
$routerFile = sys_get_temp_dir() . "/pc-get-decode.php";
file_put_contents($routerFile, $router);
// Un port liber, apoi serverul web încorporat al 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);
$base = "http://127.0.0.1:$port";
$context = stream_context_create(["http" => ["ignore_errors" => true]]);
$body = file_get_contents("$base/users", false, $context);
$status = (int) explode(" ", $http_response_header[0])[1];
if ($status !== 200) {
echo "stare neașteptată: $status\n";
} elseif (($users = json_decode($body, true)) === null) {
echo "JSON invalid: " . json_last_error_msg() . "\n";
} else {
foreach ($users as $user) {
echo "utilizator {$user['id']}: {$user['name']}\n";
}
}
proc_terminate($server);
proc_close($server);
unlink($routerFile);
POST cu un corp JSON
Trimiterea datelor este imaginea în oglindă: codifici tabloul, îl pui în context ca content împreună cu antetul Content-Type potrivit, faci POST — apoi decodifici răspunsul serverului, care aici aduce id-ul atribuit de server.
Trimite un tablou, citește răspunsul
Tabloul pleacă sub formă de JSON și înregistrarea creată se întoarce cu noul său id — întreaga cale de scriere a unui client de API într-un singur program mic.
Ieșire: script PHP
<?php
// Serverul atribuie id-ul și răspunde cu 201.
$router = <<<'PHP'
<?php
$input = json_decode(file_get_contents("php://input"), true);
header("Content-Type: application/json");
http_response_code(201);
echo json_encode(["id" => 7, "name" => $input["name"]]);
PHP;
$routerFile = sys_get_temp_dir() . "/pc-post-json.php";
file_put_contents($routerFile, $router);
// Un port liber, apoi serverul web încorporat al 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);
$base = "http://127.0.0.1:$port";
$payload = json_encode(["name" => "Cleo"]);
$context = stream_context_create(["http" => [
"method" => "POST",
"header" => "Content-Type: application/json",
"content" => $payload,
"ignore_errors" => true,
]]);
$body = file_get_contents("$base/users", false, $context);
[, $status] = explode(" ", $http_response_header[0], 2);
$created = json_decode($body, true);
echo "stare: $status\n";
echo "creat: id {$created['id']}, nume {$created['name']}\n";
proc_terminate($server);
proc_close($server);
unlink($routerFile);