Ни один из ответов (включая тот, который был принят OP) фактически не удовлетворяет двум требованиям:
- подавить предупреждение (я планирую выбросить собственное исключение в случае сбоя)
- получить информацию об ошибке (как минимум, код ответа) из потока
Вот мой вывод:
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
.