Estou tentando usar em file_get_contents
conjunto com stream_context_create
para fazer solicitações POST. Meu código até agora:
$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);
Funciona bem, no entanto, quando ocorre um erro de HTTP, ele exibe um aviso:
file_get_contents(...): failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request
e retorna falso. Existe uma maneira de:
- suprimir um aviso (estou planejando lançar minha própria exceção em caso de falha)
- obter as informações de erro (pelo menos, o código de resposta) do fluxo
'ignore_errors' => TRUE
a$options
.@
no início da linha.Nenhuma das respostas (incluindo a aceita pelo OP) realmente satisfaz os dois requisitos:
Aqui está minha opinião:
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; }
Isso resultará em uma não
200
resposta, mas você pode facilmente trabalhar a partir daí, por exemplo, adicionar umaResponse
classe simples ereturn new Response((int) $status, $response);
se isso se adequar melhor ao seu caso de uso.Por exemplo, para fazer um JSON
POST
para um endpoint de API:$response = fetch( "POST", "http://example.com/", json_encode([ "foo" => "bar", ]), [ "Content-Type: application/json", "X-API-Key: 123456789", ] );
Observe o uso de
"ignore_errors" => true
nohttp
mapa de contexto - isso evitará que a função lance erros para códigos de status não 2xx.Esta é provavelmente a quantidade "certa" de supressão de erros para a maioria dos casos de uso - eu não recomendo usar o
@
operador de supressão de erros, pois isso também suprime erros como simplesmente passar os argumentos errados, que poderiam inadvertidamente ocultar um bug no código de chamada.fonte
Adicionando mais algumas linhas à resposta aceita para obter o código 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);
para ocultar a saída de erro, ambos os comentários estão ok, ignore_errors = true ou @ (eu prefiro @)
fonte
Eu vou para esta página com um problema diferente, então postando minha resposta. Meu problema era que eu estava apenas tentando suprimir a notificação de aviso e exibir uma mensagem de aviso personalizada para o usuário, então essa correção simples e óbvia me ajudou:
// Suppress the warning messages error_reporting(0); $contents = file_get_contents($url); if ($contents === false) { print 'My warning message'; }
E se necessário, retorne o relatório de erros depois disso:
// Enable warning messages again error_reporting(-1);
fonte
@file_get_contents
eignore_errors = true
não são iguais: o primeiro não retorna nada; o segundo suprime as mensagens de erro, mas retorna a resposta do servidor (por exemplo, 400 Bad request).Eu uso uma função como esta:
$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;
Ele retorna 200 (Ok) ou 400 (Solicitação inválida).
Funciona perfeitamente e é mais fácil do que cURL.
fonte
status
- ele não tem conexão com o código de status HTTP para a chamada de API$http_response_header[0]
uma resposta altamente votada não funcionafile_get_contents
?