導入
PHPで外部Webサイトの情報を取得する際、手軽に使えるのが file_get_contents() 関数です。しかし、標準設定のままでは「404 Not Found」や「500 Internal Server Error」などのエラーが発生した際に、単に false が返るだけで「なぜ失敗したのか」が判別できません。本記事では、stream_context_create() を活用して、エラー時でも詳細なHTTPレスポンスコードを取得し、正確なエラーハンドリングを行うための手法を解説します。
基礎知識
file_get_contents() はデフォルトで、HTTPレスポンスコードが200以外(4xxや5xx系)の場合、データの取得を「失敗」と見なし false を返します。しかし、実際にはサーバーからエラーメッセージやステータスラインが送信されており、これらを受け取るには「エラーを無視(ignore_errors)」する設定が必要です。また、リクエスト実行後にPHPが自動生成する特殊変数 $http_response_header を参照することで、レスポンスヘッダー全体を配列として取得できます。
実装/解決策
解決の鍵は、stream_context_create() を利用してコンテキストオプションをカスタマイズすることです。具体的には、’http’ 配列内の ‘ignore_errors’ を true に設定します。これにより、サーバーがエラーを返してもプロセスが中断されず、PHP内部の $http_response_header にレスポンスの詳細が格納されるようになります。
サンプルプログラム
以下は、指定したURLからHTTPステータスコードを安全に取得する実用的なサンプルコードです。
/
function getHttpStatusCode($url) {
// サーバーがエラーコードを返しても処理を続行する設定
$options = [
‘http’ => [
‘ignore_errors’ => true,
‘method’ => ‘GET’,
‘timeout’ => 5 // タイムアウト設定を追加して冗長な待ち時間を防ぐ
]
];
$context = stream_context_create($options);
// URLが無効な場合に発生するWarningを抑制して実行
$result = @file_get_contents($url, false, $context);
// ヘッダー情報が格納されているか確認
if (isset($http_response_header) && is_array($http_response_header)) {
// $http_response_header[0] には ‘HTTP/1.1 200 OK’ のような文字列が入る
// 正規表現でステータスコード(3桁の数字)を抽出
if (preg_match(‘#HTTP/\d\.\d\s+(\d{3})#’, $http_response_header[0], $matches)) {
return (int)$matches[1];
}
}
// 接続自体に失敗した場合は0または適切なエラー値を返す
return 0;
}
$url = ‘https://example.com’;
$statusCode = getHttpStatusCode($url);
echo “ステータスコード: ” . $statusCode;
?>
応用・注意点
1. タイムアウト設定の重要性: 外部サイトが極端に重い場合、file_get_contents() はデフォルトで処理が止まりません。実務では上記サンプルのように ‘timeout’ オプションを必ず設定してください。
2. 正規表現の運用: $http_response_header[0] に含まれる形式はサーバーによって多少異なる場合があります。より堅牢なシステムを構築する場合は、GuzzleのようなHTTPクライアントライブラリの使用を検討しましょう。
3. エラー抑制演算子「@」の是非: 「@」はWarningを隠すために便利ですが、デバッグを困難にする側面もあります。開発環境では外し、例外処理(try-catch)が可能なライブラリへの移行を検討するのが、モダンなPHP開発におけるベストプラクティスです。