Ответ 1
http://php.net/manual/en/reserved.variables.httpresponseheader.php
file_get_contents("http://example.com", false, ['ignore_errors' => true]);
var_dump($http_response_header);
Я пытаюсь использовать file_get_contents
вместе с stream_context_create
для выполнения запросов POST. Пока мой код:
$options = array('http' => array(
'method' => 'POST',
'content' => $data,
'header' =>
"Content-Type: text/plain\r\n" .
"Content-Length: " . strlen($data) . "\r\n"
));
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
Работает нормально, однако при возникновении ошибки HTTP выдает предупреждение:
file_get_contents(...): failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request
и возвращает ложь. Есть ли способ:
http://php.net/manual/en/reserved.variables.httpresponseheader.php
file_get_contents("http://example.com", false, ['ignore_errors' => true]);
var_dump($http_response_header);
Ни один из ответов (в том числе принятый ОП) не удовлетворяет двум требованиям:
- подавить предупреждение (я планирую выдать собственное исключение в случае сбоя)
- получить информацию об ошибке (по крайней мере, код ответа) из потока
Вот мой дубль:
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;
}
Это приведет к ответу non- 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
- это предотвратит выдачу ошибок функцией для кодов состояния non- 2xx.
Скорее всего, это "правильное" количество подавления ошибок для большинства случаев использования - я не рекомендую использовать оператор подавления ошибок @
, так как это также подавляет ошибки, такие как простая передача неправильных аргументов, которые могут случайно скрыться ошибка в коде вызова.
Добавьте еще несколько строк к принятому ответу, чтобы получить http-код
function getHttpCode($http_response_header)
{
if(is_array($http_response_header))
{
$parts=explode(' ',$http_response_header[0]);
if(count($parts)>1) //HTTP/1.0 <code> <text>
return intval($parts[1]); //Get code
}
return 0;
}
@file_get_contents("http://example.com");
$code=getHttpCode($http_response_header);
чтобы скрыть вывод ошибок, оба комментария в порядке, ignore_errors = true или @(я предпочитаю @)
Я захожу на эту страницу с другой проблемой, поэтому публикую свой ответ. Моя проблема заключалась в том, что я просто пытался подавить предупреждающее уведомление и отобразить настраиваемое предупреждающее сообщение для пользователя, поэтому мне помогло это простое и очевидное исправление:
// Suppress the warning messages
error_reporting(0);
$contents = file_get_contents($url);
if ($contents === false) {
print 'My warning message';
}
А при необходимости верните отчет об ошибках после этого:
// Enable warning messages again
error_reporting(-1);
@file_get_contents
и ignore_errors = true
не совпадают:
первое ничего не возвращает;
вторая подавляет сообщения об ошибках, но возвращает ответ сервера (например, 400 неверных запросов).
Я использую такую функцию:
$result = file_get_contents(
$url_of_API,
false,
stream_context_create([
'http' => [
'content' => json_encode(['value1' => $value1, 'value2' => $value2]),
'header' => 'Authorization: Basic XXXXXXXXXXXXXXX',
'ignore_errors' => 1,
'method' => 'POST',
'timeout' => 10
]
])
);
return json_decode($result)->status;
Возвращает 200 (ОК) или 400 (Неверный запрос).
Это работает отлично, и это проще, чем cURL.