[メモ] PHPのfile_get_contentsを、HTTPリクエストに使うときのTIPS
Posted: Updated:
file_get_contentsにまつわるTIPS
$res = file_get_contents('http://example.com');
file_get_contentsはローカルのファイルパスだけでなく、URLを入れることでHTTPリクエストを送信することもできます。しかし、その仕様は奥深く難解であり、TIPSが数多く存在する関数でもあります。今回はそんなfile_get_contentsにまつわるTIPSをまとめてみます。
PHP5.3.3で確認していますが、大まかな挙動は他の5.x系でもそんなに変わらないはず。
仕様的なこと
2xx, 3xx以外のレスポンスボディを取得しない
HTTPステータスコードが204または304でなければレスポンスボディを含んでいる可能性があります。しかし、file_get_contentsは、2xx, 3xxのみ( それが204や304であっても! )ボディを返し、4xxや5xxではボディを返しません。
4xx, 5xxのステータスコードだとWarnningを発生させる
必要に応じて、file_get_contentsを使う場所の前後でエラーレベルを変更するか、@マークでエラーを抑制し、後述の方法でレスポンスヘッダーからステータスコードを読み込み分岐させるほうが良いでしょう。エラーを抑制した場合でも、レスポンスボディは取得できません。
レスポンスの取り扱い
レスポンスヘッダーは $http_response_header で取得できる
file_get_contentsを使用すると、$http_response_header という変数にレスポンスヘッダーが自動で格納されます。リクエスト直後にこの変数を参照すれば、ヘッダーを確認できます。この変数は、ローカルスコープに作成されます。
5.3.x以降であれば ignore_errorsでエラーを抑制しながら、レスポンスボディを取得できる
過剰なエラー反応や、2xx&3xx以外のレスポンスボディを取得しない問題は、PHP5.3系であればコンテキストにignore_errorsを与えることで解決します。
$context = stream_context_create(array(
'http' => array('ignore_errors' => true)
));
$body = file_get_contents('http://example.com/', false, $context);
こうなっていると、4xxや5xxのステータスコードであってもWarnningを発生させず、本来のレスポンスボディが返ってくるようになります。
へんな使い方
実はPOSTメソッドも使える
散々既出な話ですが、file_get_contentsはコンテキストを詳細に設定することでPOSTメソッドでリクエストすることもできます。
$context = stream_context_create(array(
"http" => array(
'method' => 'POST',
'header' => implode("\r\n", array(
'Content-Type: application/x-www-form-urlencoded',
)),
'content' => http_bulid_query(array(
'foo' => 'bar',
'hoge' => 'fuga',
)),
)
));
$res = file_get_contents('http://example.com/', false, $context);
トラブルシューティング
HTTPS周りで不自然なエラーがでるときはエラーを抑制
PHP: file_get_contents - Manual
IIS のような、いくつかの標準に 対応してない Web サーバは、PHP に警告を発生させるような手順でデータを送信します。 このようなサーバを使用する場合は、error_reporting を警告を発生しないレベルまで小さくする必要があります。 PHP 4.3.7 以降では、https:// ラッパーでストリームをオープンする際に バグがある IIS サーバソフトウエアを検出することができ、この警告を抑制することができます。 あなたが ssl:// ソケットを作成するために fsockopen() を使用している場合、 自らこの警告を検出し、抑制する必要があります。
ボディは取得できるので、file_get_contents自体はエラーを抑制し、レスポンスヘッダーを元にエラー処理を切り分けて実装するのが望ましいんじゃないでしょうか。
根本的に動作しないときはallow_url_fopenがOnか確認
file_get_contentsでURLを直接開く場合は、allow_url_fopenディレクティブがONになっている必要があります。共用サーバーなどで、よほど意図した設定がされていなければ、あまり気にするところではありません。
allow_url_fopen = On
参考
- PHP: file_get_contents - Manual
- PHP: HTTP と HTTPS - Manual
- HTTP ストリーム ignore_errors オプション in PHP 5.3 - 親方、空から覚え書きが!
- file_get_contentsでPOSTデータ送信 - PHPはやれば出来る子