Próbuję używać file_get_contents
razem z stream_context_create
do wykonywania żądań POST. Mój kod do tej pory:
$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);
Działa dobrze, jednak gdy wystąpi błąd HTTP, wypluwa ostrzeżenie:
file_get_contents(...): failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request
i zwraca fałsz. Czy jest sposób, aby:
- pominąć ostrzeżenie (planuję zgłosić własny wyjątek w przypadku niepowodzenia)
- uzyskać informacje o błędzie (przynajmniej kod odpowiedzi) ze strumienia
'ignore_errors' => TRUE
do$options
.@
na początku wiersza.Żadna z odpowiedzi (w tym ta zaakceptowana przez OP) nie spełnia w rzeczywistości dwóch wymagań:
Oto moja opinia:
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; }
Spowoduje to brak
200
odpowiedzi, ale możesz łatwo z tego miejsca pracować, np. Dodać prostąResponse
klasę ireturn new Response((int) $status, $response);
jeśli to lepiej pasuje do twojego przypadku użycia.Na przykład, aby wykonać JSON
POST
do punktu końcowego API:$response = fetch( "POST", "http://example.com/", json_encode([ "foo" => "bar", ]), [ "Content-Type: application/json", "X-API-Key: 123456789", ] );
Zwróć uwagę na użycie
"ignore_errors" => true
whttp
mapie kontekstu - zapobiegnie to generowaniu przez funkcję błędów dla kodów stanu innych niż 2xx.Jest to najprawdopodobniej „właściwa” wielkość pomijania błędów dla większości przypadków użycia - nie polecam używania
@
operatora eliminacji błędów, ponieważ spowoduje to również wyeliminowanie błędów, takich jak zwykłe przekazanie niewłaściwych argumentów, które mogą przypadkowo ukryć błąd w kod wywołujący.źródło
Dodanie kilku kolejnych wierszy do zaakceptowanej odpowiedzi w celu uzyskania kodu 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);
aby ukryć wyjście błędu, oba komentarze są w porządku, ignore_errors = true lub @ (wolę @)
źródło
Wchodzę na tę stronę z innym problemem, więc zamieszczam swoją odpowiedź. Mój problem polegał na tym, że próbowałem po prostu wyłączyć ostrzeżenie i wyświetlić dostosowany komunikat ostrzegawczy dla użytkownika, więc ta prosta i oczywista poprawka pomogła mi:
// Suppress the warning messages error_reporting(0); $contents = file_get_contents($url); if ($contents === false) { print 'My warning message'; }
W razie potrzeby cofnij raportowanie błędów po tym:
// Enable warning messages again error_reporting(-1);
źródło
@file_get_contents
iignore_errors = true
nie są takie same: pierwsze nic nie zwraca; druga blokuje komunikaty o błędach, ale zwraca odpowiedź serwera (np. 400 Bad request).Używam takiej funkcji:
$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;
Zwraca 200 (Ok) lub 400 (Złe żądanie).
Działa doskonale i jest łatwiejszy niż cURL.
źródło
status
- nie ma połączenia z kodem statusu HTTP dla wywołania API$http_response_header[0]
, bardzo pozytywna odpowiedź, nie działafile_get_contents
?