動かざることバグの如し

近づきたいよ 君の理想に

【PHP】file_get_contentsでエラーの分岐

file_get_contentsは非常に便利なPHPメソッドでたった一行で外部URLを取得できる

が、しかし存在しないURLだったとかサーバーエラーとかの例外に弱い

<?php
$a = file_get_contents("http://hogehoge.com/hoge/");
var_dump($a);
?>
PHP Warning:  file_get_contents(http://hogehoge.com/hoge/): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found
 in /workspace/Main.php on line 2

うーんこの Warningだから例外キャッチすら出来ないし。。

しかも失敗した場合は必ずfalseを返すからなんで失敗したのかがわからない

どうにかする方法ないのか迷って公式ドキュメント見てたら追加オプションあった

http://php.net/manual/ja/function.file-get-contents.php

ソース

<?php

$context = stream_context_create(array(
  'http' => array('ignore_errors' => true)
));
$response = file_get_contents("http://thr3a.hatenablog.com/", false, $context);
preg_match("/[0-9]{3}/", $http_response_header[0], $stcode);
switch ($stcode[0]) {
  case '200':
    // 200の場合
    var_dump($response);
  break;
  case "404":
    // 404の場合
    echo 404;
  break;
  case '500':
    echo '500';
  default:
  break;
}

?>
  • ignore_errors コンテキストを true にすることで、ステータスコードが 4xx や 5xx でも Warnning エラーが発生せずレスポンスを受け取れるようになる
  • PHPらしいというかなんというか、変数$http_response_headerにレスポンスヘッダが自動的に格納される。ステータスコードは配列の最初
  • ステータスコードをそのままくれるわけがないので正規表現で分解して分岐

ちなみに$http_response_headerにセットされる内容

array(17) {
  [0]=>
  string(15) "HTTP/1.1 200 OK"
  [1]=>
  string(22) "Cache-Control: private"
  [2]=>
  string(38) "Content-Type: text/html; charset=utf-8"
  [3]=>
  string(35) "Date: Wed, 11 May 2016 02:18:31 GMT"
  [4]=>
  string(46) "ETag: 64326b20fcb4d9760340241d4ebaf02486a44adc"
  [5]=>
  string(29) "P3P: CP="OTI CUR OUR BUS STA""
  [6]=>
  string(13) "Server: nginx"
  [7]=>
  string(21) "Vary: Accept-Encoding"
  [8]=>
  string(16) "Vary: User-Agent"
  [9]=>
  string(31) "X-Content-Type-Options: nosniff"
  [10]=>
  string(44) "X-Dispatch: Hatena::Epic::Blogs::Index#index"
  [11]=>
  string(21) "X-Frame-Options: DENY"
  [12]=>
  string(17) "X-Page-Cache: hit"
  [13]=>
  string(44) "X-Revision: e3bc98968a1b8d0768bdf3807d7cf5ff"
  [14]=>
  string(19) "X-Runtime: 0.013142"
  [15]=>
  string(19) "X-XSS-Protection: 1"
  [16]=>
  string(17) "Connection: Close"
}