2016/04/23 11:56:56

PHPのfile_get_contentでエラー回避してステータスコードを取得してみる


Warning: Attempt to read property "post_excerpt" on null in /home/kpkyvkzp/public_html/unskilled.site/wp-content/themes/unskilled2/content-header-eyecatch.php on line 5
目次(クリックするとジャンプします)
  • 1:file_get_contents便利ですよね
  • 2:エラーを回避する
  • 2.1:存在しないURLの場合…
  • 2.2:コンテキストを与える
  • 2.3:ステータスコードを取得してみる
  • 2.4:簡単な条件分岐
  • 3:まとめ

file_get_contents便利ですよね

ただfile_get_contentsは素で使うと、400系や500系のステータスコードを受けた場合にエラーが出てしまいます。

エラーとなるとハンドリングが難しくなるので、できればステータスコードを受けて自分で処理したいですよね。

エラーを回避する

これはfile_get_contentsにコンテキストを与えることで実現できます。

コンテキストとは脈絡とか筋道とか言う意味ですが、今回の場合はオプション的な感覚で捉えてもらって構わないと思います。

存在しないURLの場合…

<?php
//存在しないURL
file_get_contents("http://hogehoge.com/hoge/");¬

このように E_WARNING レベルのエラーになります。

PHP Warning:  file_get_contents(http://hogehoge.com/hoge/): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found
 in /home/pecodrive/sandbox/file.php on line 3

これではこの後に処理が続いている場合、処理が止まってしまう可能性があります。

コンテキストを与える

ステータスコードが400系や500系の場合でもきっちりレスポンスを受けるには先に説明したとおり、コンテキストを使います。

<?php
$context = stream_context_create(
        [
            "http"=>
            [
                "ignore_errors"=>true
            ]
        ]
);
file_get_contents("http://hogehoge.com/hoge/", false, $context);

stream_context_create関数でコンテキストを作成します。エラーを回避するのはhttpignore_errorsという設定をtrueにします。文字通りエラーを拒否するという設定です。

このコードを実行すると、エラーは出ません。存在しないURLなのでデータは取れないですが、エラーで止まることはなくなります。

ステータスコードを取得してみる

今度はステータスコードを取得してみます。

PHPではいくつかの定義済み変数がありますが、ステータスコードを取得するには$http_response_headerという変数を使います。

この変数にはfile_get_contents実行後にレスポンスヘッダが入ります。この変数を活用することでステータスコードの取得、ハンドリングが可能になります。

ちょっと$http_response_headerの中身を見てみます。

<?php
$context = stream_context_create(
        [
            "http"=>
            [
                "ignore_errors"=>true
            ]
        ]
);
file_get_contents("http://hogehoge.com/hoge/", false, $context);
var_dump($http_response_header);

このようにレスポンスヘッダが配列で格納されています。なぜ連想配列じゃないのか不思議ですがここからステータスコードを取得することが可能です。

array(6) {
  [0]=>
  string(22) "HTTP/1.1 404 Not Found"
  [1]=>
  string(35) "Date: Sat, 23 Apr 2016 02:00:15 GMT"
  [2]=>
  string(21) "Server: Apache/2.2.29"
  [3]=>
  string(19) "Content-Length: 203"
  [4]=>
  string(17) "Connection: close"
  [5]=>
  string(43) "Content-Type: text/html; charset=iso-8859-1"
}

残念ながら数字としてのステータスコード単体で収められている訳ではないので、何らかの方法で引きぬく必要があります。

簡単な条件分岐

ステータスコードを引き抜いて、簡単な条件分岐をつくってみました。基本的にはこんな感じでステータスコードによる分岐が可能です。

例外を投げたり、ステータスコードコードによっては再施行してみたりという処理も考えられます。

このコードの出力は以下のようになります。URLをいろいろ変えてみると挙動がわかり易かと思います。

Status Code : 404
Client Error

まとめ

意外となんにも考えなくても簡単に使えるfile_get_contentsですが、コンテキストを与えるとより便利になります。

今回はignore_errorsに関してでしたが、postgetなどメソッドの指定やデータの定義などもコンテキストで行うこともできます。curl等と同じような使い方ができるんですね。

  • file_get_contentsはコンテキストでいろいろ設定できる
  • エラーを回避したい場合はignore_errorstrueに設定する
  • 定義済み変数$http_response_headerからレスポンスヘッダを取得できる
  • 正規表現等を遣う必要があるが、レスポンスコードを引き抜くことも可能
  • ステータスコードによる分岐処理も可能