None of the answers (including the one accepted by OP) actually satisfy the two requirements:
- suppress a warning (I'm planning to throw my own exception in case of failure)
- obtain the error information (at least, the response code) from the stream
Here's my take:
function fetch(string $method, string $url, string $body, array $headers = []) {
$context = stream_context_create([
"http" => [
// http://docs.php.net/manual/en/context.http.php
"method" => $method,
"header" => implode("\r\n", $headers),
"content" => $body,
"ignore_errors" => true,
],
]);
$response = file_get_contents($url, false, $context);
/**
* @var array $http_response_header materializes out of thin air
*/
$status_line = $http_response_header[0];
preg_match('{HTTP\/\S*\s(\d{3})}', $status_line, $match);
$status = $match[1];
if ($status !== "200") {
throw new RuntimeException("unexpected response status: {$status_line}\n" . $response);
}
return $response;
}
This will throw for a non-200
response, but you can easily work from there, e.g. add a simple Response
class and return new Response((int) $status, $response);
if that fits your use-case better.
For example, to do a JSON POST
to an API endpoint:
$response = fetch(
"POST",
"http://example.com/",
json_encode([
"foo" => "bar",
]),
[
"Content-Type: application/json",
"X-API-Key: 123456789",
]
);
Note the use of "ignore_errors" => true
in the http
context map - this will prevent the function from throwing errors for non-2xx status codes.
This is most likely the "right" amount of error-suppression for most use-cases - I do not recommend using the @
error-suppression operator, as this will also suppress errors like simply passing the wrong arguments, which could inadvertently hide a bug in calling code.
'ignore_errors' => TRUE
to$options
. – Extemporize