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を返します。次の方法があります:
http://php.net/manual/en/reserved.variables.httpresponseheader.php
file_get_contents("http://example.com");
var_dump($http_response_header);
回答のいずれも(OPによって受け入れられたものを含む)実際に2つの要件を満たしていません。
- 警告を抑制する(失敗した場合に独自の例外をスローする予定です)
- ストリームからエラー情報(少なくとも応答コード)を取得します
私の見解は次のとおりです。
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);
を追加します。それがユースケースにより適している場合。
たとえば、APIエンドポイントに対してJSON POST
を実行するには:
$response = fetch(
"POST",
"http://example.com/",
json_encode([
"foo" => "bar",
]),
[
"Content-Type: application/json",
"X-API-Key: 123456789",
]
);
http
コンテキストマップでの"ignore_errors" => true
の使用に注意してください-これにより、関数が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);