Я пытаюсь использовать 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
и возвращает false. Есть ли способ:
- подавить предупреждение (я планирую выбросить собственное исключение в случае сбоя)
- получить информацию об ошибке (как минимум, код ответа) из потока
'ignore_errors' => TRUE
к$options
.@
в начале строки.Ни один из ответов (включая тот, который был принят OP) фактически не удовлетворяет двум требованиям:
Вот мой вывод:
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; }
Это приведет к отсутствию
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.Скорее всего, это «правильный» уровень подавления ошибок для большинства случаев использования - я не рекомендую использовать
@
оператор подавления ошибок, так как это также подавит такие ошибки, как простая передача неправильных аргументов, которые могут непреднамеренно скрыть ошибку в код вызова.источник
Добавляем еще несколько строк к принятому ответу, чтобы получить 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 Bad request).Я использую такую функцию:
$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.
источник
status
- у него нет связи с кодом состояния HTTP для вызова API$http_response_header[0]
, почему этот ответ, получивший большое количество голосов, не работаетfile_get_contents
?