The Other Side of the API
PHP scripts are not only servers — they call APIs too: fetching data, talking to services, integrating third parties. The built-in client is file_get_contents with a stream context: the URL alone makes a plain GET, the context adds methods, headers and a body. Three habits:
1. put ignore_errors in the context, so 4xx and 5xx responses still hand you their body,
2. check the status code — the first line of $http_response_header — before trusting the body,
3. json_decode the body and check for null before using the data.
(PHP also ships the cURL extension for advanced client work; everything here needs only the built-in streams.) The demos below call a local test server, so the outputs are stable — the client code is exactly what you would point at a real URL.
GET and Decode
The everyday task: GET a URL, check the status, decode the JSON body into arrays with json_decode($body, true) — from there it is ordinary PHP data.
Fetch a list into arrays
The response body decodes into a list of users, and from there it is ordinary PHP data — looped and printed field by field.
Output: PHP script
<?php
// A server that answers with a JSON list of users.
$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);
// A free port, then PHP's built-in web server as a child process.
$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 "unexpected status: $status\n";
} elseif (($users = json_decode($body, true)) === null) {
echo "bad JSON: " . json_last_error_msg() . "\n";
} else {
foreach ($users as $user) {
echo "user {$user['id']}: {$user['name']}\n";
}
}
proc_terminate($server);
proc_close($server);
unlink($routerFile);
POST with a JSON Body
Sending data is the mirror image: encode the array, put it in the context as content with the right Content-Type header, POST — then decode the server's answer, which here carries the id the server assigned.
Send an array, read the answer
The array goes out as JSON and the created record comes back with its new id — the complete write-path of an API client in one small program.
Output: PHP script
<?php
// The server assigns the id and answers 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);
// A free port, then PHP's built-in web server as a child process.
$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 "status: $status\n";
echo "created: id {$created['id']}, name {$created['name']}\n";
proc_terminate($server);
proc_close($server);
unlink($routerFile);