Жодна з відповідей (включаючи прийняту ОП) насправді не відповідає двом вимогам:
- придушити попередження (я планую видати власний виняток у разі невдачі)
- отримати інформацію про помилку (принаймні, код відповіді) з потоку
Ось моя думка:
function fetch(string $method, string $url, string $body, array $headers = []) {
$context = stream_context_create([
"http" => [
"method" => $method,
"header" => implode("\r\n", $headers),
"content" => $body,
"ignore_errors" => true,
],
]);
$response = file_get_contents($url, false, $context);
$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;
}
Це призведе до 200
відсутності відповіді, але ви можете легко працювати звідти, наприклад, додати простий Response
клас, і return new Response((int) $status, $response);
якщо це більше відповідає вашому випадку використання.
Наприклад, щоб зробити JSON POST
для кінцевої точки API:
$response = fetch(
"POST",
"http://example.com/",
json_encode([
"foo" => "bar",
]),
[
"Content-Type: application/json",
"X-API-Key: 123456789",
]
);
Зверніть увагу на використання "ignore_errors" => true
в http
контекстній карті - це запобіжить появі помилок функції для кодів стану, що не мають значення 2xx.
Це, швидше за все, "правильна" кількість придушення помилок для більшості випадків використання - я не рекомендую використовувати @
оператор придушення помилок, оскільки це також придушить помилки, як просто передача помилкових аргументів, які можуть ненавмисно приховати помилку в телефонний код.
'ignore_errors' => TRUE
до$options
.