php curlをつかったオリジナルクラス (myCurlRequest)
最近ハヤリの色々なAPIを使った(mashupした)サイトを遊びで作る際に、
いつもAPI呼び出しのHTTP接続の部分を適当に汎用性なく都度書いちゃう非効率なこと
ばかりやってたんですが、今回多少気合いを入れて汎用的なオリジナルクラスを書いてみました。
方針は
1. 接続コアな部分ははcurlに任せる
2. 複数のリクエストもまとめて処理できるようにする
3. データの取得はAPIの応答がいずれにせよPHPのarrayまでクラス内で変換してしまう
4. APIの応答形式はとりあえず、XMLとPHP Serializeを対応する
5. curl_multi ってのを使ってみたいので 直列/並列問い合わせどちらでもできるようにする
という感じにする。
1. 接続コアな部分ははcurlに任せる
これは前からこの手の処理はcurlで接続していたので引き続き。 (curlは安定して早いからおすすめです)
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$receiveData = curl_exec($curl);
curl_close($curl);
基本を超簡単に書くとこんな感じですね。
2. 複数のリクエストもまとめて処理できるようにする
単一のリクエスト受信のクラスを作っても結局、サービスを作る際はあれやこれやで複数の問い合わせを
1ユーザリクエストで行うわけで、そうなると外側でそのクラスを繰り返し呼んで... となるのでその辺が
楽になれば良いかなと。
3. データの取得はAPIの応答がいずれにせよPHPのarrayまでクラス内で変換してしまう
これは、取得後の内部処理を考えると必須かなと
4. APIの応答形式はとりあえず、XMLとPHP Serializeを対応する
XMLだけでもいいけど、とりあえず複数応答できる拡張性をクラスに実装するためにそうする
XML to Array 変換は本来なら追加のpackage不要としたいのだけど、今回は pear:: XML/unserializer を使う。
5. curl_multi ってのを使ってみたいので 直列/並列問い合わせどちらでもできるようにする
複数のリクエストを直列に行うとどうしても時間がかかる. どうせなら curl_multi って拡張が
curlにあるようなので、それを使ってみる。が、curl_multi に関するドキュメントが乏しい。。
色々調べた結果、以下のようにすることが基本らしい
// Curlの並列処理用のチャンネルの初期化
$curlmulti = curl_multi_init();
for(;;) {
// 個々のリクエストのcurlチャンネルの登録
$curl_n = curl_init();
curl_setopt ($curl, CURLOPT_URL, $url_n);
curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
//並列処理用のチャンネルに登録
curl_multi_add_handle($curlmulti, $curl_n);
}
// 並列にリクエストの実行. すべてのリクエストが受信するまでwait
do {
$n=curl_multi_exec($curlmulti, $active);
} while ($active);
// 個々の受信データの取得
$receive_data_n = curl_multi_getcontent($curl_n);
で、色々と考えて、クラスの設計を以下のような形にすることにした
クラス名 - myCurlRequest
メソッド
myCurlRequest() - コンストラクタ
init() - 初期化関数(コンストラクト時には自動で呼ばれる), インスタンスの使い回しの際に利用
addRequest($label, $url, $type = "xml") - リクエスト登録用関数 ($label:識別(任意)文字列, $url:リクエストURL, $type:受信形式(XML or php)
execute() - 直列 でのリクエストの実行
executeMulti() - 並列 でのリクエストの実行
getData() - リクエスト結果の取得
getInfo() - 処理状況の詳細の取得
実装したクラスを利用したアプリはこんな感じで複数のAPIをマッシュアップする準備が
簡単に整う。このまま smartyに突っ込んでも良いぐらい。
<¥?php
require_once('myCurlRequest.php');// newして
$myCurl = new myCurlRequest();// はてな人気のエントリーRSS
$myCurl->addRequest('hatebu', 'http://b.hatena.ne.jp/hotentry?mode=rss');
// Livedoor Weather Hacks 東京の天気
$myCurl->addRequest('ldoorweather', 'http://weather.livedoor.com/forecast/rss/13/63.xml');
// Yahoo!JAPAN検索API
$myCurl->addRequest('yjweb', 'http://api.search.yahoo.co.jp/WebSearchService/V1/webSearch?appid=
hiyuzawa&query=%e6%b2%96%e7%b8%84&results=2');
// Yahoo!INC画像検索API (PHP-Serialize応答版)
$myCurl->addRequest('yincimg', 'http://search.yahooapis.com/ImageSearchService/V1/imageSearch?ap
pid=hiyuzawa&query=Madonna&results=2&output=php');// 実行!(これは並列 直列は execute() )
$myCurl->executeMulti();// Data取り出して
$data = $myCurl->getData();// あとはお好きに..
print_r($data);
?>
直列処理と並列処理のパフォーマンスの違い
各リクエストを受信するまでの応答時間を time_1, time_2, ... time_n とすると
直列処理の場合の全体にかかる時間は
sum(time_1..n) + α
であり、並列処理の場合は
max(time_1..n) + α
なので、これがちゃんとできているかを上のサンプルプログラムを用いて検証してみた。
直列(execute()を利用)の場合
hatebu-0.455799
ldoorweather-0.261679
yjweb-0.253485
yincimg-0.688531
Total - 1.729500 (sec)
並列(executeMulti()を利用)の場合
hatebu-0.760833
ldoorweather-0.522466
yjweb-0.534036
yincimg-0.773258
Total - 0.838719 (sec)
たしかにその通りに動いている。
ToDo:
- noResponse時のハンドリング (timeout制御の導入)
- fail時のリトライ
- etc..
で肝心のクラスのソースはこれ↓
myCurlRequest.php
突貫なので醜い部分は多々あり。
さて、これを使って何か作るぞ!とおもったら、さくらインターネットの標準がPHP4だった。。。PHP4では curl_multi 使えない。 自分でPHP5入れるかorz..
トラックバック(0)
このブログ記事を参照しているブログ一覧: php curlをつかったオリジナルクラス (myCurlRequest)
このブログ記事に対するトラックバックURL: http://hiyuzawa.jpn.org/MT-4.0-ja/mt-tb.cgi/35

HotPepperAPIとGoogle/YahooMapAPIと連動させたアプリ。
■FlashImageSearch

flashで見る画像検索。アイドルデータベースと連動。
■FindJob転職情報メール一気読み

FindJobから定期的に送られてくる転職情報メールを一気に確認するためのTool。
■新着pickup

Yahoo!の新着ピックアップサイトをサムネイル付きで表示。自動更新。
■AU-GPS with Gmap

AU携帯電話をGPSとして利用.GoogleMapで行動を表示.製作記録まとめ中!!
■finding_yado

じゃらんAPIを使った宿探しサイト.リクルートMashupコンテスト応募作品
■オークション商品分析Tool

Y!オクAPIを使って多角的に商品を表示。Flashにて
■Yahoo!Directory with History

FlashでY!カテゴリをブラウズ.登録日時も合わせてビジアル表示.
■Okiny-Flash-Search

Yahoo!検索APIを用いてflash上で検索.ソフトウエアキーボドや検索語Suggest,人気語なども表示.
■Okiny-Search

YahooUILibraryのEffectとYahoo!検索APIを組み合わせた面白い検索結果の表示方法を体験.
■Quick-Dictonary

firefoxのGrasemonkeyを使ってウエブ上の単語(英語/日本語)を簡単に単語翻訳
■サーバサイドブックマーク

環境やブラウザに問わずどこでも自分のブックマークがみれるTool. タグによる保存も..本人はてぶ使ってますorz...
■myweb-bookmark/search

ウエブ/画像/Q&A/Amazon/Blogみんな一度に検索しちゃいます
■myweb-bookmark

ウエブ/Q&A/Amazon/BlogみんなでブックマークしちゃうTool.
--形にまだなってないやつ--
■地域スポット(観光地)登録
位置情報とコンテンツ情報を登録しておくといいことあるかも...
■国土数値情報ウエブサービス化
ダウンロードしてGoogleMapに重ねてみました...
