2011年4月1日金曜日

PHPで 簡単にGET / POSTできるように file_get_contents()を拡張する

file_get_contents()は便利だが、POSTとかエラー対応とかは少し面倒なので、手軽に使えるようにラップしてみた。
PHPのバージョンは5.2.10以降または5.3.0以降が対象。

function file_http(
    $url,
    $params = null,    //パラメータがあれば配列で渡す
    $method = 'GET',    //GET or POST
    &$status = null,    //参照渡しでレスポンスのHTTP Status Codeを返す
    &$http_response_header = null,    //参照渡しでレスポンスのHTTP Headerの配列を返す
    $request_header = array()    //追加したいリクエストのHTTP Headerがあれば
) {
  
    $opt = array(
        'method' => $method,
        'header' => (array)$request_header,    //PHP 5.2.10 / 5.3.0 以降は配列でもOK
        'ignore_errors' => true,    //PHP 5.2.10 / 5.3.0 以降で有効
    );
  
    if ($params) {
        $query_string = http_build_query($params);
      
        if ($method === 'GET') {
            $url .= '?' . $query_string;
        } else {    //POSTの場合
            $opt['header'][] = 'Content-type: application/x-www-form-urlencoded';
            $opt['content'] = $query_string;
        }
    }
  
    $res = file_get_contents($url, false, stream_context_create(array('http' => $opt)));
  
    //レスポンスのHTTP Headerは$http_response_headerにセットされている
    if (is_array($http_response_header)) {
        preg_match('@^HTTP/1\\.. ([0-9]{3}) @i', $http_response_header[0], $matches);
        $status = $matches[1];
    }
  
    return $res;
}

使用例
$res = file_http(
    'http://localhost/test.php',
    array('foo' => 'テスト'),
    'POST',
    $status,
    $responseHeaders,
    array('User-Agent: ゆーざーえーじぇんと', 'Referer: りふぁら')    // 1つだけの場合は文字列でもOK
);

echo $status;    // => "200"
var_dump($responseHeaders);

実際に使う場合には結果の判断等でレスポンスのHTTPステータスコードが欲しい場合があるので、パラメータの参照渡しで取得できるようにした。
そしてステータスコード以外のHTTP Headerを参照したいケースもあるので、これも参照渡しで配列として取得できるようにした。

また、ignore_errorsを指定することにより、レスポンスのHTTPステータスコードが400以上でもWarningを出さない、かつレスポンスのBodyを取得できるようにした。(参考:[メモ] PHPのfile_get_contentsを、HTTPリクエストに使うときのTIPS ::ハブろぐ
ただしホスト名の名前解決ができない場合はその手前でWarningが出てしまうので、PHPで URLのホスト名(ドメイン)が存在するかチェックする方法のような対応が必要。


以下は余談。
普段は変数名等はcamelCaseにするのだが、$http_response_header等に引っ張られてアンダーバー繋ぎにしてみた。
関数名は、
  • http_request
  • http_get
  • httpRequest
などを考えたのだが、どれもPECLで既に使われているので諦めた。

0 件のコメント:

ブログ アーカイブ

tags